]> git.saurik.com Git - apple/system_cmds.git/blob - trace.tproj/trace.c
system_cmds-550.6.tar.gz
[apple/system_cmds.git] / trace.tproj / trace.c
1 /*
2 cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -arch x86_64 -arch i386 -O -o trace trace.c
3 */
4
5
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sys/file.h>
9 #include <sys/socket.h>
10 #include <sys/stat.h>
11 #include <sys/ioctl.h>
12 #include <sys/mbuf.h>
13 #include <sys/mman.h>
14 #include <sys/ucred.h>
15 #include <sys/time.h>
16 #include <sys/proc.h>
17 #include <sys/ptrace.h>
18 #include <sys/sysctl.h>
19 #include <sys/wait.h>
20 #include <sys/resource.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <paths.h>
28 #include <err.h>
29
30 #include <libutil.h>
31
32 #include <sys/kdebug.h>
33
34 #include <mach/mach.h>
35 #include <mach/mach_time.h>
36
37
38 int nbufs = 0;
39 int enable_flag=0;
40 int execute_flag=0;
41 int logRAW_flag=0;
42 int LogRAW_flag=0;
43 int readRAW_flag = 0;
44 int disable_flag=0;
45 int init_flag=0;
46 int kval_flag=0;
47 int remove_flag=0;
48 int bufset_flag=0;
49 int bufget_flag=0;
50 int class_flag=0;
51 int subclass_flag=0;
52 int trace_flag=0;
53 int nowrap_flag=0;
54 int freerun_flag=0;
55 int verbose_flag=0;
56 int pid_flag=0;
57 int pid_exflag=0;
58 int ppt_flag=0;
59 unsigned int class=0;
60 unsigned int class2=0;
61 unsigned int subclass=0;
62 unsigned int value1=0;
63 unsigned int value2=0;
64 unsigned int value3=0;
65 unsigned int value4=0;
66 pid_t pid=0;
67 int reenable=0;
68
69 int force_32bit_exec = 0;
70 int frequency = 0;
71
72 int mib[6];
73 size_t needed;
74
75 char *logfile = (char *)0; /* This file is trace format */
76 char *RAW_file = (char *)0;
77 FILE *output_file;
78 int output_fd;
79
80 extern char **environ;
81
82
83 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
84 #define DBG_FUNC_MASK 0xfffffffc
85 #define SHORT_HELP 1
86 #define LONG_HELP 0
87
88 #define CSC_MASK 0xffff0000
89
90 #define VFS_LOOKUP 0x03010090
91 #define BSC_exit 0x040c0004
92 #define BSC_thread_terminate 0x040c05a4
93 #define TRACE_DATA_NEWTHREAD 0x07000004
94 #define TRACE_STRING_NEWTHREAD 0x07010004
95 #define TRACE_STRING_EXEC 0x07010008
96 #define TRACE_LOST_EVENTS 0x07020008
97 #define MACH_SCHEDULED 0x01400000
98 #define MACH_MAKERUNNABLE 0x01400018
99 #define MACH_STKHANDOFF 0x01400008
100
101 #define EMPTYSTRING ""
102 #define UNKNOWN "unknown"
103
104 char tmpcommand[MAXCOMLEN];
105
106 int total_threads = 0;
107 int nthreads = 0;
108 kd_threadmap *mapptr = 0;
109
110 /*
111 If NUMPARMS changes from the kernel,
112 then PATHLENGTH will also reflect the change
113 This is for the vfslookup entries that
114 return pathnames
115 */
116 #define NUMPARMS 23
117 #define PATHLENGTH (NUMPARMS*sizeof(long))
118
119
120 #define US_TO_SLEEP 50000
121 #define BASE_EVENTS 500000
122
123
124 double divisor;
125
126 typedef struct {
127 uint32_t debugid;
128 char *debug_string;
129 } code_type_t;
130
131 code_type_t * codesc = 0;
132
133
134 typedef struct event *event_t;
135
136 struct event {
137 event_t ev_next;
138
139 uintptr_t ev_thread;
140 uint32_t ev_debugid;
141 uint64_t ev_timestamp;
142 };
143
144 typedef struct lookup *lookup_t;
145
146 struct lookup {
147 lookup_t lk_next;
148
149 uintptr_t lk_thread;
150 uintptr_t lk_dvp;
151 long *lk_pathptr;
152 long lk_pathname[NUMPARMS + 1];
153 };
154
155 typedef struct threadmap *threadmap_t;
156
157 struct threadmap {
158 threadmap_t tm_next;
159
160 uintptr_t tm_thread;
161 uintptr_t tm_pthread;
162 boolean_t tm_deleteme;
163 char tm_command[MAXCOMLEN + 1];
164 };
165
166
167 #define HASH_SIZE 1024
168 #define HASH_MASK 1023
169
170 event_t event_hash[HASH_SIZE];
171 lookup_t lookup_hash[HASH_SIZE];
172 threadmap_t threadmap_hash[HASH_SIZE];
173
174 event_t event_freelist;
175 lookup_t lookup_freelist;
176 threadmap_t threadmap_freelist;
177 threadmap_t threadmap_temp;
178
179
180 #define SBUFFER_SIZE (128 * 4096)
181 char sbuffer[SBUFFER_SIZE];
182
183 int secs_to_run = 0;
184 int use_current_buf = 0;
185
186
187 kbufinfo_t bufinfo = {0, 0, 0, 0};
188
189 int codenum = 0;
190 int codeindx_cache = 0;
191 char codefile[] = "codes";
192 char *cfile = (char *)0;
193
194
195 static void quit(char *);
196 static int match_debugid(unsigned int, char *, int *);
197 static void usage(int short_help);
198 static int argtoi(int flag, char *req, char *str, int base);
199 static int parse_codefile(char *filename);
200 static int read_command_map(int, int);
201 static void find_thread_command(kd_buf *, char **);
202 static void create_map_entry(uintptr_t, char *);
203 static void getdivisor();
204 static unsigned long argtoul();
205
206 static void set_enable(int);
207 static void set_remove();
208 static void set_nowrap();
209 static void set_pidcheck(int, int);
210 static void set_pidexclude(int, int);
211 static void set_numbufs(int);
212 static void set_freerun();
213 static void get_bufinfo(kbufinfo_t *);
214 static void set_init();
215 static void set_class();
216 static void set_kval_list();
217 static void set_subclass();
218 static void readtrace(char *);
219 static void log_trace();
220 static void Log_trace();
221 static void read_trace();
222 static void signal_handler(int);
223 static void signal_handler_RAW(int);
224 static void delete_thread_entry(uintptr_t);
225 static void find_and_insert_tmp_map_entry(uintptr_t, char *);
226 static void create_tmp_map_entry(uintptr_t, uintptr_t);
227 static void find_thread_name(uintptr_t, char **, boolean_t);
228
229 static int writetrace(int);
230 static int write_command_map(int);
231 static int debugid_compar(code_type_t *, code_type_t *);
232
233 static threadmap_t find_thread_entry(uintptr_t);
234
235
236
237 #ifndef KERN_KDWRITETR
238 #define KERN_KDWRITETR 17
239 #endif
240
241 #ifndef KERN_KDWRITEMAP
242 #define KERN_KDWRITEMAP 18
243 #endif
244
245 #ifndef F_FLUSH_DATA
246 #define F_FLUSH_DATA 40
247 #endif
248
249 #ifndef RAW_VERSION1
250 typedef struct {
251 int version_no;
252 int thread_count;
253 uint64_t TOD_secs;
254 uint32_t TOD_usecs;
255 } RAW_header;
256
257 #define RAW_VERSION0 0x55aa0000
258 #define RAW_VERSION1 0x55aa0101
259 #endif
260
261
262 RAW_header raw_header;
263
264
265
266 void set_enable(int val)
267 {
268 mib[0] = CTL_KERN;
269 mib[1] = KERN_KDEBUG;
270 mib[2] = KERN_KDENABLE;
271 #ifdef KDEBUG_ENABLE_PPT
272 if (ppt_flag && val) {
273 mib[3] = KDEBUG_ENABLE_PPT;
274 } else {
275 mib[3] = val;
276 }
277 #else
278 mib[3] = val;
279 #endif
280 mib[4] = 0;
281 mib[5] = 0;
282 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
283 quit("trace facility failure, KERN_KDENABLE\n");
284 }
285
286 void set_remove()
287 {
288 extern int errno;
289
290 errno = 0;
291
292 mib[0] = CTL_KERN;
293 mib[1] = KERN_KDEBUG;
294 mib[2] = KERN_KDREMOVE;
295 mib[3] = 0;
296 mib[4] = 0;
297 mib[5] = 0;
298 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
299 {
300 if (errno == EBUSY)
301 quit("the trace facility is currently in use...\n fs_usage, sc_usage, trace, and latency use this feature.\n\n");
302 else
303 quit("trace facility failure, KERN_KDREMOVE\n");
304 }
305 }
306
307 void set_numbufs(int nbufs)
308 {
309 mib[0] = CTL_KERN;
310 mib[1] = KERN_KDEBUG;
311 mib[2] = KERN_KDSETBUF;
312 mib[3] = nbufs;
313 mib[4] = 0;
314 mib[5] = 0;
315 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
316 quit("trace facility failure, KERN_KDSETBUF\n");
317
318 mib[0] = CTL_KERN;
319 mib[1] = KERN_KDEBUG;
320 mib[2] = KERN_KDSETUP;
321 mib[3] = 0;
322 mib[4] = 0;
323 mib[5] = 0;
324 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
325 quit("trace facility failure, KERN_KDSETUP\n");
326 }
327
328 void set_nowrap()
329 {
330 mib[0] = CTL_KERN;
331 mib[1] = KERN_KDEBUG;
332 mib[2] = KERN_KDEFLAGS;
333 mib[3] = KDBG_NOWRAP;
334 mib[4] = 0;
335 mib[5] = 0; /* no flags */
336 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
337 quit("trace facility failure, KDBG_NOWRAP\n");
338
339 }
340
341 void set_pidcheck(int pid, int on_off_flag)
342 {
343 kd_regtype kr;
344
345 kr.type = KDBG_TYPENONE;
346 kr.value1 = pid;
347 kr.value2 = on_off_flag;
348 needed = sizeof(kd_regtype);
349 mib[0] = CTL_KERN;
350 mib[1] = KERN_KDEBUG;
351 mib[2] = KERN_KDPIDTR;
352 mib[3] = 0;
353 mib[4] = 0;
354 mib[5] = 0;
355 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
356 {
357 if (on_off_flag == 1)
358 {
359 printf("trace facility failure, KERN_KDPIDTR,\n\tpid %d does not exist\n", pid);
360 set_remove();
361 exit(2);
362 }
363 }
364 }
365
366 void set_pidexclude(int pid, int on_off_flag)
367 {
368 kd_regtype kr;
369
370 kr.type = KDBG_TYPENONE;
371 kr.value1 = pid;
372 kr.value2 = on_off_flag;
373 needed = sizeof(kd_regtype);
374 mib[0] = CTL_KERN;
375 mib[1] = KERN_KDEBUG;
376 mib[2] = KERN_KDPIDEX;
377 mib[3] = 0;
378 mib[4] = 0;
379 mib[5] = 0;
380 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
381 {
382 if (on_off_flag == 1)
383 {
384 printf ("pid %d does not exist\n", pid);
385 set_remove();
386 exit(2);
387 }
388 }
389 }
390
391 void set_freerun()
392 {
393 mib[0] = CTL_KERN;
394 mib[1] = KERN_KDEBUG;
395 mib[2] = KERN_KDEFLAGS;
396 mib[3] = KDBG_FREERUN;
397 mib[4] = 0;
398 mib[5] = 0;
399 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
400 quit("trace facility failure, KDBG_FREERUN\n");
401 }
402
403 void get_bufinfo(kbufinfo_t *val)
404 {
405 needed = sizeof (*val);
406 mib[0] = CTL_KERN;
407 mib[1] = KERN_KDEBUG;
408 mib[2] = KERN_KDGETBUF;
409 mib[3] = 0;
410 mib[4] = 0;
411 mib[5] = 0;
412 if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
413 quit("trace facility failure, KERN_KDGETBUF\n");
414 }
415
416 void set_init()
417 {
418 kd_regtype kr;
419
420 kr.type = KDBG_RANGETYPE;
421 kr.value1 = 0;
422 kr.value2 = -1;
423 needed = sizeof(kd_regtype);
424 mib[0] = CTL_KERN;
425 mib[1] = KERN_KDEBUG;
426 mib[2] = KERN_KDSETREG;
427 mib[3] = 0;
428 mib[4] = 0;
429 mib[5] = 0;
430 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
431 quit("trace facility failure, KERN_KDSETREG (rangetype)\n");
432
433 mib[0] = CTL_KERN;
434 mib[1] = KERN_KDEBUG;
435 mib[2] = KERN_KDSETUP;
436 mib[3] = 0;
437 mib[4] = 0;
438 mib[5] = 0;
439 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
440 quit("trace facility failure, KERN_KDSETUP\n");
441 }
442
443
444 void set_class()
445 {
446 kd_regtype kr;
447
448 kr.type = KDBG_CLASSTYPE;
449 kr.value1 = class;
450 kr.value2 = class2;
451 needed = sizeof(kd_regtype);
452 mib[0] = CTL_KERN;
453 mib[1] = KERN_KDEBUG;
454 mib[2] = KERN_KDSETREG;
455 mib[3] = 0;
456 mib[4] = 0;
457 mib[5] = 0;
458 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
459 quit("trace facility failure, KERN_KDSETREG (classtype)\n");
460 }
461
462 void set_kval_list()
463 {
464 kd_regtype kr;
465
466 kr.type = KDBG_VALCHECK;
467 kr.value1 = value1;
468 kr.value2 = value2;
469 kr.value3 = value3;
470 kr.value4 = value4;
471 needed = sizeof(kd_regtype);
472 mib[0] = CTL_KERN;
473 mib[1] = KERN_KDEBUG;
474 mib[2] = KERN_KDSETREG;
475 mib[3] = 0;
476 mib[4] = 0;
477 mib[5] = 0;
478 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
479 quit("trace facility failure, KERN_KDSETREG (valcheck)\n");
480 }
481
482 void set_subclass()
483 {
484 kd_regtype kr;
485
486 kr.type = KDBG_SUBCLSTYPE;
487 kr.value1 = class;
488 kr.value2 = subclass;
489 needed = sizeof(kd_regtype);
490 mib[0] = CTL_KERN;
491 mib[1] = KERN_KDEBUG;
492 mib[2] = KERN_KDSETREG;
493 mib[3] = 0;
494 mib[4] = 0;
495 mib[5] = 0;
496 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
497 quit("trace facility failure, KERN_KDSETREG (subclstype)\n");
498 }
499
500
501 void readtrace(char *buffer)
502 {
503 mib[0] = CTL_KERN;
504 mib[1] = KERN_KDEBUG;
505 mib[2] = KERN_KDREADTR;
506 mib[3] = 0;
507 mib[4] = 0;
508 mib[5] = 0;
509
510 if (sysctl(mib, 3, buffer, &needed, NULL, 0) < 0)
511 quit("trace facility failure, KERN_KDREADTR\n");
512 }
513
514
515 int writetrace(int fd)
516 {
517 mib[0] = CTL_KERN;
518 mib[1] = KERN_KDEBUG;
519 mib[2] = KERN_KDWRITETR;
520 mib[3] = fd;
521 mib[4] = 0;
522 mib[5] = 0;
523
524 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
525 return 1;
526
527 return 0;
528 }
529
530
531 int write_command_map(int fd)
532 {
533 mib[0] = CTL_KERN;
534 mib[1] = KERN_KDEBUG;
535 mib[2] = KERN_KDWRITEMAP;
536 mib[3] = fd;
537 mib[4] = 0;
538 mib[5] = 0;
539
540 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
541 return 1;
542
543 return 0;
544 }
545
546
547 static
548 lookup_t handle_lookup_event(uintptr_t thread, int debugid, kd_buf *kdp)
549 {
550 lookup_t lkp;
551 int hashid;
552 boolean_t first_record = FALSE;
553
554 hashid = thread & HASH_MASK;
555
556 if (debugid & DBG_FUNC_START)
557 first_record = TRUE;
558
559 for (lkp = lookup_hash[hashid]; lkp; lkp = lkp->lk_next) {
560 if (lkp->lk_thread == thread)
561 break;
562 }
563 if (lkp == NULL) {
564 if (first_record == FALSE)
565 return (0);
566
567 if ((lkp = lookup_freelist))
568 lookup_freelist = lkp->lk_next;
569 else
570 lkp = (lookup_t)malloc(sizeof(struct lookup));
571
572 lkp->lk_thread = thread;
573
574 lkp->lk_next = lookup_hash[hashid];
575 lookup_hash[hashid] = lkp;
576 }
577
578 if (first_record == TRUE) {
579 lkp->lk_pathptr = lkp->lk_pathname;
580 lkp->lk_dvp = kdp->arg1;
581 } else {
582 if (lkp->lk_pathptr > &lkp->lk_pathname[NUMPARMS-4])
583 return (lkp);
584
585 *lkp->lk_pathptr++ = kdp->arg1;
586 }
587 *lkp->lk_pathptr++ = kdp->arg2;
588 *lkp->lk_pathptr++ = kdp->arg3;
589 *lkp->lk_pathptr++ = kdp->arg4;
590 *lkp->lk_pathptr = 0;
591
592 return (lkp);
593 }
594
595
596 static
597 void delete_lookup_event(uintptr_t thread, lookup_t lkp_to_delete)
598 {
599 lookup_t lkp;
600 lookup_t lkp_prev;
601 int hashid;
602
603 hashid = thread & HASH_MASK;
604
605 if ((lkp = lookup_hash[hashid])) {
606 if (lkp == lkp_to_delete)
607 lookup_hash[hashid] = lkp->lk_next;
608 else {
609 lkp_prev = lkp;
610
611 for (lkp = lkp->lk_next; lkp; lkp = lkp->lk_next) {
612 if (lkp == lkp_to_delete) {
613 lkp_prev->lk_next = lkp->lk_next;
614 break;
615 }
616 lkp_prev = lkp;
617 }
618 }
619 if (lkp) {
620 lkp->lk_next = lookup_freelist;
621 lookup_freelist = lkp;
622 }
623 }
624 }
625
626
627 static
628 void insert_start_event(uintptr_t thread, int debugid, uint64_t now)
629 {
630 event_t evp;
631 int hashid;
632
633 hashid = thread & HASH_MASK;
634
635 for (evp = event_hash[hashid]; evp; evp = evp->ev_next) {
636 if (evp->ev_thread == thread && evp->ev_debugid == debugid)
637 break;
638 }
639 if (evp == NULL) {
640 if ((evp = event_freelist))
641 event_freelist = evp->ev_next;
642 else
643 evp = (event_t)malloc(sizeof(struct event));
644
645 evp->ev_thread = thread;
646 evp->ev_debugid = debugid;
647
648 evp->ev_next = event_hash[hashid];
649 event_hash[hashid] = evp;
650 }
651 evp->ev_timestamp = now;
652 }
653
654
655 static
656 uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now)
657 {
658 event_t evp;
659 event_t evp_prev;
660 int hashid;
661 uint64_t elapsed = 0;
662
663 hashid = thread & HASH_MASK;
664
665 if ((evp = event_hash[hashid])) {
666 if (evp->ev_thread == thread && evp->ev_debugid == debugid)
667 event_hash[hashid] = evp->ev_next;
668 else {
669 evp_prev = evp;
670
671 for (evp = evp->ev_next; evp; evp = evp->ev_next) {
672
673 if (evp->ev_thread == thread && evp->ev_debugid == debugid) {
674 evp_prev->ev_next = evp->ev_next;
675 break;
676 }
677 evp_prev = evp;
678 }
679 }
680 if (evp) {
681 elapsed = now - evp->ev_timestamp;
682
683 evp->ev_next = event_freelist;
684 event_freelist = evp;
685 }
686 }
687 return (elapsed);
688 }
689
690
691 void
692 log_trace()
693 {
694 char *buffer;
695 uint32_t buffer_size;
696 int fd;
697 int size;
698 int pad_size;
699 char pad_buf[4096];
700
701
702 if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) {
703 perror("Can't open logfile");
704 exit(1);
705 }
706 get_bufinfo(&bufinfo);
707
708 if (bufinfo.nolog != 1) {
709 reenable = 1;
710 set_enable(0); /* disable logging*/
711 }
712 get_bufinfo(&bufinfo);
713
714 if (verbose_flag) {
715 if (bufinfo.flags & KDBG_WRAPPED)
716 printf("Buffer has wrapped\n");
717 else
718 printf("Buffer has not wrapped\n");
719 }
720 buffer_size = 1000000 * sizeof(kd_buf);
721 buffer = malloc(buffer_size);
722
723 if (buffer == (char *) 0)
724 quit("can't allocate memory for tracing info\n");
725
726 read_command_map(0, 0);
727
728 raw_header.version_no = RAW_VERSION1;
729 raw_header.thread_count = total_threads;
730 raw_header.TOD_secs = time((long *)0);
731 raw_header.TOD_usecs = 0;
732
733 write(fd, &raw_header, sizeof(RAW_header));
734
735 size = total_threads * sizeof(kd_threadmap);
736 write(fd, (char *)mapptr, size);
737
738 pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095);
739 memset(pad_buf, 0, pad_size);
740
741 write(fd, pad_buf, pad_size);
742
743 for (;;) {
744 needed = buffer_size;
745
746 readtrace(buffer);
747
748 if (needed == 0)
749 break;
750 write(fd, buffer, needed * sizeof(kd_buf));
751 }
752 close(fd);
753 }
754
755
756 void
757 Log_trace()
758 {
759 int size;
760 kd_buf kd_tmp;
761 size_t len;
762 int num_cpus;
763 int try_writetrace = 1;
764 int fd;
765 char *buffer;
766 kd_buf *kd;
767 uint64_t sample_window_abs;
768 uint64_t next_window_begins;
769 uint64_t current_abs;
770 uint64_t ending_abstime;
771 uint64_t last_time_written;
772 uint32_t us_to_sleep;
773 uint32_t us_to_adjust;
774 uint32_t ms_to_run;
775
776 memset(&kd_tmp, 0, sizeof(kd_tmp));
777
778 if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) {
779 perror("Can't open logfile");
780 exit(1);
781 }
782 if (use_current_buf == 0) {
783 /*
784 * grab the number of cpus and scale the buffer size
785 */
786 mib[0] = CTL_HW;
787 mib[1] = HW_NCPU;
788 mib[2] = 0;
789 len = sizeof(num_cpus);
790
791 sysctl(mib, 2, &num_cpus, &len, NULL, 0);
792
793 if (!bufset_flag)
794 nbufs = BASE_EVENTS * num_cpus;
795
796 set_remove();
797 set_numbufs(nbufs);
798 set_init();
799
800 if (class_flag)
801 set_class();
802
803 if (subclass_flag)
804 set_subclass();
805
806 if (kval_flag)
807 set_kval_list();
808 }
809 /* Get kernel buffer information */
810 get_bufinfo(&bufinfo);
811
812 buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf));
813 if (buffer == (char *) 0)
814 quit("can't allocate memory for tracing info\n");
815 memset(buffer, 0, bufinfo.nkdbufs * sizeof(kd_buf));
816
817 if (use_current_buf == 0)
818 set_enable(1);
819
820 if (write_command_map(fd)) {
821 int pad_size;
822 char pad_buf[4096];
823
824 read_command_map(0, 0);
825
826 raw_header.version_no = RAW_VERSION1;
827 raw_header.thread_count = total_threads;
828 raw_header.TOD_secs = time((long *)0);
829 raw_header.TOD_usecs = 0;
830
831 write(fd, &raw_header, sizeof(RAW_header));
832
833 size = total_threads * sizeof(kd_threadmap);
834 write(fd, (char *)mapptr, size);
835
836 pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095);
837 memset(pad_buf, 0, pad_size);
838
839 write(fd, pad_buf, pad_size);
840 }
841 sample_window_abs = (uint64_t)((double)US_TO_SLEEP * divisor);
842
843 next_window_begins = mach_absolute_time() + sample_window_abs;
844
845 if (secs_to_run) {
846 ending_abstime = mach_absolute_time() + (uint64_t)((double)secs_to_run * (double)1000000 * divisor);
847 ms_to_run = secs_to_run * 1000;
848 } else
849 ms_to_run = 0;
850 last_time_written = mach_absolute_time();
851
852 while (LogRAW_flag) {
853 current_abs = mach_absolute_time();
854
855 if (try_writetrace) {
856 needed = ms_to_run;
857
858 if (writetrace(fd))
859 try_writetrace = 0;
860 else {
861 if (needed) {
862 current_abs = mach_absolute_time();
863
864 printf("wrote %d events - elapsed time = %.1f secs\n",
865 (int)needed, ((double)(current_abs - last_time_written) / divisor) / 1000000);
866
867 last_time_written = current_abs;
868 }
869 }
870 }
871 if (try_writetrace == 0) {
872
873 if (next_window_begins > current_abs)
874 us_to_adjust = US_TO_SLEEP - (uint32_t)((double)(next_window_begins - current_abs) / divisor);
875 else
876 us_to_adjust = US_TO_SLEEP;
877
878 next_window_begins = current_abs + sample_window_abs;
879
880 us_to_sleep = US_TO_SLEEP - us_to_adjust;
881
882 next_window_begins = current_abs + (uint64_t)((double)(us_to_sleep + US_TO_SLEEP) * divisor);
883
884 if (us_to_sleep)
885 usleep(us_to_sleep);
886
887 get_bufinfo(&bufinfo);
888
889 if (bufinfo.flags & KDBG_WRAPPED)
890 printf("lost events\n");
891
892 needed = bufinfo.nkdbufs * sizeof(kd_buf);
893
894 readtrace(buffer);
895
896 if (bufinfo.flags & KDBG_WRAPPED) {
897
898 kd = (kd_buf *) buffer;
899
900 kd_tmp.timestamp = kd[0].timestamp;
901 kd_tmp.debugid = TRACE_LOST_EVENTS;
902
903 write(fd, &kd_tmp, sizeof(kd_tmp));
904 }
905 write(fd, buffer, needed * sizeof(kd_buf));
906
907 if (verbose_flag && needed > nbufs)
908 printf("needed = %ld\n", needed);
909 }
910 if (secs_to_run) {
911 current_abs = mach_absolute_time();
912
913 if (current_abs > ending_abstime)
914 break;
915 ms_to_run = (ending_abstime - current_abs) / (1000 * 1000);
916
917 if (ms_to_run == 0)
918 break;
919 }
920 }
921 set_enable(0);
922 set_numbufs(0);
923 set_remove();
924
925 close(fd);
926 }
927
928
929 void read_trace()
930 {
931 char *buffer;
932 uint32_t buffer_size;
933 kd_buf *kd;
934 int fd;
935 int firsttime = 1;
936 int lines = 0;
937 int io_lines = 0;
938 uint64_t bias = 0;
939 uint32_t count_of_names;
940 double last_event_time = 0.0;
941 time_t trace_time;
942
943 if (!readRAW_flag) {
944 get_bufinfo(&bufinfo);
945
946 if (bufinfo.nolog != 1) {
947 reenable = 1;
948 set_enable(0); /* disable logging*/
949 }
950 if (verbose_flag) {
951 if (bufinfo.flags & KDBG_WRAPPED)
952 printf("Buffer has wrapped\n");
953 else
954 printf("Buffer has not wrapped\n");
955 }
956 fd = 0;
957 count_of_names = 0;
958
959 } else {
960 fd = open(RAW_file, O_RDONLY);
961
962 if (fd < 0) {
963 perror("Can't open file");
964 exit(1);
965 }
966 if (read(fd, &raw_header, sizeof(RAW_header)) != sizeof(RAW_header)) {
967 perror("read failed");
968 exit(2);
969 }
970 if (raw_header.version_no != RAW_VERSION1) {
971 raw_header.version_no = RAW_VERSION0;
972 raw_header.TOD_secs = time((long *)0);
973 raw_header.TOD_usecs = 0;
974
975 lseek(fd, (off_t)0, SEEK_SET);
976
977 if (read(fd, &raw_header.thread_count, sizeof(int)) != sizeof(int)) {
978 perror("read failed");
979 exit(2);
980 }
981 }
982 count_of_names = raw_header.thread_count;
983 trace_time = raw_header.TOD_secs;
984
985 printf("%s\n", ctime(&trace_time));
986 }
987 buffer_size = 1000000 * sizeof(kd_buf);
988 buffer = malloc(buffer_size);
989
990 if (buffer == (char *) 0)
991 quit("can't allocate memory for tracing info\n");
992
993 kd = (kd_buf *)buffer;
994
995 read_command_map(fd, count_of_names);
996
997 for (;;) {
998 uint32_t count;
999 uint64_t now = 0;
1000 uint64_t prev;
1001 uint64_t prevdelta;
1002 uint32_t cpunum;
1003 uintptr_t thread;
1004 double x = 0.0;
1005 double y = 0.0;
1006 double event_elapsed_time;
1007 kd_buf *kdp;
1008 lookup_t lkp;
1009 boolean_t ending_event;
1010 int i;
1011 int debugid;
1012 int debugid_base;
1013 int dmsgindex;
1014 char dbgmessge[80];
1015 char outbuf[32];
1016 char *command;
1017
1018 if (!readRAW_flag) {
1019 needed = buffer_size;
1020
1021 mib[0] = CTL_KERN;
1022 mib[1] = KERN_KDEBUG;
1023 mib[2] = KERN_KDREADTR;
1024 mib[3] = 0;
1025 mib[4] = 0;
1026 mib[5] = 0;
1027 if (sysctl(mib, 3, buffer, &needed, NULL, 0) < 0)
1028 quit("trace facility failure, KERN_KDREADTR\n");
1029
1030 if (needed == 0)
1031 break;
1032 count = needed;
1033
1034 } else {
1035 uint32_t bytes_read;
1036
1037 bytes_read = read(fd, buffer, buffer_size);
1038
1039 if (bytes_read == -1) {
1040 perror("read failed");
1041 exit(2);
1042 }
1043 count = bytes_read / sizeof(kd_buf);
1044
1045 if (count == 0)
1046 break;
1047 }
1048 for (kdp = &kd[0], i = 0; i < count; i++, kdp++) {
1049
1050 prev = now;
1051 debugid = kdp->debugid;
1052 debugid_base = debugid & DBG_FUNC_MASK;
1053 now = kdp->timestamp & KDBG_TIMESTAMP_MASK;
1054
1055 if (firsttime)
1056 bias = now;
1057 now -= bias;
1058
1059 cpunum = kdbg_get_cpu(kdp);
1060 thread = kdp->arg5;
1061
1062 if (lines == 64 || firsttime)
1063 {
1064 prevdelta = now - prevdelta;
1065
1066 if (firsttime)
1067 firsttime = 0;
1068 else {
1069 x = (double)prevdelta;
1070 x /= divisor;
1071
1072 fprintf(output_file, "\n\nNumber of microsecs since in last page %8.1f\n", x);
1073 }
1074 prevdelta = now;
1075
1076 /*
1077 * Output description row to output file (make sure to format correctly for 32-bit and 64-bit)
1078 */
1079 fprintf(output_file,
1080 #ifdef __LP64__
1081 " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n"
1082 #else
1083 " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n"
1084 #endif
1085 );
1086
1087 lines = 0;
1088
1089 if (io_lines > 15000) {
1090 fcntl(output_fd, F_FLUSH_DATA, 0);
1091
1092 io_lines = 0;
1093 }
1094 }
1095 lkp = 0;
1096
1097 if (debugid_base == VFS_LOOKUP) {
1098 lkp = handle_lookup_event(thread, debugid, kdp);
1099
1100 if ( !lkp || !(debugid & DBG_FUNC_END))
1101 continue;
1102 }
1103 x = (double)now;
1104 x /= divisor;
1105
1106 if (last_event_time)
1107 y = x - last_event_time;
1108 else
1109 y = x;
1110 last_event_time = x;
1111 ending_event = FALSE;
1112
1113 find_thread_command(kdp, &command);
1114
1115 /*
1116 * The internal use TRACE points clutter the output.
1117 * Print them only if in verbose mode.
1118 */
1119 if (!verbose_flag)
1120 {
1121 /* Is this entry of Class DBG_TRACE */
1122 if ((debugid >> 24) == DBG_TRACE) {
1123 if (((debugid >> 16) & 0xff) != DBG_TRACE_INFO)
1124 continue;
1125 }
1126 }
1127 if ( !lkp) {
1128 int t_debugid;
1129 int t_thread;
1130
1131 if ((debugid & DBG_FUNC_START) || debugid == MACH_MAKERUNNABLE) {
1132
1133 if (debugid_base != BSC_thread_terminate && debugid_base != BSC_exit) {
1134
1135 if (debugid == MACH_MAKERUNNABLE)
1136 t_thread = kdp->arg1;
1137 else
1138 t_thread = thread;
1139
1140 insert_start_event(t_thread, debugid_base, now);
1141 }
1142
1143 } else if ((debugid & DBG_FUNC_END) || debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) {
1144
1145 if (debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) {
1146 t_debugid = MACH_MAKERUNNABLE;
1147 t_thread = kdp->arg2;
1148 } else {
1149 t_debugid = debugid_base;
1150 t_thread = thread;
1151 }
1152 event_elapsed_time = (double)consume_start_event(t_thread, t_debugid, now);
1153 event_elapsed_time /= divisor;
1154 ending_event = TRUE;
1155
1156 if (event_elapsed_time == 0 && (debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED))
1157 ending_event = FALSE;
1158 }
1159 }
1160 if (ending_event) {
1161 char *ch;
1162
1163 sprintf(&outbuf[0], "(%-10.1f)", event_elapsed_time);
1164 /*
1165 * fix that right paren
1166 */
1167 ch = &outbuf[11];
1168
1169 if (*ch != ')') {
1170 ch = strchr (&outbuf[0], ')');
1171 }
1172 if (ch)
1173 {
1174 *ch = ' ';
1175 --ch;
1176
1177 while (ch != &outbuf[0])
1178 {
1179 if (*ch == ' ')
1180 --ch;
1181 else
1182 {
1183 *(++ch) = ')';
1184 break;
1185 }
1186 }
1187 }
1188 }
1189 if (match_debugid(debugid_base, dbgmessge, &dmsgindex)) {
1190 if (ending_event)
1191 fprintf(output_file, "%13.1f %10.1f%s %-28x ", x, y, outbuf, debugid_base);
1192 else
1193 fprintf(output_file, "%13.1f %10.1f %-28x ", x, y, debugid_base);
1194 } else {
1195 if (ending_event)
1196 fprintf(output_file, "%13.1f %10.1f%s %-28.28s ", x, y, outbuf, dbgmessge);
1197 else
1198 fprintf(output_file, "%13.1f %10.1f %-28.28s ", x, y, dbgmessge);
1199 }
1200 if (lkp) {
1201 char *strptr;
1202 int len;
1203
1204 strptr = (char *)lkp->lk_pathname;
1205
1206 /*
1207 * print the tail end of the pathname
1208 */
1209 len = strlen(strptr);
1210 if (len > 51)
1211 len -= 51;
1212 else
1213 len = 0;
1214 #ifdef __LP64__
1215
1216 fprintf(output_file, "%-16lx %-51s %-16lx %-2d %s\n", lkp->lk_dvp, &strptr[len], thread, cpunum, command);
1217 #else
1218 fprintf(output_file, "%-8x %-51s %-8lx %-2d %s\n", (unsigned int)lkp->lk_dvp, &strptr[len], thread, cpunum, command);
1219 #endif
1220 delete_lookup_event(thread, lkp);
1221 } else {
1222 #ifdef __LP64__
1223 fprintf(output_file, "%-16lx %-16lx %-16lx %-16lx %-16lx %-2d %s\n", kdp->arg1, kdp->arg2, kdp->arg3, kdp->arg4, thread, cpunum, command);
1224 #else
1225 fprintf(output_file, "%-8lx %-8lx %-8lx %-8lx %-8lx %-2d %s\n", kdp->arg1, kdp->arg2, kdp->arg3, kdp->arg4, thread, cpunum, command);
1226 #endif
1227 }
1228 lines++;
1229 io_lines++;
1230 }
1231 }
1232 if (reenable == 1)
1233 set_enable(1); /* re-enable kernel logging */
1234 }
1235
1236
1237
1238 void signal_handler(int sig)
1239 {
1240 ptrace(PT_KILL, pid, (caddr_t)0, 0);
1241 /*
1242 * child is gone; no need to disable the pid
1243 */
1244 exit(2);
1245 }
1246
1247
1248 void signal_handler_RAW(int sig)
1249 {
1250 LogRAW_flag = 0;
1251 }
1252
1253
1254
1255 int main(argc, argv, env)
1256 int argc;
1257 char **argv;
1258 char **env;
1259 {
1260 extern char *optarg;
1261 extern int optind;
1262 int status;
1263 int ch;
1264 int i;
1265 char *output_filename = NULL;
1266
1267 for (i = 1; i < argc; i++) {
1268 if (strcmp("-X", argv[i]) == 0) {
1269 force_32bit_exec = 1;
1270 break;
1271 }
1272 }
1273 if (force_32bit_exec) {
1274 if (0 != reexec_to_match_lp64ness(FALSE)) {
1275 fprintf(stderr, "Could not re-execute: %d\n", errno);
1276 exit(1);
1277 }
1278 } else {
1279 if (0 != reexec_to_match_kernel()) {
1280 fprintf(stderr, "Could not re-execute: %d\n", errno);
1281 exit(1);
1282 }
1283 }
1284 if (setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_PASSIVE) < 0) {
1285 printf("setiopolicy failed\n");
1286 exit(1);
1287 }
1288 output_file = stdout;
1289 output_fd = 1;
1290
1291 while ((ch = getopt(argc, argv, "hedEk:irb:gc:p:s:tR:L:l:S:F:a:x:Xnfvo:P")) != EOF)
1292 {
1293 switch(ch)
1294 {
1295 case 'h': /* help */
1296 usage(LONG_HELP);
1297 break;
1298 case 'S':
1299 secs_to_run = argtoi('S', "decimal number", optarg, 10);
1300 break;
1301 case 'a': /* set tracing on a pid */
1302 pid_flag=1;
1303 pid = argtoi('a', "decimal number", optarg, 10);
1304 break;
1305 case 'x': /* exclude a pid from tracing */
1306 pid_exflag=1;
1307 pid = argtoi('x', "decimal number", optarg, 10);
1308 break;
1309 case 'v':
1310 verbose_flag=1;
1311 break;
1312 case 'l':
1313 logRAW_flag = 1;
1314 logfile = optarg;
1315 break;
1316 case 'L':
1317 LogRAW_flag = 1;
1318 logfile = optarg;
1319 signal(SIGINT, signal_handler_RAW);
1320 break;
1321 case 'e':
1322 enable_flag = 1;
1323 break;
1324 case 'i':
1325 init_flag = 1;
1326 break;
1327 case 'E':
1328 execute_flag = 1;
1329 break;
1330 case 'd':
1331 disable_flag = 1;
1332 break;
1333 case 'k':
1334 if (kval_flag == 0)
1335 value1 = argtoul('k', "hex number", optarg, 16);
1336 else if (kval_flag == 1)
1337 value2 = argtoul('k', "hex number", optarg, 16);
1338 else if (kval_flag == 2)
1339 value3 = argtoul('k', "hex number", optarg, 16);
1340 else if (kval_flag == 3)
1341 value4 = argtoul('k', "hex number", optarg, 16);
1342 else
1343 {
1344 fprintf(stderr, "A maximum of four values can be specified with -k\n");
1345 usage(SHORT_HELP);
1346 }
1347 kval_flag++;
1348 break;
1349 case 'r':
1350 remove_flag = 1;
1351 break;
1352 case 'g':
1353 bufget_flag = 1;
1354 break;
1355 case 't':
1356 trace_flag = 1;
1357 break;
1358 case 'R':
1359 readRAW_flag = 1;
1360 RAW_file = optarg;
1361 break;
1362 case 'n':
1363 nowrap_flag = 1;
1364 break;
1365 case 'f':
1366 freerun_flag = 1;
1367 break;
1368 case 'b':
1369 bufset_flag = 1;
1370 nbufs = argtoi('b', "decimal number", optarg, 10);
1371 break;
1372 case 'c':
1373 class_flag = 1;
1374 class = argtoi('c', "decimal number", optarg, 10);
1375 class2 = class+1;
1376 break;
1377 case 's':
1378 subclass_flag = 1;
1379 subclass = argtoi('s', "decimal number", optarg, 10);
1380 break;
1381 case 'p':
1382 if (class_flag != 1)
1383 { fprintf(stderr, "-p must follow -c\n");
1384 exit(1);
1385 }
1386 class2 = argtoi('p', "decimal number", optarg, 10);
1387 break;
1388 case 'P':
1389 ppt_flag = 1;
1390 break;
1391 case 'o':
1392 output_filename = optarg;
1393 break;
1394 case 'F':
1395 frequency = argtoi('F', "decimal number", optarg, 10);
1396 break;
1397 case 'X':
1398 break;
1399 default:
1400 usage(SHORT_HELP);
1401 }
1402 }
1403 argc -= optind;
1404
1405 if (argc)
1406 {
1407 if (!execute_flag)
1408 {
1409 cfile = argv[optind];
1410 if (verbose_flag)
1411 printf("Code file is %s \n", cfile);
1412 if (parse_codefile(cfile) == -1)
1413 cfile = (char *)0;
1414 }
1415 }
1416 else
1417 {
1418 if (execute_flag)
1419 {
1420 printf("-E flag needs an executable to launch\n");
1421 exit(1);
1422 }
1423 }
1424 getdivisor();
1425
1426 if (pid_flag && pid_exflag)
1427 {
1428 fprintf(stderr, "Can't use both -a and -x flag together\n");
1429 exit(1);
1430 }
1431
1432 if (subclass_flag && !class_flag) {
1433 fprintf(stderr,"Must define a class ('c') with the subclass ('s') option\n");
1434 usage(SHORT_HELP);
1435 }
1436
1437 if (kval_flag && (subclass_flag || class_flag))
1438 {
1439 fprintf(stderr,"Don't use class or subclass with the 'k' code options.\n");
1440 usage(SHORT_HELP);
1441 }
1442
1443 if (output_filename && !trace_flag && !readRAW_flag)
1444 {
1445 fprintf(stderr, "When using 'o' option, must use the 't' or 'R' option too\n");
1446 usage(SHORT_HELP);
1447 }
1448
1449 if (LogRAW_flag) {
1450 get_bufinfo(&bufinfo);
1451
1452 if (bufinfo.nolog == 0)
1453 use_current_buf = 1;
1454 }
1455
1456 if (disable_flag)
1457 {
1458 if (pid_flag)
1459 {
1460 set_pidcheck(pid, 0); /* disable pid check for given pid */
1461 exit(1);
1462 }
1463 else if (pid_exflag)
1464 {
1465 set_pidexclude(pid, 0); /* disable pid exclusion for given pid */
1466 exit(1);
1467 }
1468 set_enable(0);
1469 exit(1);
1470 }
1471
1472 if (remove_flag)
1473 {
1474 set_remove();
1475 exit(1);
1476 }
1477
1478 if (bufset_flag )
1479 {
1480 if (!init_flag && !LogRAW_flag)
1481 {
1482 fprintf(stderr,"The -b flag must be used with the -i flag\n");
1483 exit(1);
1484 }
1485 set_numbufs(nbufs);
1486 }
1487
1488 if (nowrap_flag)
1489 set_nowrap();
1490
1491 if (freerun_flag)
1492 set_freerun();
1493
1494 if (bufget_flag)
1495 {
1496 get_bufinfo(&bufinfo);
1497
1498 printf("The kernel buffer settings are:\n");
1499
1500 if (bufinfo.flags & KDBG_BUFINIT)
1501 printf("\tKernel buffer is initialized\n");
1502 else
1503 printf("\tKernel buffer is not initialized\n");
1504
1505 printf("\t number of buf entries = %d\n", bufinfo.nkdbufs);
1506
1507 if (verbose_flag)
1508 {
1509 if (bufinfo.flags & KDBG_MAPINIT)
1510 printf("\tKernel thread map is initialized\n");
1511 else
1512 printf("\tKernel thread map is not initialized\n");
1513 printf("\t number of thread entries = %d\n", bufinfo.nkdthreads);
1514 }
1515
1516 if (bufinfo.nolog)
1517 printf("\tBuffer logging is disabled\n");
1518 else
1519 printf("\tBuffer logging is enabled\n");
1520
1521 if (verbose_flag)
1522 printf("\tkernel flags = 0x%x\n", bufinfo.flags);
1523
1524 if (bufinfo.flags & KDBG_NOWRAP)
1525 printf("\tKernel buffer wrap is disabled\n");
1526 else
1527 printf("\tKernel buffer wrap is enabled\n");
1528
1529 if (bufinfo.flags & KDBG_RANGECHECK)
1530 printf("\tCollection within a range is enabled\n");
1531 else
1532 printf("\tCollection within a range is disabled\n");
1533
1534 if (bufinfo.flags & KDBG_VALCHECK)
1535 printf("\tCollecting specific code values is enabled\n");
1536 else
1537 printf("\tCollecting specific code values is disabled\n");
1538
1539 if (bufinfo.flags & KDBG_PIDCHECK)
1540 printf("\tCollection based on pid is enabled\n");
1541 else
1542 printf("\tCollection based on pid is disabled\n");
1543
1544 if (bufinfo.flags & KDBG_PIDEXCLUDE)
1545 printf("\tCollection based on pid exclusion is enabled\n");
1546 else
1547 printf("\tCollection based on pid exclusion is disabled\n");
1548
1549 if (bufinfo.bufid == -1)
1550 printf("\tKernel buffer is not controlled by any process.\n");
1551 else
1552 printf("\tKernel buffer is controlled by proc id [%d]\n", bufinfo.bufid);
1553 }
1554
1555 if (init_flag)
1556 set_init();
1557
1558 if (class_flag)
1559 set_class();
1560
1561 if (subclass_flag)
1562 set_subclass();
1563
1564 if (kval_flag)
1565 set_kval_list();
1566
1567 if (execute_flag)
1568 {
1569 fprintf(stderr, "Starting program: %s\n", argv[optind]);
1570 fflush(stdout);
1571 fflush(stderr);
1572
1573 switch ((pid = vfork()))
1574 {
1575 case -1:
1576 perror("vfork: ");
1577 exit(1);
1578 case 0: /* child */
1579 setsid();
1580 ptrace(PT_TRACE_ME, 0, (caddr_t)0, 0);
1581 execve(argv[optind], &argv[optind], environ);
1582 perror("execve:");
1583 exit(1);
1584 }
1585 sleep(1);
1586
1587 signal(SIGINT, signal_handler);
1588 set_pidcheck(pid, 1);
1589 set_enable(1);
1590 ptrace(PT_CONTINUE, pid, (caddr_t)1, 0);
1591 waitpid(pid, &status, 0);
1592 /* child is gone; no need to disable the pid */
1593 exit(0);
1594 }
1595 else if (enable_flag)
1596 {
1597 if (pid_flag)
1598 set_pidcheck(pid, 1);
1599 else if (pid_exflag)
1600 set_pidexclude(pid, 1);
1601 set_enable(1);
1602 }
1603
1604 if (output_filename)
1605 {
1606 if (((output_fd = open(output_filename, O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0644)) < 0 ) ||
1607 !(output_file = fdopen(output_fd, "w")))
1608 {
1609 fprintf(stderr, "Cannot open file \"%s\" for writing.\n", output_filename);
1610 usage(SHORT_HELP);
1611 }
1612 setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE);
1613
1614 if (fcntl(output_fd, F_NOCACHE, 1) < 0)
1615 {
1616 /* Not fatal */
1617 fprintf(stderr, "Warning: setting F_NOCACHE on %s, failed\n", output_filename);
1618 }
1619 }
1620 if (!LogRAW_flag && !logRAW_flag)
1621 setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE);
1622
1623 if (trace_flag || readRAW_flag)
1624 read_trace();
1625 else if (LogRAW_flag)
1626 Log_trace();
1627 else if (logRAW_flag)
1628 log_trace();
1629
1630 exit(0);
1631
1632 } /* end main */
1633
1634
1635 void
1636 quit(char *s)
1637 {
1638 if (reenable == 1)
1639 {
1640 reenable = 0;
1641 set_enable(1); /* re-enable kernel logging */
1642 }
1643
1644 printf("trace: ");
1645 if (s)
1646 printf("%s ", s);
1647 exit(1);
1648 }
1649
1650 static void
1651 usage(int short_help)
1652 {
1653
1654 if (short_help)
1655 {
1656 (void)fprintf(stderr, " usage: trace -h\n");
1657 (void)fprintf(stderr, " usage: trace -i [-b numbufs]\n");
1658 (void)fprintf(stderr, " usage: trace -g\n");
1659 (void)fprintf(stderr, " usage: trace -d [-a pid | -x pid ]\n");
1660 (void)fprintf(stderr, " usage: trace -r\n");
1661 (void)fprintf(stderr, " usage: trace -n\n");
1662
1663 (void)fprintf(stderr,
1664 " usage: trace -e [ -c class [-p class] [-s subclass] ] [-a pid | -x pid] |\n");
1665 (void)fprintf(stderr,
1666 " [-k code | -k code | -k code | -k code] [-P] \n\n");
1667
1668 (void)fprintf(stderr,
1669 " usage: trace -E [ -c class [-p class] [-s subclass] ] |\n");
1670 (void)fprintf(stderr,
1671 " [-k code | -k code | -k code | -k code] [-P]\n");
1672 (void)fprintf(stderr,
1673 " executable_path [optional args to executable] \n\n");
1674
1675 (void)fprintf(stderr,
1676 " usage: trace -L RawFilename [-S SecsToRun]\n");
1677 (void)fprintf(stderr,
1678 " usage: trace -l RawFilename\n");
1679 (void)fprintf(stderr,
1680 " usage: trace -R RawFilename [-X] [-F frequency] [-o OutputFilename] [CodeFilename]\n");
1681 (void)fprintf(stderr,
1682 " usage: trace -t [-o OutputFilename] [CodeFilename]\n");
1683 exit(1);
1684 }
1685
1686
1687 /* Only get here of printing long usage list */
1688 (void)fprintf(stderr, "usage: trace -h\n");
1689 (void)fprintf(stderr, "\tPrint this long command help.\n\n");
1690
1691 (void)fprintf(stderr, "usage: trace -i [-b numbufs]\n");
1692 (void)fprintf(stderr, "\tInitialize the kernel trace buffer.\n\n");
1693 (void)fprintf(stderr, "\t-b numbufs The number of trace elements the kernel buffer\n");
1694 (void)fprintf(stderr, "\t can hold is set to numbufs. Use with the -i flag.\n");
1695 (void)fprintf(stderr, "\t Enter a decimal value.\n\n");
1696
1697 (void)fprintf(stderr, "usage: trace -g\n");
1698 (void)fprintf(stderr, "\tGet the kernel buffer settings.\n\n");
1699
1700 (void)fprintf(stderr, "usage: trace -d [-a pid | -x pid]\n");
1701 (void)fprintf(stderr, "\tDisable/stop collection of kernel trace elements.\n\n");
1702 (void)fprintf(stderr, "\t -a pid Disable/stop collection for this process only.\n\n");
1703 (void)fprintf(stderr, "\t -x pid Disable/stop exclusion of this process only.\n\n");
1704
1705 (void)fprintf(stderr, "usage: trace -r\n");
1706 (void)fprintf(stderr, "\tRemove the kernel trace buffer. Set controls to default.\n\n");
1707
1708 (void)fprintf(stderr, "usage: trace -n\n");
1709 (void)fprintf(stderr, "\tDisables kernel buffer wrap around.\n\n");
1710
1711 (void)fprintf(stderr,
1712 "usage: trace -e [ -c class [-p class] [-s subclass] ] [-a pid | -x pid] |\n");
1713 (void)fprintf(stderr,
1714 " [-k code | -k code | -k code | -k code] \n\n");
1715 (void)fprintf(stderr, "\tEnable/start collection of kernel trace elements.\n");
1716 (void)fprintf(stderr, "\tEnter values in decimal notation unless otherwise noted..\n\n");
1717 (void)fprintf(stderr, "\t -c class Restrict trace collection to given class.\n\n");
1718 (void)fprintf(stderr, "\t -p class Restrict trace collection to given class range.\n");
1719 (void)fprintf(stderr, "\t Must provide class with -c first.\n\n");
1720 (void)fprintf(stderr, "\t -s subclass Restrict trace collection to given subclass.\n");
1721 (void)fprintf(stderr, "\t Must provide class with -c.\n\n");
1722 (void)fprintf(stderr, "\t -a pid Restrict trace collection to the given process.\n\n");
1723 (void)fprintf(stderr, "\t -x pid Exclude the given process from trace collection.\n\n");
1724 (void)fprintf(stderr, "\t -k code Restrict trace collection up to four specific codes.\n");
1725 (void)fprintf(stderr, "\t Enter codes in hex values.\n\n");
1726 (void)fprintf(stderr, "\t -P Enable restricted PPT trace points only.\n\n");
1727
1728 (void)fprintf(stderr,
1729 "usage: trace -E [ -c class [-p class] [-s subclass] ] |\n");
1730 (void)fprintf(stderr,
1731 " [-k code | -k code | -k code | -k code] \n");
1732 (void)fprintf(stderr,
1733 " executable_path [optional args to executable] \n\n");
1734 (void)fprintf(stderr, "\tLaunch the given executable and enable/start\n");
1735 (void)fprintf(stderr, "\tcollection of kernel trace elements for that process.\n");
1736 (void)fprintf(stderr, "\tSee -e(enable) flag for option descriptions.\n\n");
1737
1738 (void)fprintf(stderr,
1739 "usage: trace -t [-o OutputFilename] [CodeFilename] \n");
1740 (void)fprintf(stderr, "\tCollect the kernel buffer trace data and print it.\n\n");
1741 (void)fprintf(stderr, "\t -o OutputFilename Print trace output to OutputFilename. Default is stdout.\n\n");
1742
1743 (void)fprintf(stderr,
1744 "usage: trace -R RawFilename [-X] [-F frequency] [-o OutputFilename] [CodeFilename] \n");
1745 (void)fprintf(stderr, "\tRead raw trace file and print it.\n\n");
1746 (void)fprintf(stderr, "\t -X Force trace to interpret trace data as 32 bit. Default is to match the current systems bit width.\n");
1747 (void)fprintf(stderr, "\t -F frequency Specify the frequency of the clock used to timestamp entries in RawFilename\n");
1748 (void)fprintf(stderr, "\t -o OutputFilename Print trace output to OutputFilename. Default is stdout.\n\n");
1749
1750 (void)fprintf(stderr,
1751 "usage: trace -L RawFilename [-S SecsToRun]\n");
1752 (void)fprintf(stderr, "\tContinuously collect the kernel buffer trace data in the raw format and write it to RawFilename.\n\n");
1753 (void)fprintf(stderr, "\t -S SecsToRun Specify the number of seconds to collect trace data.\n\n");
1754
1755 (void)fprintf(stderr,
1756 "usage: trace -l RawFilename\n");
1757 (void)fprintf(stderr, "\tCollect the existing kernel buffer trace data in the raw format.\n\n");
1758
1759 exit(1);
1760 }
1761
1762
1763 static int
1764 argtoi(flag, req, str, base)
1765 int flag;
1766 char *req, *str;
1767 int base;
1768 {
1769 char *cp;
1770 int ret;
1771
1772 ret = (int)strtol(str, &cp, base);
1773 if (cp == str || *cp)
1774 errx(EINVAL, "-%c flag requires a %s", flag, req);
1775 return (ret);
1776 }
1777
1778
1779 static unsigned long
1780 argtoul(flag, req, str, base)
1781 int flag;
1782 char *req, *str;
1783 int base;
1784 {
1785 char *cp;
1786 unsigned long ret;
1787
1788 ret = (int)strtoul(str, &cp, base);
1789 if (cp == str || *cp)
1790 errx(EINVAL, "-%c flag requires a %s", flag, req);
1791 return (ret);
1792 }
1793
1794
1795 /*
1796 * comparison function for qsort
1797 * sort by debugid
1798 */
1799 int debugid_compar(p1, p2)
1800 code_type_t *p1;
1801 code_type_t *p2;
1802 {
1803 if (p1->debugid > p2->debugid)
1804 return(1);
1805 else if (p1->debugid == p2->debugid)
1806 return(0);
1807 else
1808 return(-1);
1809 }
1810
1811
1812 /*
1813 * Find the debugid code in the list and return its index
1814 */
1815 static int binary_search(list, lowbound, highbound, code)
1816 code_type_t *list;
1817 int lowbound, highbound;
1818 unsigned int code;
1819 {
1820 int low, high, mid;
1821 int tries = 0;
1822
1823 low = lowbound;
1824 high = highbound;
1825
1826 while (1)
1827 {
1828 mid = (low + high) / 2;
1829
1830 tries++;
1831
1832 if (low > high)
1833 return (-1); /* failed */
1834 else if ( low + 1 >= high)
1835 {
1836 /* We have a match */
1837 if (list[high].debugid == code)
1838 return(high);
1839 else if (list[low].debugid == code)
1840 return(low);
1841 else
1842 return(-1); /* search failed */
1843 }
1844 else if (code < list[mid].debugid)
1845 high = mid;
1846 else
1847 low = mid;
1848 }
1849 }
1850
1851
1852 static int
1853 parse_codefile(char *filename)
1854 {
1855 int fd;
1856 int i, j, count, line;
1857 struct stat stat_buf;
1858 unsigned long file_size;
1859 char *file_addr, *endp;
1860
1861 if ((fd = open(filename, O_RDONLY, 0)) == -1)
1862 {
1863 printf("Failed to open code description file %s\n",filename);
1864 return(-1);
1865 }
1866
1867 if (fstat(fd, &stat_buf) == -1)
1868 {
1869 printf("Error: Can't fstat file: %s\n", filename);
1870 return(-1);
1871 }
1872
1873 /*
1874 * For some reason mapping files with zero size fails
1875 * so it has to be handled specially.
1876 */
1877 file_size = stat_buf.st_size;
1878
1879 if (stat_buf.st_size != 0)
1880 {
1881 if ((file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE,
1882 MAP_PRIVATE|MAP_FILE, fd, 0)) == (char*) -1)
1883 {
1884 printf("Error: Can't map file: %s\n", filename);
1885 close(fd);
1886 return(-1);
1887 }
1888 }
1889 else
1890 {
1891 printf("Error: Zero sized file: %s\n", filename);
1892 close(fd);
1893 return(-1);
1894 }
1895 close(fd);
1896
1897
1898 /*
1899 * If we get here, we have mapped the file
1900 * and we are ready to parse it. Count
1901 * the newlines to get total number of codes.
1902 */
1903
1904 for (count = 0, j=1; j < file_size; j++)
1905 {
1906 if (file_addr[j] == '\n')
1907 count++;
1908 }
1909
1910 if (count == 0)
1911 {
1912 printf("Error: No codes in %s\n", filename);
1913 return(-1);
1914 }
1915
1916 /*
1917 * Fudge the count to accomodate the last line in the file -
1918 * in case it doesn't end in a newline.
1919 */
1920 count++;
1921
1922 if ((codesc = (code_type_t *)malloc(count * sizeof(code_type_t))) == 0 ) {
1923 printf("Failed to allocate buffer for code descriptions\n");
1924 return(-1);
1925 }
1926
1927 bzero((char *)codesc, count * sizeof(code_type_t));
1928 codenum = 0;
1929
1930 for (line = 1, i = 0, j = 0; j < file_size && i < count ; i++)
1931 {
1932 /* Skip blank lines */
1933 while (file_addr[j] == '\n')
1934 {
1935 j++;
1936 line++;
1937 }
1938
1939 /* Skip leading whitespace */
1940 while (file_addr[j] == ' ' || file_addr[j] == '\t')
1941 j++;
1942
1943 /* Get the debugid code */
1944 codesc[i].debugid = strtoul(file_addr + j, &endp, 16);
1945 j = endp - file_addr;
1946
1947 if (codesc[i].debugid == 0)
1948 {
1949 /* We didn't find a debugid code - skip this line */
1950 if (verbose_flag)
1951 printf("Error: while parsing line %d, skip\n", line);
1952 while (file_addr[j] != '\n' && j < file_size)
1953 j++;
1954 i--;
1955 line++;
1956 continue;
1957 }
1958
1959 /* Skip whitespace */
1960 while (file_addr[j] == ' ' || file_addr[j] == '\t')
1961 j++;
1962
1963 /* Get around old file that had count at the beginning */
1964 if (file_addr[j] == '\n')
1965 {
1966 /* missing debugid string - skip */
1967 if (verbose_flag)
1968 printf("Error: while parsing line %d, (0x%x) skip\n", line, codesc[i].debugid);
1969
1970 j++;
1971 i--;
1972 line++;
1973 continue;
1974 }
1975
1976 /* Next is the debugid string terminated by a newline */
1977 codesc[i].debug_string = &file_addr[j];
1978
1979 /* Null out the newline terminator */
1980 while ((j < file_size) && (file_addr[j] != '\n'))
1981 j++;
1982 file_addr[j] = '\0'; /* File must be read-write */
1983 j++;
1984 line++;
1985 codenum++; /*Index into codesc is 0 to codenum-1 */
1986 }
1987
1988 if (verbose_flag)
1989 {
1990 printf("Parsed %d codes in %s\n", codenum, filename);
1991 printf("[%6d] 0x%8x %s\n", 0, codesc[0].debugid, codesc[0].debug_string);
1992 printf("[%6d] 0x%8x %s\n\n", codenum-1, codesc[codenum-1].debugid, codesc[codenum-1].debug_string);
1993 }
1994
1995 /* sort */
1996 qsort((void *)codesc, codenum, sizeof(code_type_t), debugid_compar);
1997
1998 if (verbose_flag)
1999 {
2000 printf("Sorted %d codes in %s\n", codenum, filename);
2001 printf("lowbound [%6d]: 0x%8x %s\n", 0, codesc[0].debugid, codesc[0].debug_string);
2002 printf("highbound [%6d]: 0x%8x %s\n\n", codenum-1, codesc[codenum-1].debugid, codesc[codenum-1].debug_string);
2003 }
2004
2005 #if 0
2006 /* Dump the codefile */
2007 for (i = 0; i < codenum; i++)
2008 printf("[%d] 0x%x %s\n",i+1, codesc[i].debugid, codesc[i].debug_string);
2009 #endif
2010 return(0);
2011 }
2012
2013
2014
2015 int match_debugid(unsigned int xx, char * debugstr, int * yy)
2016 {
2017 int indx;
2018
2019 if (codenum == 0)
2020 return(-1);
2021
2022 if (codesc[codeindx_cache].debugid != xx)
2023 indx = binary_search(codesc, 0, (codenum-1), xx);
2024 else
2025 indx = codeindx_cache;
2026
2027 if (indx == -1)
2028 return(indx); /* match failed */
2029 else {
2030 bcopy(&codesc[indx].debug_string[0], debugstr,80);
2031 *yy = indx;
2032 codeindx_cache = indx;
2033 return(0); /* match success */
2034 }
2035 }
2036
2037
2038 int
2039 read_command_map(int fd, int count)
2040 {
2041 int i;
2042 size_t size;
2043 int mib[6];
2044
2045 if (readRAW_flag) {
2046 total_threads = count;
2047 size = count * sizeof(kd_threadmap);
2048 } else {
2049 get_bufinfo(&bufinfo);
2050
2051 total_threads = bufinfo.nkdthreads;
2052 size = bufinfo.nkdthreads * sizeof(kd_threadmap);
2053 }
2054 mapptr = 0;
2055 nthreads = total_threads * 2;
2056
2057 if (verbose_flag)
2058 printf("Size of map table is %d, thus %d entries\n", (int)size, total_threads);
2059
2060 if (size) {
2061 if ((mapptr = (kd_threadmap *) malloc(size)))
2062 bzero (mapptr, size);
2063 else
2064 {
2065 if (verbose_flag)
2066 printf("Thread map is not initialized -- this is not fatal\n");
2067 return(0);
2068 }
2069 }
2070 if (readRAW_flag) {
2071 off_t offset;
2072
2073 if (read(fd, mapptr, size) != size) {
2074 if (verbose_flag)
2075 printf("Can't read the thread map -- this is not fatal\n");
2076 free(mapptr);
2077 mapptr = 0;
2078
2079 return(size);
2080 }
2081 if (raw_header.version_no != RAW_VERSION0) {
2082 offset = lseek(fd, (off_t)0, SEEK_CUR);
2083 offset = (offset + (4095)) & ~4095;
2084
2085 lseek(fd, offset, SEEK_SET);
2086 }
2087 } else {
2088 /* Now read the threadmap */
2089 mib[0] = CTL_KERN;
2090 mib[1] = KERN_KDEBUG;
2091 mib[2] = KERN_KDTHRMAP;
2092 mib[3] = 0;
2093 mib[4] = 0;
2094 mib[5] = 0; /* no flags */
2095 if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
2096 {
2097 /* This is not fatal -- just means I cant map command strings */
2098 if (verbose_flag)
2099 printf("Can't read the thread map -- this is not fatal\n");
2100 free(mapptr);
2101 mapptr = 0;
2102 return(0);
2103 }
2104 }
2105 for (i = 0; i < total_threads; i++)
2106 create_map_entry(mapptr[i].thread, &mapptr[i].command[0]);
2107
2108 if (verbose_flag) {
2109 /* Dump the initial map */
2110
2111 printf("Size of maptable returned is %ld, thus %ld entries\n", size, (size/sizeof(kd_threadmap)));
2112
2113 printf("Thread Command\n");
2114 for (i = 0; i < total_threads; i++)
2115 {
2116 printf ("0x%lx %s\n",
2117 mapptr[i].thread,
2118 mapptr[i].command);
2119 }
2120 }
2121 return(size);
2122 }
2123
2124
2125 void create_map_entry(uintptr_t thread, char *command)
2126 {
2127 threadmap_t tme;
2128 int hashid;
2129
2130 if ((tme = threadmap_freelist))
2131 threadmap_freelist = tme->tm_next;
2132 else
2133 tme = (threadmap_t)malloc(sizeof(struct threadmap));
2134
2135 tme->tm_thread = thread;
2136 tme->tm_deleteme = FALSE;
2137
2138 (void)strncpy (tme->tm_command, command, MAXCOMLEN);
2139 tme->tm_command[MAXCOMLEN] = '\0';
2140
2141 hashid = thread & HASH_MASK;
2142
2143 tme->tm_next = threadmap_hash[hashid];
2144 threadmap_hash[hashid] = tme;
2145 }
2146
2147
2148 void delete_thread_entry(uintptr_t thread)
2149 {
2150 threadmap_t tme = 0;
2151 threadmap_t tme_prev;
2152 int hashid;
2153
2154 hashid = thread & HASH_MASK;
2155
2156 if ((tme = threadmap_hash[hashid])) {
2157 if (tme->tm_thread == thread)
2158 threadmap_hash[hashid] = tme->tm_next;
2159 else {
2160 tme_prev = tme;
2161
2162 for (tme = tme->tm_next; tme; tme = tme->tm_next) {
2163 if (tme->tm_thread == thread) {
2164 tme_prev->tm_next = tme->tm_next;
2165 break;
2166 }
2167 tme_prev = tme;
2168 }
2169 }
2170 if (tme) {
2171 tme->tm_next = threadmap_freelist;
2172 threadmap_freelist = tme;
2173 }
2174 }
2175 }
2176
2177
2178 void find_and_insert_tmp_map_entry(uintptr_t pthread, char *command)
2179 {
2180 threadmap_t tme = 0;
2181 threadmap_t tme_prev;
2182 int hashid;
2183
2184 if ((tme = threadmap_temp)) {
2185 if (tme->tm_pthread == pthread)
2186 threadmap_temp = tme->tm_next;
2187 else {
2188 tme_prev = tme;
2189
2190 for (tme = tme->tm_next; tme; tme = tme->tm_next) {
2191 if (tme->tm_pthread == pthread) {
2192 tme_prev->tm_next = tme->tm_next;
2193 break;
2194 }
2195 tme_prev = tme;
2196 }
2197 }
2198 if (tme) {
2199 (void)strncpy (tme->tm_command, command, MAXCOMLEN);
2200 tme->tm_command[MAXCOMLEN] = '\0';
2201
2202 delete_thread_entry(tme->tm_thread);
2203
2204 hashid = tme->tm_thread & HASH_MASK;
2205
2206 tme->tm_next = threadmap_hash[hashid];
2207 threadmap_hash[hashid] = tme;
2208 }
2209 }
2210 }
2211
2212
2213 void create_tmp_map_entry(uintptr_t thread, uintptr_t pthread)
2214 {
2215 threadmap_t tme;
2216
2217 if ((tme = threadmap_freelist))
2218 threadmap_freelist = tme->tm_next;
2219 else
2220 tme = (threadmap_t)malloc(sizeof(struct threadmap));
2221
2222 tme->tm_thread = thread;
2223 tme->tm_pthread = pthread;
2224 tme->tm_deleteme = FALSE;
2225 tme->tm_command[0] = '\0';
2226
2227 tme->tm_next = threadmap_temp;
2228 threadmap_temp = tme;
2229 }
2230
2231
2232 threadmap_t
2233 find_thread_entry(uintptr_t thread)
2234 {
2235 threadmap_t tme;
2236 int hashid;
2237
2238 hashid = thread & HASH_MASK;
2239
2240 for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
2241 if (tme->tm_thread == thread)
2242 return (tme);
2243 }
2244 return (0);
2245 }
2246
2247
2248 void find_thread_name(uintptr_t thread, char **command, boolean_t deleteme)
2249 {
2250 threadmap_t tme;
2251
2252 if ((tme = find_thread_entry(thread))) {
2253 *command = tme->tm_command;
2254
2255 if (deleteme == TRUE)
2256 tme->tm_deleteme = deleteme;
2257 } else
2258 *command = EMPTYSTRING;
2259 }
2260
2261
2262 void find_thread_command(kd_buf *kbufp, char **command)
2263 {
2264 uintptr_t thread;
2265 threadmap_t tme;
2266 int debugid_base;
2267
2268 thread = kbufp->arg5;
2269 debugid_base = kbufp->debugid & DBG_FUNC_MASK;
2270
2271 if (debugid_base == BSC_exit || debugid_base == MACH_STKHANDOFF) {
2272 /*
2273 * Mark entry as invalid and return temp command pointer
2274 */
2275 if ((tme = find_thread_entry(thread))) {
2276
2277 strncpy(tmpcommand, tme->tm_command, MAXCOMLEN);
2278 *command = tmpcommand;
2279
2280 if (debugid_base == BSC_exit || tme->tm_deleteme == TRUE)
2281 delete_thread_entry(thread);
2282 } else
2283 *command = EMPTYSTRING;
2284 }
2285 else if (debugid_base == TRACE_DATA_NEWTHREAD) {
2286 /*
2287 * Save the create thread data
2288 */
2289 create_tmp_map_entry(kbufp->arg1, kbufp->arg5);
2290 }
2291 else if (debugid_base == TRACE_STRING_NEWTHREAD) {
2292 /*
2293 * process new map entry
2294 */
2295 find_and_insert_tmp_map_entry(kbufp->arg5, (char *)&kbufp->arg1);
2296 }
2297 else if (debugid_base == TRACE_STRING_EXEC) {
2298
2299 delete_thread_entry(kbufp->arg5);
2300
2301 create_map_entry(kbufp->arg5, (char *)&kbufp->arg1);
2302 }
2303 else
2304 find_thread_name(thread, command, (debugid_base == BSC_thread_terminate));
2305 }
2306
2307
2308 static
2309 void getdivisor()
2310 {
2311 mach_timebase_info_data_t info;
2312
2313 if (frequency == 0) {
2314 (void) mach_timebase_info (&info);
2315
2316 divisor = ( (double)info.denom / (double)info.numer) * 1000;
2317 } else
2318 divisor = (double)frequency / 1000000;
2319
2320 if (verbose_flag)
2321 printf("divisor = %g\n", divisor);
2322 }