2 cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -arch x86_64 -arch i386 -O -o trace trace.c
9 #include <sys/socket.h>
11 #include <sys/ioctl.h>
14 #include <sys/ucred.h>
17 #include <sys/ptrace.h>
18 #include <sys/sysctl.h>
20 #include <sys/resource.h>
32 #include <sys/kdebug.h>
34 #include <mach/mach.h>
35 #include <mach/mach_time.h>
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;
69 int force_32bit_exec
= 0;
75 char *logfile
= (char *)0; /* This file is trace format */
76 char *RAW_file
= (char *)0;
80 extern char **environ
;
83 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
84 #define DBG_FUNC_MASK 0xfffffffc
88 #define CSC_MASK 0xffff0000
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
101 #define EMPTYSTRING ""
102 #define UNKNOWN "unknown"
104 char tmpcommand
[MAXCOMLEN
];
106 int total_threads
= 0;
108 kd_threadmap
*mapptr
= 0;
111 If NUMPARMS changes from the kernel,
112 then PATHLENGTH will also reflect the change
113 This is for the vfslookup entries that
117 #define PATHLENGTH (NUMPARMS*sizeof(long))
120 #define US_TO_SLEEP 50000
121 #define BASE_EVENTS 500000
131 code_type_t
* codesc
= 0;
134 typedef struct event
*event_t
;
141 uint64_t ev_timestamp
;
144 typedef struct lookup
*lookup_t
;
152 long lk_pathname
[NUMPARMS
+ 1];
155 typedef struct threadmap
*threadmap_t
;
161 uintptr_t tm_pthread
;
162 boolean_t tm_deleteme
;
163 char tm_command
[MAXCOMLEN
+ 1];
167 #define HASH_SIZE 1024
168 #define HASH_MASK 1023
170 event_t event_hash
[HASH_SIZE
];
171 lookup_t lookup_hash
[HASH_SIZE
];
172 threadmap_t threadmap_hash
[HASH_SIZE
];
174 event_t event_freelist
;
175 lookup_t lookup_freelist
;
176 threadmap_t threadmap_freelist
;
177 threadmap_t threadmap_temp
;
180 #define SBUFFER_SIZE (128 * 4096)
181 char sbuffer
[SBUFFER_SIZE
];
184 int use_current_buf
= 0;
187 kbufinfo_t bufinfo
= {0, 0, 0, 0};
190 int codeindx_cache
= 0;
191 char codefile
[] = "codes";
192 char *cfile
= (char *)0;
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();
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
);
229 static int writetrace(int);
230 static int write_command_map(int);
231 static int debugid_compar(code_type_t
*, code_type_t
*);
233 static threadmap_t
find_thread_entry(uintptr_t);
237 #ifndef KERN_KDWRITETR
238 #define KERN_KDWRITETR 17
241 #ifndef KERN_KDWRITEMAP
242 #define KERN_KDWRITEMAP 18
246 #define F_FLUSH_DATA 40
257 #define RAW_VERSION0 0x55aa0000
258 #define RAW_VERSION1 0x55aa0101
262 RAW_header raw_header
;
266 void set_enable(int val
)
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
;
282 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
283 quit("trace facility failure, KERN_KDENABLE\n");
293 mib
[1] = KERN_KDEBUG
;
294 mib
[2] = KERN_KDREMOVE
;
298 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
301 quit("the trace facility is currently in use...\n fs_usage, sc_usage, trace, and latency use this feature.\n\n");
303 quit("trace facility failure, KERN_KDREMOVE\n");
307 void set_numbufs(int nbufs
)
310 mib
[1] = KERN_KDEBUG
;
311 mib
[2] = KERN_KDSETBUF
;
315 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
316 quit("trace facility failure, KERN_KDSETBUF\n");
319 mib
[1] = KERN_KDEBUG
;
320 mib
[2] = KERN_KDSETUP
;
324 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
325 quit("trace facility failure, KERN_KDSETUP\n");
331 mib
[1] = KERN_KDEBUG
;
332 mib
[2] = KERN_KDEFLAGS
;
333 mib
[3] = KDBG_NOWRAP
;
335 mib
[5] = 0; /* no flags */
336 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
337 quit("trace facility failure, KDBG_NOWRAP\n");
341 void set_pidcheck(int pid
, int on_off_flag
)
345 kr
.type
= KDBG_TYPENONE
;
347 kr
.value2
= on_off_flag
;
348 needed
= sizeof(kd_regtype
);
350 mib
[1] = KERN_KDEBUG
;
351 mib
[2] = KERN_KDPIDTR
;
355 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
357 if (on_off_flag
== 1)
359 printf("trace facility failure, KERN_KDPIDTR,\n\tpid %d does not exist\n", pid
);
366 void set_pidexclude(int pid
, int on_off_flag
)
370 kr
.type
= KDBG_TYPENONE
;
372 kr
.value2
= on_off_flag
;
373 needed
= sizeof(kd_regtype
);
375 mib
[1] = KERN_KDEBUG
;
376 mib
[2] = KERN_KDPIDEX
;
380 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
382 if (on_off_flag
== 1)
384 printf ("pid %d does not exist\n", pid
);
394 mib
[1] = KERN_KDEBUG
;
395 mib
[2] = KERN_KDEFLAGS
;
396 mib
[3] = KDBG_FREERUN
;
399 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
400 quit("trace facility failure, KDBG_FREERUN\n");
403 void get_bufinfo(kbufinfo_t
*val
)
405 needed
= sizeof (*val
);
407 mib
[1] = KERN_KDEBUG
;
408 mib
[2] = KERN_KDGETBUF
;
412 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
413 quit("trace facility failure, KERN_KDGETBUF\n");
420 kr
.type
= KDBG_RANGETYPE
;
423 needed
= sizeof(kd_regtype
);
425 mib
[1] = KERN_KDEBUG
;
426 mib
[2] = KERN_KDSETREG
;
430 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
431 quit("trace facility failure, KERN_KDSETREG (rangetype)\n");
434 mib
[1] = KERN_KDEBUG
;
435 mib
[2] = KERN_KDSETUP
;
439 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
440 quit("trace facility failure, KERN_KDSETUP\n");
448 kr
.type
= KDBG_CLASSTYPE
;
451 needed
= sizeof(kd_regtype
);
453 mib
[1] = KERN_KDEBUG
;
454 mib
[2] = KERN_KDSETREG
;
458 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
459 quit("trace facility failure, KERN_KDSETREG (classtype)\n");
466 kr
.type
= KDBG_VALCHECK
;
471 needed
= sizeof(kd_regtype
);
473 mib
[1] = KERN_KDEBUG
;
474 mib
[2] = KERN_KDSETREG
;
478 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
479 quit("trace facility failure, KERN_KDSETREG (valcheck)\n");
486 kr
.type
= KDBG_SUBCLSTYPE
;
488 kr
.value2
= subclass
;
489 needed
= sizeof(kd_regtype
);
491 mib
[1] = KERN_KDEBUG
;
492 mib
[2] = KERN_KDSETREG
;
496 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
497 quit("trace facility failure, KERN_KDSETREG (subclstype)\n");
501 void readtrace(char *buffer
)
504 mib
[1] = KERN_KDEBUG
;
505 mib
[2] = KERN_KDREADTR
;
510 if (sysctl(mib
, 3, buffer
, &needed
, NULL
, 0) < 0)
511 quit("trace facility failure, KERN_KDREADTR\n");
515 int writetrace(int fd
)
518 mib
[1] = KERN_KDEBUG
;
519 mib
[2] = KERN_KDWRITETR
;
524 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
531 int write_command_map(int fd
)
534 mib
[1] = KERN_KDEBUG
;
535 mib
[2] = KERN_KDWRITEMAP
;
540 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
548 lookup_t
handle_lookup_event(uintptr_t thread
, int debugid
, kd_buf
*kdp
)
552 boolean_t first_record
= FALSE
;
554 hashid
= thread
& HASH_MASK
;
556 if (debugid
& DBG_FUNC_START
)
559 for (lkp
= lookup_hash
[hashid
]; lkp
; lkp
= lkp
->lk_next
) {
560 if (lkp
->lk_thread
== thread
)
564 if (first_record
== FALSE
)
567 if ((lkp
= lookup_freelist
))
568 lookup_freelist
= lkp
->lk_next
;
570 lkp
= (lookup_t
)malloc(sizeof(struct lookup
));
572 lkp
->lk_thread
= thread
;
574 lkp
->lk_next
= lookup_hash
[hashid
];
575 lookup_hash
[hashid
] = lkp
;
578 if (first_record
== TRUE
) {
579 lkp
->lk_pathptr
= lkp
->lk_pathname
;
580 lkp
->lk_dvp
= kdp
->arg1
;
582 if (lkp
->lk_pathptr
> &lkp
->lk_pathname
[NUMPARMS
-4])
585 *lkp
->lk_pathptr
++ = kdp
->arg1
;
587 *lkp
->lk_pathptr
++ = kdp
->arg2
;
588 *lkp
->lk_pathptr
++ = kdp
->arg3
;
589 *lkp
->lk_pathptr
++ = kdp
->arg4
;
590 *lkp
->lk_pathptr
= 0;
597 void delete_lookup_event(uintptr_t thread
, lookup_t lkp_to_delete
)
603 hashid
= thread
& HASH_MASK
;
605 if ((lkp
= lookup_hash
[hashid
])) {
606 if (lkp
== lkp_to_delete
)
607 lookup_hash
[hashid
] = lkp
->lk_next
;
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
;
620 lkp
->lk_next
= lookup_freelist
;
621 lookup_freelist
= lkp
;
628 void insert_start_event(uintptr_t thread
, int debugid
, uint64_t now
)
633 hashid
= thread
& HASH_MASK
;
635 for (evp
= event_hash
[hashid
]; evp
; evp
= evp
->ev_next
) {
636 if (evp
->ev_thread
== thread
&& evp
->ev_debugid
== debugid
)
640 if ((evp
= event_freelist
))
641 event_freelist
= evp
->ev_next
;
643 evp
= (event_t
)malloc(sizeof(struct event
));
645 evp
->ev_thread
= thread
;
646 evp
->ev_debugid
= debugid
;
648 evp
->ev_next
= event_hash
[hashid
];
649 event_hash
[hashid
] = evp
;
651 evp
->ev_timestamp
= now
;
656 uint64_t consume_start_event(uintptr_t thread
, int debugid
, uint64_t now
)
661 uint64_t elapsed
= 0;
663 hashid
= thread
& HASH_MASK
;
665 if ((evp
= event_hash
[hashid
])) {
666 if (evp
->ev_thread
== thread
&& evp
->ev_debugid
== debugid
)
667 event_hash
[hashid
] = evp
->ev_next
;
671 for (evp
= evp
->ev_next
; evp
; evp
= evp
->ev_next
) {
673 if (evp
->ev_thread
== thread
&& evp
->ev_debugid
== debugid
) {
674 evp_prev
->ev_next
= evp
->ev_next
;
681 elapsed
= now
- evp
->ev_timestamp
;
683 evp
->ev_next
= event_freelist
;
684 event_freelist
= evp
;
695 uint32_t buffer_size
;
702 if ((fd
= open(logfile
, O_TRUNC
|O_WRONLY
|O_CREAT
, 0777)) == -1) {
703 perror("Can't open logfile");
706 get_bufinfo(&bufinfo
);
708 if (bufinfo
.nolog
!= 1) {
710 set_enable(0); /* disable logging*/
712 get_bufinfo(&bufinfo
);
715 if (bufinfo
.flags
& KDBG_WRAPPED
)
716 printf("Buffer has wrapped\n");
718 printf("Buffer has not wrapped\n");
720 buffer_size
= 1000000 * sizeof(kd_buf
);
721 buffer
= malloc(buffer_size
);
723 if (buffer
== (char *) 0)
724 quit("can't allocate memory for tracing info\n");
726 read_command_map(0, 0);
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;
733 write(fd
, &raw_header
, sizeof(RAW_header
));
735 size
= total_threads
* sizeof(kd_threadmap
);
736 write(fd
, (char *)mapptr
, size
);
738 pad_size
= 4096 - ((sizeof(RAW_header
) + size
) & 4095);
739 memset(pad_buf
, 0, pad_size
);
741 write(fd
, pad_buf
, pad_size
);
744 needed
= buffer_size
;
750 write(fd
, buffer
, needed
* sizeof(kd_buf
));
763 int try_writetrace
= 1;
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
;
776 memset(&kd_tmp
, 0, sizeof(kd_tmp
));
778 if ((fd
= open(logfile
, O_TRUNC
|O_WRONLY
|O_CREAT
, 0777)) == -1) {
779 perror("Can't open logfile");
782 if (use_current_buf
== 0) {
784 * grab the number of cpus and scale the buffer size
789 len
= sizeof(num_cpus
);
791 sysctl(mib
, 2, &num_cpus
, &len
, NULL
, 0);
794 nbufs
= BASE_EVENTS
* num_cpus
;
809 /* Get kernel buffer information */
810 get_bufinfo(&bufinfo
);
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
));
817 if (use_current_buf
== 0)
820 if (write_command_map(fd
)) {
824 read_command_map(0, 0);
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;
831 write(fd
, &raw_header
, sizeof(RAW_header
));
833 size
= total_threads
* sizeof(kd_threadmap
);
834 write(fd
, (char *)mapptr
, size
);
836 pad_size
= 4096 - ((sizeof(RAW_header
) + size
) & 4095);
837 memset(pad_buf
, 0, pad_size
);
839 write(fd
, pad_buf
, pad_size
);
841 sample_window_abs
= (uint64_t)((double)US_TO_SLEEP
* divisor
);
843 next_window_begins
= mach_absolute_time() + sample_window_abs
;
846 ending_abstime
= mach_absolute_time() + (uint64_t)((double)secs_to_run
* (double)1000000 * divisor
);
847 ms_to_run
= secs_to_run
* 1000;
850 last_time_written
= mach_absolute_time();
852 while (LogRAW_flag
) {
853 current_abs
= mach_absolute_time();
855 if (try_writetrace
) {
862 current_abs
= mach_absolute_time();
864 printf("wrote %d events - elapsed time = %.1f secs\n",
865 (int)needed
, ((double)(current_abs
- last_time_written
) / divisor
) / 1000000);
867 last_time_written
= current_abs
;
871 if (try_writetrace
== 0) {
873 if (next_window_begins
> current_abs
)
874 us_to_adjust
= US_TO_SLEEP
- (uint32_t)((double)(next_window_begins
- current_abs
) / divisor
);
876 us_to_adjust
= US_TO_SLEEP
;
878 next_window_begins
= current_abs
+ sample_window_abs
;
880 us_to_sleep
= US_TO_SLEEP
- us_to_adjust
;
882 next_window_begins
= current_abs
+ (uint64_t)((double)(us_to_sleep
+ US_TO_SLEEP
) * divisor
);
887 get_bufinfo(&bufinfo
);
889 if (bufinfo
.flags
& KDBG_WRAPPED
)
890 printf("lost events\n");
892 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
896 if (bufinfo
.flags
& KDBG_WRAPPED
) {
898 kd
= (kd_buf
*) buffer
;
900 kd_tmp
.timestamp
= kd
[0].timestamp
;
901 kd_tmp
.debugid
= TRACE_LOST_EVENTS
;
903 write(fd
, &kd_tmp
, sizeof(kd_tmp
));
905 write(fd
, buffer
, needed
* sizeof(kd_buf
));
907 if (verbose_flag
&& needed
> nbufs
)
908 printf("needed = %ld\n", needed
);
911 current_abs
= mach_absolute_time();
913 if (current_abs
> ending_abstime
)
915 ms_to_run
= (ending_abstime
- current_abs
) / (1000 * 1000);
932 uint32_t buffer_size
;
939 uint32_t count_of_names
;
940 double last_event_time
= 0.0;
944 get_bufinfo(&bufinfo
);
946 if (bufinfo
.nolog
!= 1) {
948 set_enable(0); /* disable logging*/
951 if (bufinfo
.flags
& KDBG_WRAPPED
)
952 printf("Buffer has wrapped\n");
954 printf("Buffer has not wrapped\n");
960 fd
= open(RAW_file
, O_RDONLY
);
963 perror("Can't open file");
966 if (read(fd
, &raw_header
, sizeof(RAW_header
)) != sizeof(RAW_header
)) {
967 perror("read failed");
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;
975 lseek(fd
, (off_t
)0, SEEK_SET
);
977 if (read(fd
, &raw_header
.thread_count
, sizeof(int)) != sizeof(int)) {
978 perror("read failed");
982 count_of_names
= raw_header
.thread_count
;
983 trace_time
= raw_header
.TOD_secs
;
985 printf("%s\n", ctime(&trace_time
));
987 buffer_size
= 1000000 * sizeof(kd_buf
);
988 buffer
= malloc(buffer_size
);
990 if (buffer
== (char *) 0)
991 quit("can't allocate memory for tracing info\n");
993 kd
= (kd_buf
*)buffer
;
995 read_command_map(fd
, count_of_names
);
1006 double event_elapsed_time
;
1009 boolean_t ending_event
;
1018 if (!readRAW_flag
) {
1019 needed
= buffer_size
;
1022 mib
[1] = KERN_KDEBUG
;
1023 mib
[2] = KERN_KDREADTR
;
1027 if (sysctl(mib
, 3, buffer
, &needed
, NULL
, 0) < 0)
1028 quit("trace facility failure, KERN_KDREADTR\n");
1035 uint32_t bytes_read
;
1037 bytes_read
= read(fd
, buffer
, buffer_size
);
1039 if (bytes_read
== -1) {
1040 perror("read failed");
1043 count
= bytes_read
/ sizeof(kd_buf
);
1048 for (kdp
= &kd
[0], i
= 0; i
< count
; i
++, kdp
++) {
1051 debugid
= kdp
->debugid
;
1052 debugid_base
= debugid
& DBG_FUNC_MASK
;
1053 now
= kdp
->timestamp
& KDBG_TIMESTAMP_MASK
;
1059 cpunum
= kdbg_get_cpu(kdp
);
1062 if (lines
== 64 || firsttime
)
1064 prevdelta
= now
- prevdelta
;
1069 x
= (double)prevdelta
;
1072 fprintf(output_file
, "\n\nNumber of microsecs since in last page %8.1f\n", x
);
1077 * Output description row to output file (make sure to format correctly for 32-bit and 64-bit)
1079 fprintf(output_file
,
1081 " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n"
1083 " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n"
1089 if (io_lines
> 15000) {
1090 fcntl(output_fd
, F_FLUSH_DATA
, 0);
1097 if (debugid_base
== VFS_LOOKUP
) {
1098 lkp
= handle_lookup_event(thread
, debugid
, kdp
);
1100 if ( !lkp
|| !(debugid
& DBG_FUNC_END
))
1106 if (last_event_time
)
1107 y
= x
- last_event_time
;
1110 last_event_time
= x
;
1111 ending_event
= FALSE
;
1113 find_thread_command(kdp
, &command
);
1116 * The internal use TRACE points clutter the output.
1117 * Print them only if in verbose mode.
1121 /* Is this entry of Class DBG_TRACE */
1122 if ((debugid
>> 24) == DBG_TRACE
) {
1123 if (((debugid
>> 16) & 0xff) != DBG_TRACE_INFO
)
1131 if ((debugid
& DBG_FUNC_START
) || debugid
== MACH_MAKERUNNABLE
) {
1133 if (debugid_base
!= BSC_thread_terminate
&& debugid_base
!= BSC_exit
) {
1135 if (debugid
== MACH_MAKERUNNABLE
)
1136 t_thread
= kdp
->arg1
;
1140 insert_start_event(t_thread
, debugid_base
, now
);
1143 } else if ((debugid
& DBG_FUNC_END
) || debugid
== MACH_STKHANDOFF
|| debugid
== MACH_SCHEDULED
) {
1145 if (debugid
== MACH_STKHANDOFF
|| debugid
== MACH_SCHEDULED
) {
1146 t_debugid
= MACH_MAKERUNNABLE
;
1147 t_thread
= kdp
->arg2
;
1149 t_debugid
= debugid_base
;
1152 event_elapsed_time
= (double)consume_start_event(t_thread
, t_debugid
, now
);
1153 event_elapsed_time
/= divisor
;
1154 ending_event
= TRUE
;
1156 if (event_elapsed_time
== 0 && (debugid
== MACH_STKHANDOFF
|| debugid
== MACH_SCHEDULED
))
1157 ending_event
= FALSE
;
1163 sprintf(&outbuf
[0], "(%-10.1f)", event_elapsed_time
);
1165 * fix that right paren
1170 ch
= strchr (&outbuf
[0], ')');
1177 while (ch
!= &outbuf
[0])
1189 if (match_debugid(debugid_base
, dbgmessge
, &dmsgindex
)) {
1191 fprintf(output_file
, "%13.1f %10.1f%s %-28x ", x
, y
, outbuf
, debugid_base
);
1193 fprintf(output_file
, "%13.1f %10.1f %-28x ", x
, y
, debugid_base
);
1196 fprintf(output_file
, "%13.1f %10.1f%s %-28.28s ", x
, y
, outbuf
, dbgmessge
);
1198 fprintf(output_file
, "%13.1f %10.1f %-28.28s ", x
, y
, dbgmessge
);
1204 strptr
= (char *)lkp
->lk_pathname
;
1207 * print the tail end of the pathname
1209 len
= strlen(strptr
);
1216 fprintf(output_file
, "%-16lx %-51s %-16lx %-2d %s\n", lkp
->lk_dvp
, &strptr
[len
], thread
, cpunum
, command
);
1218 fprintf(output_file
, "%-8x %-51s %-8lx %-2d %s\n", (unsigned int)lkp
->lk_dvp
, &strptr
[len
], thread
, cpunum
, command
);
1220 delete_lookup_event(thread
, lkp
);
1223 fprintf(output_file
, "%-16lx %-16lx %-16lx %-16lx %-16lx %-2d %s\n", kdp
->arg1
, kdp
->arg2
, kdp
->arg3
, kdp
->arg4
, thread
, cpunum
, command
);
1225 fprintf(output_file
, "%-8lx %-8lx %-8lx %-8lx %-8lx %-2d %s\n", kdp
->arg1
, kdp
->arg2
, kdp
->arg3
, kdp
->arg4
, thread
, cpunum
, command
);
1233 set_enable(1); /* re-enable kernel logging */
1238 void signal_handler(int sig
)
1240 ptrace(PT_KILL
, pid
, (caddr_t
)0, 0);
1242 * child is gone; no need to disable the pid
1248 void signal_handler_RAW(int sig
)
1255 int main(argc
, argv
, env
)
1260 extern char *optarg
;
1265 char *output_filename
= NULL
;
1267 for (i
= 1; i
< argc
; i
++) {
1268 if (strcmp("-X", argv
[i
]) == 0) {
1269 force_32bit_exec
= 1;
1273 if (force_32bit_exec
) {
1274 if (0 != reexec_to_match_lp64ness(FALSE
)) {
1275 fprintf(stderr
, "Could not re-execute: %d\n", errno
);
1279 if (0 != reexec_to_match_kernel()) {
1280 fprintf(stderr
, "Could not re-execute: %d\n", errno
);
1284 if (setiopolicy_np(IOPOL_TYPE_DISK
, IOPOL_SCOPE_PROCESS
, IOPOL_PASSIVE
) < 0) {
1285 printf("setiopolicy failed\n");
1288 output_file
= stdout
;
1291 while ((ch
= getopt(argc
, argv
, "hedEk:irb:gc:p:s:tR:L:l:S:F:a:x:Xnfvo:P")) != EOF
)
1295 case 'h': /* help */
1299 secs_to_run
= argtoi('S', "decimal number", optarg
, 10);
1301 case 'a': /* set tracing on a pid */
1303 pid
= argtoi('a', "decimal number", optarg
, 10);
1305 case 'x': /* exclude a pid from tracing */
1307 pid
= argtoi('x', "decimal number", optarg
, 10);
1319 signal(SIGINT
, signal_handler_RAW
);
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);
1344 fprintf(stderr
, "A maximum of four values can be specified with -k\n");
1370 nbufs
= argtoi('b', "decimal number", optarg
, 10);
1374 class = argtoi('c', "decimal number", optarg
, 10);
1379 subclass
= argtoi('s', "decimal number", optarg
, 10);
1382 if (class_flag
!= 1)
1383 { fprintf(stderr
, "-p must follow -c\n");
1386 class2
= argtoi('p', "decimal number", optarg
, 10);
1392 output_filename
= optarg
;
1395 frequency
= argtoi('F', "decimal number", optarg
, 10);
1409 cfile
= argv
[optind
];
1411 printf("Code file is %s \n", cfile
);
1412 if (parse_codefile(cfile
) == -1)
1420 printf("-E flag needs an executable to launch\n");
1426 if (pid_flag
&& pid_exflag
)
1428 fprintf(stderr
, "Can't use both -a and -x flag together\n");
1432 if (subclass_flag
&& !class_flag
) {
1433 fprintf(stderr
,"Must define a class ('c') with the subclass ('s') option\n");
1437 if (kval_flag
&& (subclass_flag
|| class_flag
))
1439 fprintf(stderr
,"Don't use class or subclass with the 'k' code options.\n");
1443 if (output_filename
&& !trace_flag
&& !readRAW_flag
)
1445 fprintf(stderr
, "When using 'o' option, must use the 't' or 'R' option too\n");
1450 get_bufinfo(&bufinfo
);
1452 if (bufinfo
.nolog
== 0)
1453 use_current_buf
= 1;
1460 set_pidcheck(pid
, 0); /* disable pid check for given pid */
1463 else if (pid_exflag
)
1465 set_pidexclude(pid
, 0); /* disable pid exclusion for given pid */
1480 if (!init_flag
&& !LogRAW_flag
)
1482 fprintf(stderr
,"The -b flag must be used with the -i flag\n");
1496 get_bufinfo(&bufinfo
);
1498 printf("The kernel buffer settings are:\n");
1500 if (bufinfo
.flags
& KDBG_BUFINIT
)
1501 printf("\tKernel buffer is initialized\n");
1503 printf("\tKernel buffer is not initialized\n");
1505 printf("\t number of buf entries = %d\n", bufinfo
.nkdbufs
);
1509 if (bufinfo
.flags
& KDBG_MAPINIT
)
1510 printf("\tKernel thread map is initialized\n");
1512 printf("\tKernel thread map is not initialized\n");
1513 printf("\t number of thread entries = %d\n", bufinfo
.nkdthreads
);
1517 printf("\tBuffer logging is disabled\n");
1519 printf("\tBuffer logging is enabled\n");
1522 printf("\tkernel flags = 0x%x\n", bufinfo
.flags
);
1524 if (bufinfo
.flags
& KDBG_NOWRAP
)
1525 printf("\tKernel buffer wrap is disabled\n");
1527 printf("\tKernel buffer wrap is enabled\n");
1529 if (bufinfo
.flags
& KDBG_RANGECHECK
)
1530 printf("\tCollection within a range is enabled\n");
1532 printf("\tCollection within a range is disabled\n");
1534 if (bufinfo
.flags
& KDBG_VALCHECK
)
1535 printf("\tCollecting specific code values is enabled\n");
1537 printf("\tCollecting specific code values is disabled\n");
1539 if (bufinfo
.flags
& KDBG_PIDCHECK
)
1540 printf("\tCollection based on pid is enabled\n");
1542 printf("\tCollection based on pid is disabled\n");
1544 if (bufinfo
.flags
& KDBG_PIDEXCLUDE
)
1545 printf("\tCollection based on pid exclusion is enabled\n");
1547 printf("\tCollection based on pid exclusion is disabled\n");
1549 if (bufinfo
.bufid
== -1)
1550 printf("\tKernel buffer is not controlled by any process.\n");
1552 printf("\tKernel buffer is controlled by proc id [%d]\n", bufinfo
.bufid
);
1569 fprintf(stderr
, "Starting program: %s\n", argv
[optind
]);
1573 switch ((pid
= vfork()))
1580 ptrace(PT_TRACE_ME
, 0, (caddr_t
)0, 0);
1581 execve(argv
[optind
], &argv
[optind
], environ
);
1587 signal(SIGINT
, signal_handler
);
1588 set_pidcheck(pid
, 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 */
1595 else if (enable_flag
)
1598 set_pidcheck(pid
, 1);
1599 else if (pid_exflag
)
1600 set_pidexclude(pid
, 1);
1604 if (output_filename
)
1606 if (((output_fd
= open(output_filename
, O_CREAT
| O_TRUNC
| O_WRONLY
| O_APPEND
, 0644)) < 0 ) ||
1607 !(output_file
= fdopen(output_fd
, "w")))
1609 fprintf(stderr
, "Cannot open file \"%s\" for writing.\n", output_filename
);
1612 setbuffer(output_file
, &sbuffer
[0], SBUFFER_SIZE
);
1614 if (fcntl(output_fd
, F_NOCACHE
, 1) < 0)
1617 fprintf(stderr
, "Warning: setting F_NOCACHE on %s, failed\n", output_filename
);
1620 if (!LogRAW_flag
&& !logRAW_flag
)
1621 setbuffer(output_file
, &sbuffer
[0], SBUFFER_SIZE
);
1623 if (trace_flag
|| readRAW_flag
)
1625 else if (LogRAW_flag
)
1627 else if (logRAW_flag
)
1641 set_enable(1); /* re-enable kernel logging */
1651 usage(int short_help
)
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");
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");
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");
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");
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");
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");
1697 (void)fprintf(stderr
, "usage: trace -g\n");
1698 (void)fprintf(stderr
, "\tGet the kernel buffer settings.\n\n");
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");
1705 (void)fprintf(stderr
, "usage: trace -r\n");
1706 (void)fprintf(stderr
, "\tRemove the kernel trace buffer. Set controls to default.\n\n");
1708 (void)fprintf(stderr
, "usage: trace -n\n");
1709 (void)fprintf(stderr
, "\tDisables kernel buffer wrap around.\n\n");
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");
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");
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");
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");
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");
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");
1764 argtoi(flag
, req
, str
, base
)
1772 ret
= (int)strtol(str
, &cp
, base
);
1773 if (cp
== str
|| *cp
)
1774 errx(EINVAL
, "-%c flag requires a %s", flag
, req
);
1779 static unsigned long
1780 argtoul(flag
, req
, str
, base
)
1788 ret
= (int)strtoul(str
, &cp
, base
);
1789 if (cp
== str
|| *cp
)
1790 errx(EINVAL
, "-%c flag requires a %s", flag
, req
);
1796 * comparison function for qsort
1799 int debugid_compar(p1
, p2
)
1803 if (p1
->debugid
> p2
->debugid
)
1805 else if (p1
->debugid
== p2
->debugid
)
1813 * Find the debugid code in the list and return its index
1815 static int binary_search(list
, lowbound
, highbound
, code
)
1817 int lowbound
, highbound
;
1828 mid
= (low
+ high
) / 2;
1833 return (-1); /* failed */
1834 else if ( low
+ 1 >= high
)
1836 /* We have a match */
1837 if (list
[high
].debugid
== code
)
1839 else if (list
[low
].debugid
== code
)
1842 return(-1); /* search failed */
1844 else if (code
< list
[mid
].debugid
)
1853 parse_codefile(char *filename
)
1856 int i
, j
, count
, line
;
1857 struct stat stat_buf
;
1858 unsigned long file_size
;
1859 char *file_addr
, *endp
;
1861 if ((fd
= open(filename
, O_RDONLY
, 0)) == -1)
1863 printf("Failed to open code description file %s\n",filename
);
1867 if (fstat(fd
, &stat_buf
) == -1)
1869 printf("Error: Can't fstat file: %s\n", filename
);
1874 * For some reason mapping files with zero size fails
1875 * so it has to be handled specially.
1877 file_size
= stat_buf
.st_size
;
1879 if (stat_buf
.st_size
!= 0)
1881 if ((file_addr
= mmap(0, stat_buf
.st_size
, PROT_READ
|PROT_WRITE
,
1882 MAP_PRIVATE
|MAP_FILE
, fd
, 0)) == (char*) -1)
1884 printf("Error: Can't map file: %s\n", filename
);
1891 printf("Error: Zero sized file: %s\n", filename
);
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.
1904 for (count
= 0, j
=1; j
< file_size
; j
++)
1906 if (file_addr
[j
] == '\n')
1912 printf("Error: No codes in %s\n", filename
);
1917 * Fudge the count to accomodate the last line in the file -
1918 * in case it doesn't end in a newline.
1922 if ((codesc
= (code_type_t
*)malloc(count
* sizeof(code_type_t
))) == 0 ) {
1923 printf("Failed to allocate buffer for code descriptions\n");
1927 bzero((char *)codesc
, count
* sizeof(code_type_t
));
1930 for (line
= 1, i
= 0, j
= 0; j
< file_size
&& i
< count
; i
++)
1932 /* Skip blank lines */
1933 while (file_addr
[j
] == '\n')
1939 /* Skip leading whitespace */
1940 while (file_addr
[j
] == ' ' || file_addr
[j
] == '\t')
1943 /* Get the debugid code */
1944 codesc
[i
].debugid
= strtoul(file_addr
+ j
, &endp
, 16);
1945 j
= endp
- file_addr
;
1947 if (codesc
[i
].debugid
== 0)
1949 /* We didn't find a debugid code - skip this line */
1951 printf("Error: while parsing line %d, skip\n", line
);
1952 while (file_addr
[j
] != '\n' && j
< file_size
)
1959 /* Skip whitespace */
1960 while (file_addr
[j
] == ' ' || file_addr
[j
] == '\t')
1963 /* Get around old file that had count at the beginning */
1964 if (file_addr
[j
] == '\n')
1966 /* missing debugid string - skip */
1968 printf("Error: while parsing line %d, (0x%x) skip\n", line
, codesc
[i
].debugid
);
1976 /* Next is the debugid string terminated by a newline */
1977 codesc
[i
].debug_string
= &file_addr
[j
];
1979 /* Null out the newline terminator */
1980 while ((j
< file_size
) && (file_addr
[j
] != '\n'))
1982 file_addr
[j
] = '\0'; /* File must be read-write */
1985 codenum
++; /*Index into codesc is 0 to codenum-1 */
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
);
1996 qsort((void *)codesc
, codenum
, sizeof(code_type_t
), debugid_compar
);
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
);
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
);
2015 int match_debugid(unsigned int xx
, char * debugstr
, int * yy
)
2022 if (codesc
[codeindx_cache
].debugid
!= xx
)
2023 indx
= binary_search(codesc
, 0, (codenum
-1), xx
);
2025 indx
= codeindx_cache
;
2028 return(indx
); /* match failed */
2030 bcopy(&codesc
[indx
].debug_string
[0], debugstr
,80);
2032 codeindx_cache
= indx
;
2033 return(0); /* match success */
2039 read_command_map(int fd
, int count
)
2046 total_threads
= count
;
2047 size
= count
* sizeof(kd_threadmap
);
2049 get_bufinfo(&bufinfo
);
2051 total_threads
= bufinfo
.nkdthreads
;
2052 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
2055 nthreads
= total_threads
* 2;
2058 printf("Size of map table is %d, thus %d entries\n", (int)size
, total_threads
);
2061 if ((mapptr
= (kd_threadmap
*) malloc(size
)))
2062 bzero (mapptr
, size
);
2066 printf("Thread map is not initialized -- this is not fatal\n");
2073 if (read(fd
, mapptr
, size
) != size
) {
2075 printf("Can't read the thread map -- this is not fatal\n");
2081 if (raw_header
.version_no
!= RAW_VERSION0
) {
2082 offset
= lseek(fd
, (off_t
)0, SEEK_CUR
);
2083 offset
= (offset
+ (4095)) & ~4095;
2085 lseek(fd
, offset
, SEEK_SET
);
2088 /* Now read the threadmap */
2090 mib
[1] = KERN_KDEBUG
;
2091 mib
[2] = KERN_KDTHRMAP
;
2094 mib
[5] = 0; /* no flags */
2095 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0)
2097 /* This is not fatal -- just means I cant map command strings */
2099 printf("Can't read the thread map -- this is not fatal\n");
2105 for (i
= 0; i
< total_threads
; i
++)
2106 create_map_entry(mapptr
[i
].thread
, &mapptr
[i
].command
[0]);
2109 /* Dump the initial map */
2111 printf("Size of maptable returned is %ld, thus %ld entries\n", size
, (size
/sizeof(kd_threadmap
)));
2113 printf("Thread Command\n");
2114 for (i
= 0; i
< total_threads
; i
++)
2116 printf ("0x%lx %s\n",
2125 void create_map_entry(uintptr_t thread
, char *command
)
2130 if ((tme
= threadmap_freelist
))
2131 threadmap_freelist
= tme
->tm_next
;
2133 tme
= (threadmap_t
)malloc(sizeof(struct threadmap
));
2135 tme
->tm_thread
= thread
;
2136 tme
->tm_deleteme
= FALSE
;
2138 (void)strncpy (tme
->tm_command
, command
, MAXCOMLEN
);
2139 tme
->tm_command
[MAXCOMLEN
] = '\0';
2141 hashid
= thread
& HASH_MASK
;
2143 tme
->tm_next
= threadmap_hash
[hashid
];
2144 threadmap_hash
[hashid
] = tme
;
2148 void delete_thread_entry(uintptr_t thread
)
2150 threadmap_t tme
= 0;
2151 threadmap_t tme_prev
;
2154 hashid
= thread
& HASH_MASK
;
2156 if ((tme
= threadmap_hash
[hashid
])) {
2157 if (tme
->tm_thread
== thread
)
2158 threadmap_hash
[hashid
] = tme
->tm_next
;
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
;
2171 tme
->tm_next
= threadmap_freelist
;
2172 threadmap_freelist
= tme
;
2178 void find_and_insert_tmp_map_entry(uintptr_t pthread
, char *command
)
2180 threadmap_t tme
= 0;
2181 threadmap_t tme_prev
;
2184 if ((tme
= threadmap_temp
)) {
2185 if (tme
->tm_pthread
== pthread
)
2186 threadmap_temp
= tme
->tm_next
;
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
;
2199 (void)strncpy (tme
->tm_command
, command
, MAXCOMLEN
);
2200 tme
->tm_command
[MAXCOMLEN
] = '\0';
2202 delete_thread_entry(tme
->tm_thread
);
2204 hashid
= tme
->tm_thread
& HASH_MASK
;
2206 tme
->tm_next
= threadmap_hash
[hashid
];
2207 threadmap_hash
[hashid
] = tme
;
2213 void create_tmp_map_entry(uintptr_t thread
, uintptr_t pthread
)
2217 if ((tme
= threadmap_freelist
))
2218 threadmap_freelist
= tme
->tm_next
;
2220 tme
= (threadmap_t
)malloc(sizeof(struct threadmap
));
2222 tme
->tm_thread
= thread
;
2223 tme
->tm_pthread
= pthread
;
2224 tme
->tm_deleteme
= FALSE
;
2225 tme
->tm_command
[0] = '\0';
2227 tme
->tm_next
= threadmap_temp
;
2228 threadmap_temp
= tme
;
2233 find_thread_entry(uintptr_t thread
)
2238 hashid
= thread
& HASH_MASK
;
2240 for (tme
= threadmap_hash
[hashid
]; tme
; tme
= tme
->tm_next
) {
2241 if (tme
->tm_thread
== thread
)
2248 void find_thread_name(uintptr_t thread
, char **command
, boolean_t deleteme
)
2252 if ((tme
= find_thread_entry(thread
))) {
2253 *command
= tme
->tm_command
;
2255 if (deleteme
== TRUE
)
2256 tme
->tm_deleteme
= deleteme
;
2258 *command
= EMPTYSTRING
;
2262 void find_thread_command(kd_buf
*kbufp
, char **command
)
2268 thread
= kbufp
->arg5
;
2269 debugid_base
= kbufp
->debugid
& DBG_FUNC_MASK
;
2271 if (debugid_base
== BSC_exit
|| debugid_base
== MACH_STKHANDOFF
) {
2273 * Mark entry as invalid and return temp command pointer
2275 if ((tme
= find_thread_entry(thread
))) {
2277 strncpy(tmpcommand
, tme
->tm_command
, MAXCOMLEN
);
2278 *command
= tmpcommand
;
2280 if (debugid_base
== BSC_exit
|| tme
->tm_deleteme
== TRUE
)
2281 delete_thread_entry(thread
);
2283 *command
= EMPTYSTRING
;
2285 else if (debugid_base
== TRACE_DATA_NEWTHREAD
) {
2287 * Save the create thread data
2289 create_tmp_map_entry(kbufp
->arg1
, kbufp
->arg5
);
2291 else if (debugid_base
== TRACE_STRING_NEWTHREAD
) {
2293 * process new map entry
2295 find_and_insert_tmp_map_entry(kbufp
->arg5
, (char *)&kbufp
->arg1
);
2297 else if (debugid_base
== TRACE_STRING_EXEC
) {
2299 delete_thread_entry(kbufp
->arg5
);
2301 create_map_entry(kbufp
->arg5
, (char *)&kbufp
->arg1
);
2304 find_thread_name(thread
, command
, (debugid_base
== BSC_thread_terminate
));
2311 mach_timebase_info_data_t info
;
2313 if (frequency
== 0) {
2314 (void) mach_timebase_info (&info
);
2316 divisor
= ( (double)info
.denom
/ (double)info
.numer
) * 1000;
2318 divisor
= (double)frequency
/ 1000000;
2321 printf("divisor = %g\n", divisor
);