]> git.saurik.com Git - apple/system_cmds.git/blob - fs_usage.tproj/fs_usage.c
7ed62cca524c937370e8efedb9161a82b7d29b8f
[apple/system_cmds.git] / fs_usage.tproj / fs_usage.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -o fs_usage fs_usage.c
27 */
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <strings.h>
33 #include <nlist.h>
34 #include <fcntl.h>
35 #include <aio.h>
36 #include <string.h>
37 #include <dirent.h>
38 #include <libc.h>
39 #include <termios.h>
40 #include <errno.h>
41 #include <err.h>
42 #include <libutil.h>
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/time.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <sys/mman.h>
50 #include <sys/sysctl.h>
51 #include <sys/disk.h>
52
53 #ifndef KERNEL_PRIVATE
54 #define KERNEL_PRIVATE
55 #include <sys/kdebug.h>
56 #undef KERNEL_PRIVATE
57 #else
58 #include <sys/kdebug.h>
59 #endif /*KERNEL_PRIVATE*/
60
61 #import <mach/clock_types.h>
62 #import <mach/mach_time.h>
63
64
65
66 #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
67 #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
68 #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
69
70
71 #ifndef RAW_VERSION1
72 typedef struct {
73 int version_no;
74 int thread_count;
75 uint64_t TOD_secs;
76 uint32_t TOD_usecs;
77 } RAW_header;
78
79 #define RAW_VERSION0 0x55aa0000
80 #define RAW_VERSION1 0x55aa0101
81 #endif
82
83
84 #define MAXINDEX 2048
85
86 typedef struct LibraryRange {
87 uint64_t b_address;
88 uint64_t e_address;
89 } LibraryRange;
90
91 LibraryRange framework32;
92 LibraryRange framework64;
93
94
95 #define TEXT_R 0
96 #define DATA_R 1
97 #define OBJC_R 2
98 #define IMPORT_R 3
99 #define UNICODE_R 4
100 #define IMAGE_R 5
101 #define LINKEDIT_R 6
102
103
104 char *frameworkType[] = {
105 "<TEXT> ",
106 "<DATA> ",
107 "<OBJC> ",
108 "<IMPORT> ",
109 "<UNICODE> ",
110 "<IMAGE> ",
111 "<LINKEDIT>",
112 };
113
114
115 typedef struct LibraryInfo {
116 uint64_t b_address;
117 uint64_t e_address;
118 int r_type;
119 char *name;
120 } LibraryInfo;
121
122 LibraryInfo frameworkInfo[MAXINDEX];
123 int numFrameworks = 0;
124
125
126 /*
127 * MAXCOLS controls when extra data kicks in.
128 * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
129 * If NUMPARMS changes to match the kernel, it will automatically
130 * get reflected in the -w mode output.
131 */
132 #define NUMPARMS 23
133 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
134
135 #define MAXCOLS 132
136 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
137 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64
138
139
140 typedef struct th_info *th_info_t;
141
142 struct th_info {
143 th_info_t next;
144 uintptr_t thread;
145 uintptr_t child_thread;
146
147 int in_filemgr;
148 int pid;
149 int type;
150 int arg1;
151 int arg2;
152 int arg3;
153 int arg4;
154 int arg5;
155 int arg6;
156 int arg7;
157 int arg8;
158 int waited;
159 double stime;
160 uintptr_t *pathptr;
161 uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */
162 uintptr_t pathname2[NUMPARMS + 1]; /* add room for null terminator */
163 };
164
165
166 typedef struct threadmap * threadmap_t;
167
168 struct threadmap {
169 threadmap_t tm_next;
170
171 uintptr_t tm_thread;
172 unsigned int tm_setsize; /* this is a bit count */
173 unsigned long *tm_setptr; /* file descripter bitmap */
174 char tm_command[MAXCOMLEN + 1];
175 };
176
177
178 #define HASH_SIZE 1024
179 #define HASH_MASK 1023
180
181 th_info_t th_info_hash[HASH_SIZE];
182 th_info_t th_info_freelist;
183
184 threadmap_t threadmap_hash[HASH_SIZE];
185 threadmap_t threadmap_freelist;
186
187
188 int filemgr_in_progress = 0;
189 int need_new_map = 1;
190 int bias_secs = 0;
191 long last_time;
192 int wideflag = 0;
193 int columns = 0;
194
195 int one_good_pid = 0; /* Used to fail gracefully when bad pids given */
196 int select_pid_mode = 0; /* Flag set indicates that output is restricted
197 to selected pids or commands */
198
199 char *arguments = 0;
200 int argmax = 0;
201
202
203 #define USLEEP_MIN 1
204 #define USLEEP_BEHIND 2
205 #define USLEEP_MAX 32
206 int usleep_ms = USLEEP_MIN;
207
208 /*
209 * Network only or filesystem only output filter
210 * Default of zero means report all activity - no filtering
211 */
212 #define FILESYS_FILTER 0x01
213 #define NETWORK_FILTER 0x02
214 #define CACHEHIT_FILTER 0x04
215 #define EXEC_FILTER 0x08
216 #define PATHNAME_FILTER 0x10
217 #define DEFAULT_DO_NOT_FILTER 0x00
218
219 int filter_mode = CACHEHIT_FILTER;
220
221 #define NFS_DEV -1
222 #define CS_DEV -2
223
224 struct diskrec {
225 struct diskrec *next;
226 char *diskname;
227 int dev;
228 };
229
230 struct diskio {
231 struct diskio *next;
232 struct diskio *prev;
233 int type;
234 int bp;
235 int dev;
236 int blkno;
237 int iosize;
238 int io_errno;
239 uintptr_t issuing_thread;
240 uintptr_t completion_thread;
241 char issuing_command[MAXCOMLEN];
242 double issued_time;
243 double completed_time;
244 };
245
246 struct diskrec *disk_list = NULL;
247 struct diskio *free_diskios = NULL;
248 struct diskio *busy_diskios = NULL;
249
250
251 struct diskio *insert_diskio();
252 struct diskio *complete_diskio();
253 void free_diskio();
254 void print_diskio();
255
256 int check_filter_mode(struct th_info *, int, int, int, char *);
257 void format_print(struct th_info *, char *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio *);
258 void enter_event_now(uintptr_t, int, kd_buf *, char *, double);
259 void enter_event(uintptr_t, int, kd_buf *, char *, double);
260 void exit_event(char *, uintptr_t, int, int, int, int, int, int, double);
261 void extend_syscall(uintptr_t, int, kd_buf *);
262
263 char *generate_cs_disk_name(int, char *s);
264 char *find_disk_name(int);
265 void cache_disk_names();
266 void recache_disk_names();
267
268 void lookup_name(uint64_t user_addr, char **type, char **name);
269 int ReadSharedCacheMap(const char *, LibraryRange *, char *);
270 void SortFrameworkAddresses();
271
272 void fs_usage_fd_set(uintptr_t, unsigned int);
273 int fs_usage_fd_isset(uintptr_t, unsigned int);
274 void fs_usage_fd_clear(uintptr_t, unsigned int);
275
276 void init_arguments_buffer();
277 int get_real_command_name(int, char *, int);
278
279 void delete_all_events();
280 void delete_event(th_info_t);
281 th_info_t add_event(uintptr_t, int);
282 th_info_t find_event(uintptr_t, int);
283 void mark_thread_waited(uintptr_t);
284
285 void read_command_map();
286 void delete_all_map_entries();
287 void create_map_entry(uintptr_t, int, char *);
288 void delete_map_entry(uintptr_t);
289 threadmap_t find_map_entry(uintptr_t);
290
291 void getdivisor();
292 void argtopid();
293 void set_remove();
294 void set_pidcheck();
295 void set_pidexclude();
296 int quit();
297
298
299 #define CLASS_MASK 0xff000000
300 #define CSC_MASK 0xffff0000
301 #define BSC_INDEX(type) ((type >> 2) & 0x3fff)
302
303
304 #define TRACE_DATA_NEWTHREAD 0x07000004
305 #define TRACE_DATA_EXEC 0x07000008
306 #define TRACE_STRING_NEWTHREAD 0x07010004
307 #define TRACE_STRING_EXEC 0x07010008
308
309 #define MACH_vmfault 0x01300008
310 #define MACH_pageout 0x01300004
311 #define MACH_sched 0x01400000
312 #define MACH_stkhandoff 0x01400008
313 #define MACH_idle 0x01400024
314 #define VFS_LOOKUP 0x03010090
315
316 #define BSC_thread_terminate 0x040c05a4
317
318 #define Throttled 0x3010184
319 #define SPEC_ioctl 0x3060000
320 #define proc_exit 0x4010004
321
322 #define P_DISKIO 0x03020000
323 #define P_DISKIO_DONE 0x03020004
324 #define P_DISKIO_TYPE 0x03020068
325 #define P_DISKIO_MASK (CSC_MASK | 0x4)
326
327 #define P_DISKIO_READ 0x00000008
328 #define P_DISKIO_ASYNC 0x00000010
329 #define P_DISKIO_META 0x00000020
330 #define P_DISKIO_PAGING 0x00000040
331 #define P_DISKIO_THROTTLE 0x00000080
332 #define P_DISKIO_PASSIVE 0x00000100
333
334 #define P_WrData 0x03020000
335 #define P_RdData 0x03020008
336 #define P_WrMeta 0x03020020
337 #define P_RdMeta 0x03020028
338 #define P_PgOut 0x03020040
339 #define P_PgIn 0x03020048
340
341 #define P_CS_ReadChunk 0x0a000200
342 #define P_CS_ReadChunkDone 0x0a000280
343 #define P_CS_WriteChunk 0x0a000210
344 #define P_CS_WriteChunkDone 0x0a000290
345
346 #define P_CS_Originated_Read 0x0a000500
347 #define P_CS_Originated_ReadDone 0x0a000580
348 #define P_CS_Originated_Write 0x0a000510
349 #define P_CS_Originated_WriteDone 0x0a000590
350 #define P_CS_MetaRead 0x0a000900
351 #define P_CS_MetaReadDone 0x0a000980
352 #define P_CS_MetaWrite 0x0a000910
353 #define P_CS_MetaWriteDone 0x0a000990
354 #define P_CS_SYNC_DISK 0x0a008000
355
356
357 #define MSC_map_fd 0x010c00ac
358
359 #define BSC_BASE 0x040C0000
360 #define MSC_BASE 0x010C0000
361
362 // Network related codes
363 #define BSC_recvmsg 0x040C006C
364 #define BSC_sendmsg 0x040C0070
365 #define BSC_recvfrom 0x040C0074
366 #define BSC_accept 0x040C0078
367 #define BSC_select 0x040C0174
368 #define BSC_socket 0x040C0184
369 #define BSC_connect 0x040C0188
370 #define BSC_bind 0x040C01A0
371 #define BSC_listen 0x040C01A8
372 #define BSC_sendto 0x040C0214
373 #define BSC_socketpair 0x040C021C
374
375 #define BSC_exit 0x040C0004
376 #define BSC_read 0x040C000C
377 #define BSC_write 0x040C0010
378 #define BSC_open 0x040C0014
379 #define BSC_close 0x040C0018
380 #define BSC_link 0x040C0024
381 #define BSC_unlink 0x040C0028
382 #define BSC_chdir 0x040c0030
383 #define BSC_fchdir 0x040c0034
384 #define BSC_mknod 0x040C0038
385 #define BSC_chmod 0x040C003C
386 #define BSC_chown 0x040C0040
387 #define BSC_getfsstat 0x040C0048
388 #define BSC_access 0x040C0084
389 #define BSC_chflags 0x040C0088
390 #define BSC_fchflags 0x040C008C
391 #define BSC_sync 0x040C0090
392 #define BSC_dup 0x040C00A4
393 #define BSC_ioctl 0x040C00D8
394 #define BSC_revoke 0x040C00E0
395 #define BSC_symlink 0x040C00E4
396 #define BSC_readlink 0x040C00E8
397 #define BSC_execve 0x040C00EC
398 #define BSC_umask 0x040C00F0
399 #define BSC_chroot 0x040C00F4
400 #define BSC_msync 0x040C0104
401 #define BSC_dup2 0x040C0168
402 #define BSC_fcntl 0x040C0170
403 #define BSC_fsync 0x040C017C
404 #define BSC_readv 0x040C01E0
405 #define BSC_writev 0x040C01E4
406 #define BSC_fchown 0x040C01EC
407 #define BSC_fchmod 0x040C01F0
408 #define BSC_rename 0x040C0200
409 #define BSC_mkfifo 0x040c0210
410 #define BSC_mkdir 0x040C0220
411 #define BSC_rmdir 0x040C0224
412 #define BSC_utimes 0x040C0228
413 #define BSC_futimes 0x040C022C
414 #define BSC_pread 0x040C0264
415 #define BSC_pwrite 0x040C0268
416 #define BSC_statfs 0x040C0274
417 #define BSC_fstatfs 0x040C0278
418 #define BSC_unmount 0x040C027C
419 #define BSC_mount 0x040C029C
420 #define BSC_stat 0x040C02F0
421 #define BSC_fstat 0x040C02F4
422 #define BSC_lstat 0x040C02F8
423 #define BSC_pathconf 0x040C02FC
424 #define BSC_fpathconf 0x040C0300
425 #define BSC_getdirentries 0x040C0310
426 #define BSC_mmap 0x040c0314
427 #define BSC_lseek 0x040c031c
428 #define BSC_truncate 0x040C0320
429 #define BSC_ftruncate 0x040C0324
430 #define BSC_undelete 0x040C0334
431 #define BSC_statv 0x040C0364
432 #define BSC_lstatv 0x040C0368
433 #define BSC_fstatv 0x040C036C
434 #define BSC_mkcomplex 0x040C0360
435 #define BSC_getattrlist 0x040C0370
436 #define BSC_setattrlist 0x040C0374
437 #define BSC_getdirentriesattr 0x040C0378
438 #define BSC_exchangedata 0x040C037C
439 #define BSC_checkuseraccess 0x040C0380
440 #define BSC_searchfs 0x040C0384
441 #define BSC_delete 0x040C0388
442 #define BSC_copyfile 0x040C038C
443 #define BSC_getxattr 0x040C03A8
444 #define BSC_fgetxattr 0x040C03AC
445 #define BSC_setxattr 0x040C03B0
446 #define BSC_fsetxattr 0x040C03B4
447 #define BSC_removexattr 0x040C03B8
448 #define BSC_fremovexattr 0x040C03BC
449 #define BSC_listxattr 0x040C03C0
450 #define BSC_flistxattr 0x040C03C4
451 #define BSC_fsctl 0x040C03C8
452 #define BSC_posix_spawn 0x040C03D0
453 #define BSC_open_extended 0x040C0454
454 #define BSC_stat_extended 0x040C045C
455 #define BSC_lstat_extended 0x040C0460
456 #define BSC_fstat_extended 0x040C0464
457 #define BSC_chmod_extended 0x040C0468
458 #define BSC_fchmod_extended 0x040C046C
459 #define BSC_access_extended 0x040C0470
460 #define BSC_mkfifo_extended 0x040C048C
461 #define BSC_mkdir_extended 0x040C0490
462 #define BSC_load_shared_file 0x040C04A0
463 #define BSC_aio_fsync 0x040C04E4
464 #define BSC_aio_return 0x040C04E8
465 #define BSC_aio_suspend 0x040C04EC
466 #define BSC_aio_cancel 0x040C04F0
467 #define BSC_aio_error 0x040C04F4
468 #define BSC_aio_read 0x040C04F8
469 #define BSC_aio_write 0x040C04FC
470 #define BSC_lio_listio 0x040C0500
471 #define BSC_sendfile 0x040C0544
472 #define BSC_stat64 0x040C0548
473 #define BSC_fstat64 0x040C054C
474 #define BSC_lstat64 0x040C0550
475 #define BSC_stat64_extended 0x040C0554
476 #define BSC_lstat64_extended 0x040C0558
477 #define BSC_fstat64_extended 0x040C055C
478 #define BSC_getdirentries64 0x040C0560
479 #define BSC_statfs64 0x040C0564
480 #define BSC_fstatfs64 0x040C0568
481 #define BSC_getfsstat64 0x040C056C
482 #define BSC_pthread_chdir 0x040C0570
483 #define BSC_pthread_fchdir 0x040C0574
484 #define BSC_lchown 0x040C05B0
485
486 #define BSC_read_nocancel 0x040c0630
487 #define BSC_write_nocancel 0x040c0634
488 #define BSC_open_nocancel 0x040c0638
489 #define BSC_close_nocancel 0x040c063c
490 #define BSC_recvmsg_nocancel 0x040c0644
491 #define BSC_sendmsg_nocancel 0x040c0648
492 #define BSC_recvfrom_nocancel 0x040c064c
493 #define BSC_accept_nocancel 0x040c0650
494 #define BSC_msync_nocancel 0x040c0654
495 #define BSC_fcntl_nocancel 0x040c0658
496 #define BSC_select_nocancel 0x040c065c
497 #define BSC_fsync_nocancel 0x040c0660
498 #define BSC_connect_nocancel 0x040c0664
499 #define BSC_readv_nocancel 0x040c066c
500 #define BSC_writev_nocancel 0x040c0670
501 #define BSC_sendto_nocancel 0x040c0674
502 #define BSC_pread_nocancel 0x040c0678
503 #define BSC_pwrite_nocancel 0x040c067c
504 #define BSC_aio_suspend_nocancel 0x40c0694
505
506 #define BSC_msync_extended 0x040e0104
507 #define BSC_pread_extended 0x040e0264
508 #define BSC_pwrite_extended 0x040e0268
509 #define BSC_mmap_extended 0x040e0314
510 #define BSC_mmap_extended2 0x040f0314
511
512 // Carbon File Manager support
513 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
514 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
515 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
516 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
517 #define FILEMGR_PBCREATEFORK 0x1e000030
518 #define FILEMGR_PBDELETEFORK 0x1e000034
519 #define FILEMGR_PBITERATEFORK 0x1e000038
520 #define FILEMGR_PBOPENFORK 0x1e00003c
521 #define FILEMGR_PBREADFORK 0x1e000040
522 #define FILEMGR_PBWRITEFORK 0x1e000044
523 #define FILEMGR_PBALLOCATEFORK 0x1e000048
524 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
525 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
526 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
527 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
528 #define FILEMGR_PBMAKEFSREF 0x1e00005c
529 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
530 #define FILEMGR_PBMOVEOBJECT 0x1e000064
531 #define FILEMGR_PBOPENITERATOR 0x1e000068
532 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
533 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
534 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
535 #define FILEMGR_FSREFMAKEPATH 0x1e000078
536 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
537
538 #define FILEMGR_PBGETCATINFO 0x1e010000
539 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
540 #define FILEMGR_PBHGETFINFO 0x1e010008
541 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
542 #define FILEMGR_PBHCREATE 0x1e010010
543 #define FILEMGR_PBHOPENDF 0x1e010014
544 #define FILEMGR_PBHOPENRF 0x1e010018
545 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
546 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
547 #define FILEMGR_PBHMAPID 0x1e010024
548 #define FILEMGR_PBHMAPNAME 0x1e010028
549 #define FILEMGR_PBCLOSE 0x1e01002c
550 #define FILEMGR_PBFLUSHFILE 0x1e010030
551 #define FILEMGR_PBGETEOF 0x1e010034
552 #define FILEMGR_PBSETEOF 0x1e010038
553 #define FILEMGR_PBGETFPOS 0x1e01003c
554 #define FILEMGR_PBREAD 0x1e010040
555 #define FILEMGR_PBWRITE 0x1e010044
556 #define FILEMGR_PBGETFCBINFO 0x1e010048
557 #define FILEMGR_PBSETFINFO 0x1e01004c
558 #define FILEMGR_PBALLOCATE 0x1e010050
559 #define FILEMGR_PBALLOCCONTIG 0x1e010054
560 #define FILEMGR_PBSETFPOS 0x1e010058
561 #define FILEMGR_PBSETCATINFO 0x1e01005c
562 #define FILEMGR_PBGETVOLPARMS 0x1e010060
563 #define FILEMGR_PBSETVINFO 0x1e010064
564 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
565 #define FILEMGR_PBHGETVINFO 0x1e01006c
566 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
567 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
568 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
569 #define FILEMGR_PBFLUSHVOL 0x1e01007c
570 #define FILEMGR_PBHRENAME 0x1e010080
571 #define FILEMGR_PBCATMOVE 0x1e010084
572 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
573 #define FILEMGR_PBHDELETE 0x1e01008c
574 #define FILEMGR_PBDIRCREATE 0x1e010090
575 #define FILEMGR_PBCATSEARCH 0x1e010094
576 #define FILEMGR_PBHSETFLOCK 0x1e010098
577 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
578 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
579 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
580
581
582 #define FILEMGR_CLASS 0x1e
583 #define FILEMGR_BASE 0x1e000000
584
585 #define FMT_DEFAULT 0
586 #define FMT_FD 1
587 #define FMT_FD_IO 2
588 #define FMT_FD_2 3
589 #define FMT_SOCKET 4
590 #define FMT_PGIN 5
591 #define FMT_PGOUT 6
592 #define FMT_CACHEHIT 7
593 #define FMT_DISKIO 8
594 #define FMT_LSEEK 9
595 #define FMT_PREAD 10
596 #define FMT_FTRUNC 11
597 #define FMT_TRUNC 12
598 #define FMT_SELECT 13
599 #define FMT_OPEN 14
600 #define FMT_AIO_FSYNC 15
601 #define FMT_AIO_RETURN 16
602 #define FMT_AIO_SUSPEND 17
603 #define FMT_AIO_CANCEL 18
604 #define FMT_AIO 19
605 #define FMT_LIO_LISTIO 20
606 #define FMT_MSYNC 21
607 #define FMT_FCNTL 22
608 #define FMT_ACCESS 23
609 #define FMT_CHMOD 24
610 #define FMT_FCHMOD 25
611 #define FMT_CHMOD_EXT 26
612 #define FMT_FCHMOD_EXT 27
613 #define FMT_CHFLAGS 28
614 #define FMT_FCHFLAGS 29
615 #define FMT_IOCTL 30
616 #define FMT_MMAP 31
617 #define FMT_UMASK 32
618 #define FMT_SENDFILE 33
619 #define FMT_SPEC_IOCTL 34
620 #define FMT_MOUNT 35
621 #define FMT_UNMOUNT 36
622 #define FMT_DISKIO_CS 37
623 #define FMT_SYNC_DISK_CS 38
624
625 #define MAX_BSD_SYSCALL 512
626
627 struct bsd_syscall {
628 char *sc_name;
629 int sc_format;
630 } bsd_syscalls[MAX_BSD_SYSCALL];
631
632
633 int bsd_syscall_types[] = {
634 BSC_recvmsg,
635 BSC_recvmsg_nocancel,
636 BSC_sendmsg,
637 BSC_sendmsg_nocancel,
638 BSC_recvfrom,
639 BSC_recvfrom_nocancel,
640 BSC_accept,
641 BSC_accept_nocancel,
642 BSC_select,
643 BSC_select_nocancel,
644 BSC_socket,
645 BSC_connect,
646 BSC_connect_nocancel,
647 BSC_bind,
648 BSC_listen,
649 BSC_sendto,
650 BSC_sendto_nocancel,
651 BSC_socketpair,
652 BSC_read,
653 BSC_read_nocancel,
654 BSC_write,
655 BSC_write_nocancel,
656 BSC_open,
657 BSC_open_nocancel,
658 BSC_close,
659 BSC_close_nocancel,
660 BSC_link,
661 BSC_unlink,
662 BSC_chdir,
663 BSC_fchdir,
664 BSC_mknod,
665 BSC_chmod,
666 BSC_chown,
667 BSC_access,
668 BSC_chflags,
669 BSC_fchflags,
670 BSC_sync,
671 BSC_dup,
672 BSC_revoke,
673 BSC_symlink,
674 BSC_readlink,
675 BSC_exit,
676 BSC_execve,
677 BSC_posix_spawn,
678 BSC_umask,
679 BSC_chroot,
680 BSC_dup2,
681 BSC_fsync,
682 BSC_fsync_nocancel,
683 BSC_readv,
684 BSC_readv_nocancel,
685 BSC_writev,
686 BSC_writev_nocancel,
687 BSC_fchown,
688 BSC_fchmod,
689 BSC_rename,
690 BSC_mkfifo,
691 BSC_mkdir,
692 BSC_rmdir,
693 BSC_utimes,
694 BSC_futimes,
695 BSC_pread,
696 BSC_pread_nocancel,
697 BSC_pwrite,
698 BSC_pwrite_nocancel,
699 BSC_statfs,
700 BSC_fstatfs,
701 BSC_stat,
702 BSC_fstat,
703 BSC_lstat,
704 BSC_mount,
705 BSC_unmount,
706 BSC_pathconf,
707 BSC_fpathconf,
708 BSC_getdirentries,
709 BSC_mmap,
710 BSC_lseek,
711 BSC_truncate,
712 BSC_ftruncate,
713 BSC_undelete,
714 BSC_statv,
715 BSC_lstatv,
716 BSC_fstatv,
717 BSC_mkcomplex,
718 BSC_getattrlist,
719 BSC_setattrlist,
720 BSC_getdirentriesattr,
721 BSC_exchangedata,
722 BSC_checkuseraccess,
723 BSC_searchfs,
724 BSC_delete,
725 BSC_copyfile,
726 BSC_getxattr,
727 BSC_fgetxattr,
728 BSC_setxattr,
729 BSC_fsetxattr,
730 BSC_removexattr,
731 BSC_fremovexattr,
732 BSC_listxattr,
733 BSC_flistxattr,
734 BSC_fsctl,
735 BSC_open_extended,
736 BSC_stat_extended,
737 BSC_lstat_extended,
738 BSC_fstat_extended,
739 BSC_chmod_extended,
740 BSC_fchmod_extended,
741 BSC_access_extended,
742 BSC_mkfifo_extended,
743 BSC_mkdir_extended,
744 BSC_load_shared_file,
745 BSC_aio_fsync,
746 BSC_aio_return,
747 BSC_aio_suspend,
748 BSC_aio_suspend_nocancel,
749 BSC_aio_cancel,
750 BSC_aio_error,
751 BSC_aio_read,
752 BSC_aio_write,
753 BSC_lio_listio,
754 BSC_lchown,
755 BSC_sendfile,
756 BSC_msync,
757 BSC_msync_nocancel,
758 BSC_fcntl,
759 BSC_fcntl_nocancel,
760 BSC_ioctl,
761 BSC_stat64,
762 BSC_fstat64,
763 BSC_lstat64,
764 BSC_stat64_extended,
765 BSC_lstat64_extended,
766 BSC_fstat64_extended,
767 BSC_getdirentries64,
768 BSC_statfs64,
769 BSC_fstatfs64,
770 BSC_pthread_chdir,
771 BSC_pthread_fchdir,
772 BSC_getfsstat,
773 BSC_getfsstat64,
774 0
775 };
776
777
778 #define MAX_FILEMGR 512
779
780 struct filemgr_call {
781 char *fm_name;
782 } filemgr_calls[MAX_FILEMGR];
783
784
785 int filemgr_call_types[] = {
786 FILEMGR_PBGETCATALOGINFO,
787 FILEMGR_PBGETCATALOGINFOBULK,
788 FILEMGR_PBCREATEFILEUNICODE,
789 FILEMGR_PBCREATEDIRECTORYUNICODE,
790 FILEMGR_PBCREATEFORK,
791 FILEMGR_PBDELETEFORK,
792 FILEMGR_PBITERATEFORK,
793 FILEMGR_PBOPENFORK,
794 FILEMGR_PBREADFORK,
795 FILEMGR_PBWRITEFORK,
796 FILEMGR_PBALLOCATEFORK,
797 FILEMGR_PBDELETEOBJECT,
798 FILEMGR_PBEXCHANGEOBJECT,
799 FILEMGR_PBGETFORKCBINFO,
800 FILEMGR_PBGETVOLUMEINFO,
801 FILEMGR_PBMAKEFSREF,
802 FILEMGR_PBMAKEFSREFUNICODE,
803 FILEMGR_PBMOVEOBJECT,
804 FILEMGR_PBOPENITERATOR,
805 FILEMGR_PBRENAMEUNICODE,
806 FILEMGR_PBSETCATALOGINFO,
807 FILEMGR_PBSETVOLUMEINFO,
808 FILEMGR_FSREFMAKEPATH,
809 FILEMGR_FSPATHMAKEREF,
810
811 FILEMGR_PBGETCATINFO,
812 FILEMGR_PBGETCATINFOLITE,
813 FILEMGR_PBHGETFINFO,
814 FILEMGR_PBXGETVOLINFO,
815 FILEMGR_PBHCREATE,
816 FILEMGR_PBHOPENDF,
817 FILEMGR_PBHOPENRF,
818 FILEMGR_PBHGETDIRACCESS,
819 FILEMGR_PBHSETDIRACCESS,
820 FILEMGR_PBHMAPID,
821 FILEMGR_PBHMAPNAME,
822 FILEMGR_PBCLOSE,
823 FILEMGR_PBFLUSHFILE,
824 FILEMGR_PBGETEOF,
825 FILEMGR_PBSETEOF,
826 FILEMGR_PBGETFPOS,
827 FILEMGR_PBREAD,
828 FILEMGR_PBWRITE,
829 FILEMGR_PBGETFCBINFO,
830 FILEMGR_PBSETFINFO,
831 FILEMGR_PBALLOCATE,
832 FILEMGR_PBALLOCCONTIG,
833 FILEMGR_PBSETFPOS,
834 FILEMGR_PBSETCATINFO,
835 FILEMGR_PBGETVOLPARMS,
836 FILEMGR_PBSETVINFO,
837 FILEMGR_PBMAKEFSSPEC,
838 FILEMGR_PBHGETVINFO,
839 FILEMGR_PBCREATEFILEIDREF,
840 FILEMGR_PBDELETEFILEIDREF,
841 FILEMGR_PBRESOLVEFILEIDREF,
842 FILEMGR_PBFLUSHVOL,
843 FILEMGR_PBHRENAME,
844 FILEMGR_PBCATMOVE,
845 FILEMGR_PBEXCHANGEFILES,
846 FILEMGR_PBHDELETE,
847 FILEMGR_PBDIRCREATE,
848 FILEMGR_PBCATSEARCH,
849 FILEMGR_PBHSETFLOCK,
850 FILEMGR_PBHRSTFLOCK,
851 FILEMGR_PBLOCKRANGE,
852 FILEMGR_PBUNLOCKRANGE,
853 0
854 };
855
856
857
858 #define MAX_PIDS 256
859 int pids[MAX_PIDS];
860
861 int num_of_pids = 0;
862 int exclude_pids = 0;
863 int exclude_default_pids = 1;
864
865
866 struct kinfo_proc *kp_buffer = 0;
867 int kp_nentries = 0;
868
869 #define EVENT_BASE 60000
870
871 int num_events = EVENT_BASE;
872
873
874 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
875 #define DBG_FUNC_MASK 0xfffffffc
876
877 double divisor = 0.0; /* Trace divisor converts to microseconds */
878
879 int mib[6];
880 size_t needed;
881 char *my_buffer;
882
883 kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
884
885
886 /* defines for tracking file descriptor state */
887 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
888 thread that we will track */
889
890 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
891 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
892
893 int trace_enabled = 0;
894 int set_remove_flag = 1;
895
896 char *RAW_file = (char *)0;
897 int RAW_flag = 0;
898 int RAW_fd = 0;
899
900 uint64_t sample_TOD_secs;
901 uint32_t sample_TOD_usecs;
902
903 double bias_now = 0.0;
904 double start_time = 0.0;
905 double end_time = 999999999999.9;
906
907
908 void set_numbufs();
909 void set_init();
910 void set_enable();
911 void sample_sc();
912 int quit();
913
914 /*
915 * signal handlers
916 */
917
918 void leave() /* exit under normal conditions -- INT handler */
919 {
920 int i;
921 void set_enable();
922 void set_pidcheck();
923 void set_pidexclude();
924 void set_remove();
925
926 fflush(0);
927
928 set_enable(0);
929
930 if (exclude_pids == 0) {
931 for (i = 0; i < num_of_pids; i++)
932 set_pidcheck(pids[i], 0);
933 }
934 else {
935 for (i = 0; i < num_of_pids; i++)
936 set_pidexclude(pids[i], 0);
937 }
938 set_remove();
939 exit(0);
940 }
941
942
943 int
944 quit(s)
945 char *s;
946 {
947 if (trace_enabled)
948 set_enable(0);
949
950 /*
951 * This flag is turned off when calling
952 * quit() due to a set_remove() failure.
953 */
954 if (set_remove_flag)
955 set_remove();
956
957 fprintf(stderr, "fs_usage: ");
958 if (s)
959 fprintf(stderr, "%s", s);
960
961 exit(1);
962 }
963
964
965 void get_screenwidth()
966 {
967 struct winsize size;
968
969 columns = MAXCOLS;
970
971 if (isatty(1)) {
972 if (ioctl(1, TIOCGWINSZ, &size) != -1) {
973 columns = size.ws_col;
974
975 if (columns > MAXWIDTH)
976 columns = MAXWIDTH;
977 }
978 }
979 }
980
981
982 void sigwinch()
983 {
984 if (!wideflag)
985 get_screenwidth();
986 }
987
988
989 void getdivisor()
990 {
991 struct mach_timebase_info mti;
992
993 mach_timebase_info(&mti);
994
995 divisor = ((double)mti.denom / (double)mti.numer) * 1000;
996 }
997
998
999 int
1000 exit_usage(char *myname) {
1001
1002 fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd]....]\n", myname);
1003 fprintf(stderr, " -e exclude the specified list of pids from the sample\n");
1004 fprintf(stderr, " and exclude fs_usage by default\n");
1005 fprintf(stderr, " -w force wider, detailed, output\n");
1006 fprintf(stderr, " -f Output is based on the mode provided\n");
1007 fprintf(stderr, " mode = \"network\" Show only network related output\n");
1008 fprintf(stderr, " mode = \"filesys\" Show only file system related output\n");
1009 fprintf(stderr, " mode = \"pathname\" Show only pathname related output\n");
1010 fprintf(stderr, " mode = \"exec\" Show only execs\n");
1011 fprintf(stderr, " mode = \"cachehit\" In addition, show cachehits\n");
1012 fprintf(stderr, " -R specifies a raw trace file to process\n");
1013 fprintf(stderr, " -S if -R is specified, selects a start point in microseconds\n");
1014 fprintf(stderr, " -E if -R is specified, selects an end point in microseconds\n");
1015 fprintf(stderr, " pid selects process(s) to sample\n");
1016 fprintf(stderr, " cmd selects process(s) matching command string to sample\n");
1017 fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
1018 fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
1019 fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
1020
1021 exit(1);
1022 }
1023
1024
1025 int filemgr_index(type) {
1026
1027 if (type & 0x10000)
1028 return (((type >> 2) & 0x3fff) + 256);
1029
1030 return (((type >> 2) & 0x3fff));
1031 }
1032
1033
1034 void init_tables(void)
1035 { int i;
1036 int type;
1037 int code;
1038
1039
1040 for (i = 0; i < MAX_BSD_SYSCALL; i++) {
1041 bsd_syscalls[i].sc_name = NULL;
1042 bsd_syscalls[i].sc_format = FMT_DEFAULT;
1043 }
1044
1045 for (i = 0; i < MAX_FILEMGR; i++) {
1046 filemgr_calls[i].fm_name = NULL;
1047 }
1048
1049 for (i = 0; (type = bsd_syscall_types[i]); i++) {
1050
1051 code = BSC_INDEX(type);
1052
1053 if (code >= MAX_BSD_SYSCALL) {
1054 printf("BSD syscall init (%x): type exceeds table size\n", type);
1055 continue;
1056 }
1057 switch (type) {
1058
1059 case BSC_sendfile:
1060 bsd_syscalls[code].sc_name = "sendfile";
1061 bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */
1062 break; /* once we add an extended info trace event */
1063
1064 case BSC_recvmsg:
1065 case BSC_recvmsg_nocancel:
1066 bsd_syscalls[code].sc_name = "recvmsg";
1067 bsd_syscalls[code].sc_format = FMT_FD_IO;
1068 break;
1069
1070 case BSC_sendmsg:
1071 case BSC_sendmsg_nocancel:
1072 bsd_syscalls[code].sc_name = "sendmsg";
1073 bsd_syscalls[code].sc_format = FMT_FD_IO;
1074 break;
1075
1076 case BSC_recvfrom:
1077 case BSC_recvfrom_nocancel:
1078 bsd_syscalls[code].sc_name = "recvfrom";
1079 bsd_syscalls[code].sc_format = FMT_FD_IO;
1080 break;
1081
1082 case BSC_sendto:
1083 case BSC_sendto_nocancel:
1084 bsd_syscalls[code].sc_name = "sendto";
1085 bsd_syscalls[code].sc_format = FMT_FD_IO;
1086 break;
1087
1088 case BSC_select:
1089 case BSC_select_nocancel:
1090 bsd_syscalls[code].sc_name = "select";
1091 bsd_syscalls[code].sc_format = FMT_SELECT;
1092 break;
1093
1094 case BSC_accept:
1095 case BSC_accept_nocancel:
1096 bsd_syscalls[code].sc_name = "accept";
1097 bsd_syscalls[code].sc_format = FMT_FD_2;
1098 break;
1099
1100 case BSC_socket:
1101 bsd_syscalls[code].sc_name = "socket";
1102 bsd_syscalls[code].sc_format = FMT_SOCKET;
1103 break;
1104
1105 case BSC_connect:
1106 case BSC_connect_nocancel:
1107 bsd_syscalls[code].sc_name = "connect";
1108 bsd_syscalls[code].sc_format = FMT_FD;
1109 break;
1110
1111 case BSC_bind:
1112 bsd_syscalls[code].sc_name = "bind";
1113 bsd_syscalls[code].sc_format = FMT_FD;
1114 break;
1115
1116 case BSC_listen:
1117 bsd_syscalls[code].sc_name = "listen";
1118 bsd_syscalls[code].sc_format = FMT_FD;
1119 break;
1120
1121 case BSC_mmap:
1122 bsd_syscalls[code].sc_name = "mmap";
1123 bsd_syscalls[code].sc_format = FMT_MMAP;
1124 break;
1125
1126 case BSC_socketpair:
1127 bsd_syscalls[code].sc_name = "socketpair";
1128 break;
1129
1130 case BSC_getxattr:
1131 bsd_syscalls[code].sc_name = "getxattr";
1132 break;
1133
1134 case BSC_setxattr:
1135 bsd_syscalls[code].sc_name = "setxattr";
1136 break;
1137
1138 case BSC_removexattr:
1139 bsd_syscalls[code].sc_name = "removexattr";
1140 break;
1141
1142 case BSC_listxattr:
1143 bsd_syscalls[code].sc_name = "listxattr";
1144 break;
1145
1146 case BSC_stat:
1147 bsd_syscalls[code].sc_name = "stat";
1148 break;
1149
1150 case BSC_stat64:
1151 bsd_syscalls[code].sc_name = "stat64";
1152 break;
1153
1154 case BSC_stat_extended:
1155 bsd_syscalls[code].sc_name = "stat_extended";
1156 break;
1157
1158 case BSC_stat64_extended:
1159 bsd_syscalls[code].sc_name = "stat_extended64";
1160 break;
1161
1162 case BSC_mount:
1163 bsd_syscalls[code].sc_name = "mount";
1164 bsd_syscalls[code].sc_format = FMT_MOUNT;
1165 break;
1166
1167 case BSC_unmount:
1168 bsd_syscalls[code].sc_name = "unmount";
1169 bsd_syscalls[code].sc_format = FMT_UNMOUNT;
1170 break;
1171
1172 case BSC_exit:
1173 bsd_syscalls[code].sc_name = "exit";
1174 break;
1175
1176 case BSC_execve:
1177 bsd_syscalls[code].sc_name = "execve";
1178 break;
1179
1180 case BSC_posix_spawn:
1181 bsd_syscalls[code].sc_name = "posix_spawn";
1182 break;
1183
1184 case BSC_load_shared_file:
1185 bsd_syscalls[code].sc_name = "load_sf";
1186 break;
1187
1188 case BSC_open:
1189 case BSC_open_nocancel:
1190 bsd_syscalls[code].sc_name = "open";
1191 bsd_syscalls[code].sc_format = FMT_OPEN;
1192 break;
1193
1194 case BSC_open_extended:
1195 bsd_syscalls[code].sc_name = "open_extended";
1196 bsd_syscalls[code].sc_format = FMT_OPEN;
1197 break;
1198
1199 case BSC_dup:
1200 bsd_syscalls[code].sc_name = "dup";
1201 bsd_syscalls[code].sc_format = FMT_FD_2;
1202 break;
1203
1204 case BSC_dup2:
1205 bsd_syscalls[code].sc_name = "dup2";
1206 bsd_syscalls[code].sc_format = FMT_FD_2;
1207 break;
1208
1209 case BSC_close:
1210 case BSC_close_nocancel:
1211 bsd_syscalls[code].sc_name = "close";
1212 bsd_syscalls[code].sc_format = FMT_FD;
1213 break;
1214
1215 case BSC_read:
1216 case BSC_read_nocancel:
1217 bsd_syscalls[code].sc_name = "read";
1218 bsd_syscalls[code].sc_format = FMT_FD_IO;
1219 break;
1220
1221 case BSC_write:
1222 case BSC_write_nocancel:
1223 bsd_syscalls[code].sc_name = "write";
1224 bsd_syscalls[code].sc_format = FMT_FD_IO;
1225 break;
1226
1227 case BSC_fgetxattr:
1228 bsd_syscalls[code].sc_name = "fgetxattr";
1229 bsd_syscalls[code].sc_format = FMT_FD;
1230 break;
1231
1232 case BSC_fsetxattr:
1233 bsd_syscalls[code].sc_name = "fsetxattr";
1234 bsd_syscalls[code].sc_format = FMT_FD;
1235 break;
1236
1237 case BSC_fremovexattr:
1238 bsd_syscalls[code].sc_name = "fremovexattr";
1239 bsd_syscalls[code].sc_format = FMT_FD;
1240 break;
1241
1242 case BSC_flistxattr:
1243 bsd_syscalls[code].sc_name = "flistxattr";
1244 bsd_syscalls[code].sc_format = FMT_FD;
1245 break;
1246
1247 case BSC_fstat:
1248 bsd_syscalls[code].sc_name = "fstat";
1249 bsd_syscalls[code].sc_format = FMT_FD;
1250 break;
1251
1252 case BSC_fstat64:
1253 bsd_syscalls[code].sc_name = "fstat64";
1254 bsd_syscalls[code].sc_format = FMT_FD;
1255 break;
1256
1257 case BSC_fstat_extended:
1258 bsd_syscalls[code].sc_name = "fstat_extended";
1259 bsd_syscalls[code].sc_format = FMT_FD;
1260 break;
1261
1262 case BSC_fstat64_extended:
1263 bsd_syscalls[code].sc_name = "fstat64_extended";
1264 bsd_syscalls[code].sc_format = FMT_FD;
1265 break;
1266
1267 case BSC_lstat:
1268 bsd_syscalls[code].sc_name = "lstat";
1269 break;
1270
1271 case BSC_lstat64:
1272 bsd_syscalls[code].sc_name = "lstat64";
1273 break;
1274
1275 case BSC_lstat_extended:
1276 bsd_syscalls[code].sc_name = "lstat_extended";
1277 break;
1278
1279 case BSC_lstat64_extended:
1280 bsd_syscalls[code].sc_name = "lstat_extended64";
1281 break;
1282
1283 case BSC_lstatv:
1284 bsd_syscalls[code].sc_name = "lstatv";
1285 break;
1286
1287 case BSC_link:
1288 bsd_syscalls[code].sc_name = "link";
1289 break;
1290
1291 case BSC_unlink:
1292 bsd_syscalls[code].sc_name = "unlink";
1293 break;
1294
1295 case BSC_mknod:
1296 bsd_syscalls[code].sc_name = "mknod";
1297 break;
1298
1299 case BSC_umask:
1300 bsd_syscalls[code].sc_name = "umask";
1301 bsd_syscalls[code].sc_format = FMT_UMASK;
1302 break;
1303
1304 case BSC_chmod:
1305 bsd_syscalls[code].sc_name = "chmod";
1306 bsd_syscalls[code].sc_format = FMT_CHMOD;
1307 break;
1308
1309 case BSC_chmod_extended:
1310 bsd_syscalls[code].sc_name = "chmod_extended";
1311 bsd_syscalls[code].sc_format = FMT_CHMOD_EXT;
1312 break;
1313
1314 case BSC_fchmod:
1315 bsd_syscalls[code].sc_name = "fchmod";
1316 bsd_syscalls[code].sc_format = FMT_FCHMOD;
1317 break;
1318
1319 case BSC_fchmod_extended:
1320 bsd_syscalls[code].sc_name = "fchmod_extended";
1321 bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT;
1322 break;
1323
1324 case BSC_chown:
1325 bsd_syscalls[code].sc_name = "chown";
1326 break;
1327
1328 case BSC_lchown:
1329 bsd_syscalls[code].sc_name = "lchown";
1330 break;
1331
1332 case BSC_fchown:
1333 bsd_syscalls[code].sc_name = "fchown";
1334 bsd_syscalls[code].sc_format = FMT_FD;
1335 break;
1336
1337 case BSC_access:
1338 bsd_syscalls[code].sc_name = "access";
1339 bsd_syscalls[code].sc_format = FMT_ACCESS;
1340 break;
1341
1342 case BSC_access_extended:
1343 bsd_syscalls[code].sc_name = "access_extended";
1344 break;
1345
1346 case BSC_chdir:
1347 bsd_syscalls[code].sc_name = "chdir";
1348 break;
1349
1350 case BSC_pthread_chdir:
1351 bsd_syscalls[code].sc_name = "pthread_chdir";
1352 break;
1353
1354 case BSC_chroot:
1355 bsd_syscalls[code].sc_name = "chroot";
1356 break;
1357
1358 case BSC_utimes:
1359 bsd_syscalls[code].sc_name = "utimes";
1360 break;
1361
1362 case BSC_delete:
1363 bsd_syscalls[code].sc_name = "delete-Carbon";
1364 break;
1365
1366 case BSC_undelete:
1367 bsd_syscalls[code].sc_name = "undelete";
1368 break;
1369
1370 case BSC_revoke:
1371 bsd_syscalls[code].sc_name = "revoke";
1372 break;
1373
1374 case BSC_fsctl:
1375 bsd_syscalls[code].sc_name = "fsctl";
1376 break;
1377
1378 case BSC_chflags:
1379 bsd_syscalls[code].sc_name = "chflags";
1380 bsd_syscalls[code].sc_format = FMT_CHFLAGS;
1381 break;
1382
1383 case BSC_fchflags:
1384 bsd_syscalls[code].sc_name = "fchflags";
1385 bsd_syscalls[code].sc_format = FMT_FCHFLAGS;
1386 break;
1387
1388 case BSC_fchdir:
1389 bsd_syscalls[code].sc_name = "fchdir";
1390 bsd_syscalls[code].sc_format = FMT_FD;
1391 break;
1392
1393 case BSC_pthread_fchdir:
1394 bsd_syscalls[code].sc_name = "pthread_fchdir";
1395 bsd_syscalls[code].sc_format = FMT_FD;
1396 break;
1397
1398 case BSC_futimes:
1399 bsd_syscalls[code].sc_name = "futimes";
1400 bsd_syscalls[code].sc_format = FMT_FD;
1401 break;
1402
1403 case BSC_sync:
1404 bsd_syscalls[code].sc_name = "sync";
1405 break;
1406
1407 case BSC_symlink:
1408 bsd_syscalls[code].sc_name = "symlink";
1409 break;
1410
1411 case BSC_readlink:
1412 bsd_syscalls[code].sc_name = "readlink";
1413 break;
1414
1415 case BSC_fsync:
1416 case BSC_fsync_nocancel:
1417 bsd_syscalls[code].sc_name = "fsync";
1418 bsd_syscalls[code].sc_format = FMT_FD;
1419 break;
1420
1421 case BSC_readv:
1422 case BSC_readv_nocancel:
1423 bsd_syscalls[code].sc_name = "readv";
1424 bsd_syscalls[code].sc_format = FMT_FD_IO;
1425 break;
1426
1427 case BSC_writev:
1428 case BSC_writev_nocancel:
1429 bsd_syscalls[code].sc_name = "writev";
1430 bsd_syscalls[code].sc_format = FMT_FD_IO;
1431 break;
1432
1433 case BSC_pread:
1434 case BSC_pread_nocancel:
1435 bsd_syscalls[code].sc_name = "pread";
1436 bsd_syscalls[code].sc_format = FMT_PREAD;
1437 break;
1438
1439 case BSC_pwrite:
1440 case BSC_pwrite_nocancel:
1441 bsd_syscalls[code].sc_name = "pwrite";
1442 bsd_syscalls[code].sc_format = FMT_PREAD;
1443 break;
1444
1445 case BSC_mkdir:
1446 bsd_syscalls[code].sc_name = "mkdir";
1447 break;
1448
1449 case BSC_mkdir_extended:
1450 bsd_syscalls[code].sc_name = "mkdir_extended";
1451 break;
1452
1453 case BSC_mkfifo:
1454 bsd_syscalls[code].sc_name = "mkfifo";
1455 break;
1456
1457 case BSC_mkfifo_extended:
1458 bsd_syscalls[code].sc_name = "mkfifo_extended";
1459 break;
1460
1461 case BSC_rmdir:
1462 bsd_syscalls[code].sc_name = "rmdir";
1463 break;
1464
1465 case BSC_statfs:
1466 bsd_syscalls[code].sc_name = "statfs";
1467 break;
1468
1469 case BSC_statfs64:
1470 bsd_syscalls[code].sc_name = "statfs64";
1471 break;
1472
1473 case BSC_getfsstat:
1474 bsd_syscalls[code].sc_name = "getfsstat";
1475 break;
1476
1477 case BSC_getfsstat64:
1478 bsd_syscalls[code].sc_name = "getfsstat64";
1479 break;
1480
1481 case BSC_fstatfs:
1482 bsd_syscalls[code].sc_name = "fstatfs";
1483 bsd_syscalls[code].sc_format = FMT_FD;
1484 break;
1485
1486 case BSC_fstatfs64:
1487 bsd_syscalls[code].sc_name = "fstatfs64";
1488 bsd_syscalls[code].sc_format = FMT_FD;
1489 break;
1490
1491 case BSC_pathconf:
1492 bsd_syscalls[code].sc_name = "pathconf";
1493 break;
1494
1495 case BSC_fpathconf:
1496 bsd_syscalls[code].sc_name = "fpathconf";
1497 bsd_syscalls[code].sc_format = FMT_FD;
1498 break;
1499
1500 case BSC_getdirentries:
1501 bsd_syscalls[code].sc_name = "getdirentries";
1502 bsd_syscalls[code].sc_format = FMT_FD_IO;
1503 break;
1504
1505 case BSC_getdirentries64:
1506 bsd_syscalls[code].sc_name = "getdirentries64";
1507 bsd_syscalls[code].sc_format = FMT_FD_IO;
1508 break;
1509
1510 case BSC_lseek:
1511 bsd_syscalls[code].sc_name = "lseek";
1512 bsd_syscalls[code].sc_format = FMT_LSEEK;
1513 break;
1514
1515 case BSC_truncate:
1516 bsd_syscalls[code].sc_name = "truncate";
1517 bsd_syscalls[code].sc_format = FMT_TRUNC;
1518 break;
1519
1520 case BSC_ftruncate:
1521 bsd_syscalls[code].sc_name = "ftruncate";
1522 bsd_syscalls[code].sc_format = FMT_FTRUNC;
1523 break;
1524
1525 case BSC_statv:
1526 bsd_syscalls[code].sc_name = "statv";
1527 break;
1528
1529 case BSC_fstatv:
1530 bsd_syscalls[code].sc_name = "fstatv";
1531 bsd_syscalls[code].sc_format = FMT_FD;
1532 break;
1533
1534 case BSC_mkcomplex:
1535 bsd_syscalls[code].sc_name = "mkcomplex";
1536 break;
1537
1538 case BSC_getattrlist:
1539 bsd_syscalls[code].sc_name = "getattrlist";
1540 break;
1541
1542 case BSC_setattrlist:
1543 bsd_syscalls[code].sc_name = "setattrlist";
1544 break;
1545
1546 case BSC_getdirentriesattr:
1547 bsd_syscalls[code].sc_name = "getdirentriesattr";
1548 bsd_syscalls[code].sc_format = FMT_FD;
1549 break;
1550
1551 case BSC_exchangedata:
1552 bsd_syscalls[code].sc_name = "exchangedata";
1553 break;
1554
1555 case BSC_rename:
1556 bsd_syscalls[code].sc_name = "rename";
1557 break;
1558
1559 case BSC_copyfile:
1560 bsd_syscalls[code].sc_name = "copyfile";
1561 break;
1562
1563 case BSC_checkuseraccess:
1564 bsd_syscalls[code].sc_name = "checkuseraccess";
1565 break;
1566
1567 case BSC_searchfs:
1568 bsd_syscalls[code].sc_name = "searchfs";
1569 break;
1570
1571 case BSC_aio_fsync:
1572 bsd_syscalls[code].sc_name = "aio_fsync";
1573 bsd_syscalls[code].sc_format = FMT_AIO_FSYNC;
1574 break;
1575
1576 case BSC_aio_return:
1577 bsd_syscalls[code].sc_name = "aio_return";
1578 bsd_syscalls[code].sc_format = FMT_AIO_RETURN;
1579 break;
1580
1581 case BSC_aio_suspend:
1582 case BSC_aio_suspend_nocancel:
1583 bsd_syscalls[code].sc_name = "aio_suspend";
1584 bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND;
1585 break;
1586
1587 case BSC_aio_cancel:
1588 bsd_syscalls[code].sc_name = "aio_cancel";
1589 bsd_syscalls[code].sc_format = FMT_AIO_CANCEL;
1590 break;
1591
1592 case BSC_aio_error:
1593 bsd_syscalls[code].sc_name = "aio_error";
1594 bsd_syscalls[code].sc_format = FMT_AIO;
1595 break;
1596
1597 case BSC_aio_read:
1598 bsd_syscalls[code].sc_name = "aio_read";
1599 bsd_syscalls[code].sc_format = FMT_AIO;
1600 break;
1601
1602 case BSC_aio_write:
1603 bsd_syscalls[code].sc_name = "aio_write";
1604 bsd_syscalls[code].sc_format = FMT_AIO;
1605 break;
1606
1607 case BSC_lio_listio:
1608 bsd_syscalls[code].sc_name = "lio_listio";
1609 bsd_syscalls[code].sc_format = FMT_LIO_LISTIO;
1610 break;
1611
1612 case BSC_msync:
1613 case BSC_msync_nocancel:
1614 bsd_syscalls[code].sc_name = "msync";
1615 bsd_syscalls[code].sc_format = FMT_MSYNC;
1616 break;
1617
1618 case BSC_fcntl:
1619 case BSC_fcntl_nocancel:
1620 bsd_syscalls[code].sc_name = "fcntl";
1621 bsd_syscalls[code].sc_format = FMT_FCNTL;
1622 break;
1623
1624 case BSC_ioctl:
1625 bsd_syscalls[code].sc_name = "ioctl";
1626 bsd_syscalls[code].sc_format = FMT_IOCTL;
1627 break;
1628 }
1629 }
1630
1631 for (i = 0; (type = filemgr_call_types[i]); i++) {
1632 char * p;
1633
1634 code = filemgr_index(type);
1635
1636 if (code >= MAX_FILEMGR) {
1637 printf("FILEMGR call init (%x): type exceeds table size\n", type);
1638 continue;
1639 }
1640 switch (type) {
1641
1642 case FILEMGR_PBGETCATALOGINFO:
1643 p = "GetCatalogInfo";
1644 break;
1645
1646 case FILEMGR_PBGETCATALOGINFOBULK:
1647 p = "GetCatalogInfoBulk";
1648 break;
1649
1650 case FILEMGR_PBCREATEFILEUNICODE:
1651 p = "CreateFileUnicode";
1652 break;
1653
1654 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1655 p = "CreateDirectoryUnicode";
1656 break;
1657
1658 case FILEMGR_PBCREATEFORK:
1659 p = "PBCreateFork";
1660 break;
1661
1662 case FILEMGR_PBDELETEFORK:
1663 p = "PBDeleteFork";
1664 break;
1665
1666 case FILEMGR_PBITERATEFORK:
1667 p = "PBIterateFork";
1668 break;
1669
1670 case FILEMGR_PBOPENFORK:
1671 p = "PBOpenFork";
1672 break;
1673
1674 case FILEMGR_PBREADFORK:
1675 p = "PBReadFork";
1676 break;
1677
1678 case FILEMGR_PBWRITEFORK:
1679 p = "PBWriteFork";
1680 break;
1681
1682 case FILEMGR_PBALLOCATEFORK:
1683 p = "PBAllocateFork";
1684 break;
1685
1686 case FILEMGR_PBDELETEOBJECT:
1687 p = "PBDeleteObject";
1688 break;
1689
1690 case FILEMGR_PBEXCHANGEOBJECT:
1691 p = "PBExchangeObject";
1692 break;
1693
1694 case FILEMGR_PBGETFORKCBINFO:
1695 p = "PBGetForkCBInfo";
1696 break;
1697
1698 case FILEMGR_PBGETVOLUMEINFO:
1699 p = "PBGetVolumeInfo";
1700 break;
1701
1702 case FILEMGR_PBMAKEFSREF:
1703 p = "PBMakeFSRef";
1704 break;
1705
1706 case FILEMGR_PBMAKEFSREFUNICODE:
1707 p = "PBMakeFSRefUnicode";
1708 break;
1709
1710 case FILEMGR_PBMOVEOBJECT:
1711 p = "PBMoveObject";
1712 break;
1713
1714 case FILEMGR_PBOPENITERATOR:
1715 p = "PBOpenIterator";
1716 break;
1717
1718 case FILEMGR_PBRENAMEUNICODE:
1719 p = "PBRenameUnicode";
1720 break;
1721
1722 case FILEMGR_PBSETCATALOGINFO:
1723 p = "SetCatalogInfo";
1724 break;
1725
1726 case FILEMGR_PBSETVOLUMEINFO:
1727 p = "SetVolumeInfo";
1728 break;
1729
1730 case FILEMGR_FSREFMAKEPATH:
1731 p = "FSRefMakePath";
1732 break;
1733
1734 case FILEMGR_FSPATHMAKEREF:
1735 p = "FSPathMakeRef";
1736 break;
1737
1738 case FILEMGR_PBGETCATINFO:
1739 p = "GetCatInfo";
1740 break;
1741
1742 case FILEMGR_PBGETCATINFOLITE:
1743 p = "GetCatInfoLite";
1744 break;
1745
1746 case FILEMGR_PBHGETFINFO:
1747 p = "PBHGetFInfo";
1748 break;
1749
1750 case FILEMGR_PBXGETVOLINFO:
1751 p = "PBXGetVolInfo";
1752 break;
1753
1754 case FILEMGR_PBHCREATE:
1755 p = "PBHCreate";
1756 break;
1757
1758 case FILEMGR_PBHOPENDF:
1759 p = "PBHOpenDF";
1760 break;
1761
1762 case FILEMGR_PBHOPENRF:
1763 p = "PBHOpenRF";
1764 break;
1765
1766 case FILEMGR_PBHGETDIRACCESS:
1767 p = "PBHGetDirAccess";
1768 break;
1769
1770 case FILEMGR_PBHSETDIRACCESS:
1771 p = "PBHSetDirAccess";
1772 break;
1773
1774 case FILEMGR_PBHMAPID:
1775 p = "PBHMapID";
1776 break;
1777
1778 case FILEMGR_PBHMAPNAME:
1779 p = "PBHMapName";
1780 break;
1781
1782 case FILEMGR_PBCLOSE:
1783 p = "PBClose";
1784 break;
1785
1786 case FILEMGR_PBFLUSHFILE:
1787 p = "PBFlushFile";
1788 break;
1789
1790 case FILEMGR_PBGETEOF:
1791 p = "PBGetEOF";
1792 break;
1793
1794 case FILEMGR_PBSETEOF:
1795 p = "PBSetEOF";
1796 break;
1797
1798 case FILEMGR_PBGETFPOS:
1799 p = "PBGetFPos";
1800 break;
1801
1802 case FILEMGR_PBREAD:
1803 p = "PBRead";
1804 break;
1805
1806 case FILEMGR_PBWRITE:
1807 p = "PBWrite";
1808 break;
1809
1810 case FILEMGR_PBGETFCBINFO:
1811 p = "PBGetFCBInfo";
1812 break;
1813
1814 case FILEMGR_PBSETFINFO:
1815 p = "PBSetFInfo";
1816 break;
1817
1818 case FILEMGR_PBALLOCATE:
1819 p = "PBAllocate";
1820 break;
1821
1822 case FILEMGR_PBALLOCCONTIG:
1823 p = "PBAllocContig";
1824 break;
1825
1826 case FILEMGR_PBSETFPOS:
1827 p = "PBSetFPos";
1828 break;
1829
1830 case FILEMGR_PBSETCATINFO:
1831 p = "PBSetCatInfo";
1832 break;
1833
1834 case FILEMGR_PBGETVOLPARMS:
1835 p = "PBGetVolParms";
1836 break;
1837
1838 case FILEMGR_PBSETVINFO:
1839 p = "PBSetVInfo";
1840 break;
1841
1842 case FILEMGR_PBMAKEFSSPEC:
1843 p = "PBMakeFSSpec";
1844 break;
1845
1846 case FILEMGR_PBHGETVINFO:
1847 p = "PBHGetVInfo";
1848 break;
1849
1850 case FILEMGR_PBCREATEFILEIDREF:
1851 p = "PBCreateFileIDRef";
1852 break;
1853
1854 case FILEMGR_PBDELETEFILEIDREF:
1855 p = "PBDeleteFileIDRef";
1856 break;
1857
1858 case FILEMGR_PBRESOLVEFILEIDREF:
1859 p = "PBResolveFileIDRef";
1860 break;
1861
1862 case FILEMGR_PBFLUSHVOL:
1863 p = "PBFlushVol";
1864 break;
1865
1866 case FILEMGR_PBHRENAME:
1867 p = "PBHRename";
1868 break;
1869
1870 case FILEMGR_PBCATMOVE:
1871 p = "PBCatMove";
1872 break;
1873
1874 case FILEMGR_PBEXCHANGEFILES:
1875 p = "PBExchangeFiles";
1876 break;
1877
1878 case FILEMGR_PBHDELETE:
1879 p = "PBHDelete";
1880 break;
1881
1882 case FILEMGR_PBDIRCREATE:
1883 p = "PBDirCreate";
1884 break;
1885
1886 case FILEMGR_PBCATSEARCH:
1887 p = "PBCatSearch";
1888 break;
1889
1890 case FILEMGR_PBHSETFLOCK:
1891 p = "PBHSetFlock";
1892 break;
1893
1894 case FILEMGR_PBHRSTFLOCK:
1895 p = "PBHRstFLock";
1896 break;
1897
1898 case FILEMGR_PBLOCKRANGE:
1899 p = "PBLockRange";
1900 break;
1901
1902 case FILEMGR_PBUNLOCKRANGE:
1903 p = "PBUnlockRange";
1904 break;
1905
1906 default:
1907 p = NULL;
1908 break;
1909 }
1910 filemgr_calls[code].fm_name = p;
1911 }
1912 }
1913
1914
1915
1916 int
1917 main(argc, argv)
1918 int argc;
1919 char *argv[];
1920 {
1921 char *myname = "fs_usage";
1922 int i;
1923 char ch;
1924
1925 if (0 != reexec_to_match_kernel()) {
1926 fprintf(stderr, "Could not re-execute: %d\n", errno);
1927 exit(1);
1928 }
1929 get_screenwidth();
1930
1931 /*
1932 * get our name
1933 */
1934 if (argc > 0) {
1935 if ((myname = rindex(argv[0], '/')) == 0)
1936 myname = argv[0];
1937 else
1938 myname++;
1939 }
1940
1941 while ((ch = getopt(argc, argv, "ewf:R:S:E:")) != EOF) {
1942
1943 switch(ch) {
1944
1945 case 'e':
1946 exclude_pids = 1;
1947 exclude_default_pids = 0;
1948 break;
1949
1950 case 'w':
1951 wideflag = 1;
1952 if ((uint)columns < MAX_WIDE_MODE_COLS)
1953 columns = MAX_WIDE_MODE_COLS;
1954 break;
1955
1956 case 'f':
1957 if (!strcmp(optarg, "network"))
1958 filter_mode |= NETWORK_FILTER;
1959 else if (!strcmp(optarg, "filesys"))
1960 filter_mode |= FILESYS_FILTER;
1961 else if (!strcmp(optarg, "cachehit"))
1962 filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */
1963 else if (!strcmp(optarg, "exec"))
1964 filter_mode |= EXEC_FILTER;
1965 else if (!strcmp(optarg, "pathname"))
1966 filter_mode |= PATHNAME_FILTER;
1967 break;
1968
1969 case 'R':
1970 RAW_flag = 1;
1971 RAW_file = optarg;
1972 break;
1973
1974 case 'S':
1975 start_time = atof(optarg);
1976 break;
1977
1978 case 'E':
1979 end_time = atof(optarg);
1980 break;
1981
1982 default:
1983 exit_usage(myname);
1984 }
1985 }
1986 if (!RAW_flag) {
1987 if ( geteuid() != 0 ) {
1988 fprintf(stderr, "'fs_usage' must be run as root...\n");
1989 exit(1);
1990 }
1991 }
1992 argc -= optind;
1993 argv += optind;
1994
1995 /*
1996 * when excluding, fs_usage should be the first in line for pids[]
1997 *
1998 * the !exclude_pids && argc == 0 catches the exclude_default_pids
1999 * case below where exclude_pids is later set and the fs_usage PID
2000 * needs to make it into pids[]
2001 */
2002 if (exclude_pids || (!exclude_pids && argc == 0)) {
2003 if (num_of_pids < (MAX_PIDS - 1))
2004 pids[num_of_pids++] = getpid();
2005 }
2006
2007 /*
2008 * If we process any list of pids/cmds, then turn off the defaults
2009 */
2010 if (argc > 0)
2011 exclude_default_pids = 0;
2012
2013 while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
2014 select_pid_mode++;
2015 argtopid(argv[0]);
2016 argc--;
2017 argv++;
2018 }
2019 /*
2020 * Exclude a set of default pids
2021 */
2022 if (exclude_default_pids) {
2023 argtopid("Terminal");
2024 argtopid("telnetd");
2025 argtopid("telnet");
2026 argtopid("sshd");
2027 argtopid("rlogind");
2028 argtopid("tcsh");
2029 argtopid("csh");
2030 argtopid("sh");
2031 exclude_pids = 1;
2032 }
2033 #if 0
2034 for (i = 0; i < num_of_pids; i++) {
2035 if (exclude_pids)
2036 fprintf(stderr, "exclude pid %d\n", pids[i]);
2037 else
2038 fprintf(stderr, "pid %d\n", pids[i]);
2039 }
2040 #endif
2041 if (!RAW_flag) {
2042 struct sigaction osa;
2043 int num_cpus;
2044 size_t len;
2045
2046 /* set up signal handlers */
2047 signal(SIGINT, leave);
2048 signal(SIGQUIT, leave);
2049
2050 sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
2051
2052 if (osa.sa_handler == SIG_DFL)
2053 signal(SIGHUP, leave);
2054 signal(SIGTERM, leave);
2055 /*
2056 * grab the number of cpus
2057 */
2058 mib[0] = CTL_HW;
2059 mib[1] = HW_NCPU;
2060 mib[2] = 0;
2061 len = sizeof(num_cpus);
2062
2063 sysctl(mib, 2, &num_cpus, &len, NULL, 0);
2064 num_events = EVENT_BASE * num_cpus;
2065 }
2066 signal(SIGWINCH, sigwinch);
2067
2068 if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0)
2069 quit("can't allocate memory for tracing info\n");
2070
2071 if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) {
2072 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64");
2073 } else {
2074 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc");
2075 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64");
2076 }
2077 SortFrameworkAddresses();
2078
2079 cache_disk_names();
2080
2081 if (!RAW_flag) {
2082
2083 set_remove();
2084 set_numbufs(num_events);
2085 set_init();
2086
2087 if (exclude_pids == 0) {
2088 for (i = 0; i < num_of_pids; i++)
2089 set_pidcheck(pids[i], 1);
2090 } else {
2091 for (i = 0; i < num_of_pids; i++)
2092 set_pidexclude(pids[i], 1);
2093 }
2094 if (select_pid_mode && !one_good_pid) {
2095 /*
2096 * An attempt to restrict output to a given
2097 * pid or command has failed. Exit gracefully
2098 */
2099 set_remove();
2100 exit_usage(myname);
2101 }
2102 set_enable(1);
2103
2104 init_arguments_buffer();
2105 }
2106 getdivisor();
2107
2108 init_tables();
2109
2110 /*
2111 * main loop
2112 */
2113 while (1) {
2114 if (!RAW_flag)
2115 usleep(1000 * usleep_ms);
2116
2117 sample_sc();
2118
2119 last_time = time((long *)0);
2120 }
2121 }
2122
2123
2124 void
2125 find_proc_names()
2126 {
2127 size_t bufSize = 0;
2128 struct kinfo_proc *kp;
2129
2130 mib[0] = CTL_KERN;
2131 mib[1] = KERN_PROC;
2132 mib[2] = KERN_PROC_ALL;
2133 mib[3] = 0;
2134
2135 if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
2136 quit("trace facility failure, KERN_PROC_ALL\n");
2137
2138 if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
2139 quit("can't allocate memory for proc buffer\n");
2140
2141 if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
2142 quit("trace facility failure, KERN_PROC_ALL\n");
2143
2144 kp_nentries = bufSize/ sizeof(struct kinfo_proc);
2145 kp_buffer = kp;
2146 }
2147
2148
2149 void
2150 set_enable(int val)
2151 {
2152 mib[0] = CTL_KERN;
2153 mib[1] = KERN_KDEBUG;
2154 mib[2] = KERN_KDENABLE; /* protocol */
2155 mib[3] = val;
2156 mib[4] = 0;
2157 mib[5] = 0; /* no flags */
2158
2159 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2160 quit("trace facility failure, KERN_KDENABLE\n");
2161
2162 if (val)
2163 trace_enabled = 1;
2164 else
2165 trace_enabled = 0;
2166 }
2167
2168 void
2169 set_numbufs(int nbufs)
2170 {
2171 mib[0] = CTL_KERN;
2172 mib[1] = KERN_KDEBUG;
2173 mib[2] = KERN_KDSETBUF;
2174 mib[3] = nbufs;
2175 mib[4] = 0;
2176 mib[5] = 0; /* no flags */
2177
2178 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2179 quit("trace facility failure, KERN_KDSETBUF\n");
2180
2181 mib[0] = CTL_KERN;
2182 mib[1] = KERN_KDEBUG;
2183 mib[2] = KERN_KDSETUP;
2184 mib[3] = 0;
2185 mib[4] = 0;
2186 mib[5] = 0; /* no flags */
2187
2188 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2189 quit("trace facility failure, KERN_KDSETUP\n");
2190 }
2191
2192 void
2193 set_pidcheck(int pid, int on_off)
2194 {
2195 kd_regtype kr;
2196
2197 kr.type = KDBG_TYPENONE;
2198 kr.value1 = pid;
2199 kr.value2 = on_off;
2200 needed = sizeof(kd_regtype);
2201 mib[0] = CTL_KERN;
2202 mib[1] = KERN_KDEBUG;
2203 mib[2] = KERN_KDPIDTR;
2204 mib[3] = 0;
2205 mib[4] = 0;
2206 mib[5] = 0;
2207
2208 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2209 if (on_off == 1)
2210 fprintf(stderr, "pid %d does not exist\n", pid);
2211 } else
2212 one_good_pid++;
2213 }
2214
2215 /*
2216 * on_off == 0 turns off pid exclusion
2217 * on_off == 1 turns on pid exclusion
2218 */
2219 void
2220 set_pidexclude(int pid, int on_off)
2221 {
2222 kd_regtype kr;
2223
2224 one_good_pid++;
2225
2226 kr.type = KDBG_TYPENONE;
2227 kr.value1 = pid;
2228 kr.value2 = on_off;
2229 needed = sizeof(kd_regtype);
2230 mib[0] = CTL_KERN;
2231 mib[1] = KERN_KDEBUG;
2232 mib[2] = KERN_KDPIDEX;
2233 mib[3] = 0;
2234 mib[4] = 0;
2235 mib[5] = 0;
2236
2237 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2238 if (on_off == 1)
2239 fprintf(stderr, "pid %d does not exist\n", pid);
2240 }
2241 }
2242
2243 void
2244 get_bufinfo(kbufinfo_t *val)
2245 {
2246 needed = sizeof (*val);
2247 mib[0] = CTL_KERN;
2248 mib[1] = KERN_KDEBUG;
2249 mib[2] = KERN_KDGETBUF;
2250 mib[3] = 0;
2251 mib[4] = 0;
2252 mib[5] = 0; /* no flags */
2253
2254 if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
2255 quit("trace facility failure, KERN_KDGETBUF\n");
2256
2257 }
2258
2259 void
2260 set_remove()
2261 {
2262 errno = 0;
2263
2264 mib[0] = CTL_KERN;
2265 mib[1] = KERN_KDEBUG;
2266 mib[2] = KERN_KDREMOVE; /* protocol */
2267 mib[3] = 0;
2268 mib[4] = 0;
2269 mib[5] = 0; /* no flags */
2270
2271 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) {
2272 set_remove_flag = 0;
2273
2274 if (errno == EBUSY)
2275 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
2276 else
2277 quit("trace facility failure, KERN_KDREMOVE\n");
2278 }
2279 }
2280
2281 void
2282 set_init()
2283 { kd_regtype kr;
2284
2285 kr.type = KDBG_RANGETYPE;
2286 kr.value1 = 0;
2287 kr.value2 = -1;
2288 needed = sizeof(kd_regtype);
2289
2290 mib[0] = CTL_KERN;
2291 mib[1] = KERN_KDEBUG;
2292 mib[2] = KERN_KDSETREG;
2293 mib[3] = 0;
2294 mib[4] = 0;
2295 mib[5] = 0; /* no flags */
2296
2297 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
2298 quit("trace facility failure, KERN_KDSETREG\n");
2299
2300 mib[0] = CTL_KERN;
2301 mib[1] = KERN_KDEBUG;
2302 mib[2] = KERN_KDSETUP;
2303 mib[3] = 0;
2304 mib[4] = 0;
2305 mib[5] = 0; /* no flags */
2306
2307 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2308 quit("trace facility failure, KERN_KDSETUP\n");
2309 }
2310
2311 void
2312 sample_sc()
2313 {
2314 kd_buf *kd;
2315 int i, count;
2316 size_t needed;
2317 uint32_t my_buffer_size = 0;
2318
2319 if (!RAW_flag)
2320 get_bufinfo(&bufinfo);
2321 else
2322 my_buffer_size = num_events * sizeof(kd_buf);
2323
2324 if (need_new_map) {
2325 read_command_map();
2326 need_new_map = 0;
2327 }
2328 if (!RAW_flag) {
2329 needed = bufinfo.nkdbufs * sizeof(kd_buf);
2330
2331 mib[0] = CTL_KERN;
2332 mib[1] = KERN_KDEBUG;
2333 mib[2] = KERN_KDREADTR;
2334 mib[3] = 0;
2335 mib[4] = 0;
2336 mib[5] = 0; /* no flags */
2337
2338 if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
2339 quit("trace facility failure, KERN_KDREADTR\n");
2340 count = needed;
2341
2342 if (count > (num_events / 8)) {
2343 if (usleep_ms > USLEEP_BEHIND)
2344 usleep_ms = USLEEP_BEHIND;
2345 else if (usleep_ms > USLEEP_MIN)
2346 usleep_ms /= 2;
2347
2348 } else if (count < (num_events / 16)) {
2349 if (usleep_ms < USLEEP_MAX)
2350 usleep_ms *= 2;
2351 }
2352
2353 if (bufinfo.flags & KDBG_WRAPPED) {
2354 fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
2355
2356 delete_all_events();
2357
2358 need_new_map = 1;
2359
2360 set_enable(0);
2361 set_enable(1);
2362 }
2363 } else {
2364 int bytes_read;
2365
2366 if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf))
2367 exit(0);
2368 count = bytes_read / sizeof(kd_buf);
2369 }
2370 kd = (kd_buf *)my_buffer;
2371 #if 0
2372 fprintf(stderr, "READTR returned %d items\n", count);
2373 #endif
2374 for (i = 0; i < count; i++) {
2375 uint32_t debugid;
2376 uintptr_t thread;
2377 int type;
2378 int index;
2379 uintptr_t *sargptr;
2380 uint64_t now;
2381 long long l_usecs;
2382 int secs;
2383 long curr_time;
2384 th_info_t ti;
2385 struct diskio *dio;
2386
2387
2388 thread = kd[i].arg5;
2389 debugid = kd[i].debugid;
2390 type = kd[i].debugid & DBG_FUNC_MASK;
2391
2392 now = kdbg_get_timestamp(&kd[i]);
2393
2394 if (i == 0 && !RAW_flag) {
2395
2396 curr_time = time((long *)0);
2397 /*
2398 * Compute bias seconds after each trace buffer read.
2399 * This helps resync timestamps with the system clock
2400 * in the event of a system sleep.
2401 */
2402 if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
2403 l_usecs = (long long)(now / divisor);
2404 secs = l_usecs / 1000000;
2405 bias_secs = curr_time - secs;
2406 }
2407 }
2408 if (RAW_flag && bias_now == 0.0)
2409 bias_now = now;
2410
2411 if ((type & P_DISKIO_MASK) == P_DISKIO) {
2412 insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
2413 continue;
2414 }
2415 if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
2416 if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2417 print_diskio(dio);
2418 free_diskio(dio);
2419 }
2420 continue;
2421 }
2422 switch (type) {
2423
2424 case P_CS_ReadChunk:
2425 case P_CS_WriteChunk:
2426 case P_CS_MetaRead:
2427 case P_CS_MetaWrite:
2428 insert_diskio(type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now);
2429 continue;
2430
2431 case P_CS_Originated_Read:
2432 case P_CS_Originated_Write:
2433 insert_diskio(type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now);
2434 continue;
2435
2436 case P_CS_ReadChunkDone:
2437 case P_CS_WriteChunkDone:
2438 case P_CS_Originated_ReadDone:
2439 case P_CS_Originated_WriteDone:
2440 case P_CS_MetaReadDone:
2441 case P_CS_MetaWriteDone:
2442 if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2443 print_diskio(dio);
2444 free_diskio(dio);
2445 }
2446 continue;
2447
2448 case TRACE_DATA_NEWTHREAD:
2449 if (kd[i].arg1) {
2450 if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL)
2451 continue;
2452 ti->child_thread = kd[i].arg1;
2453 ti->pid = kd[i].arg2;
2454 }
2455 continue;
2456
2457 case TRACE_STRING_NEWTHREAD:
2458 if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0)
2459 continue;
2460
2461 create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
2462
2463 delete_event(ti);
2464 continue;
2465
2466 case TRACE_DATA_EXEC:
2467 if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL)
2468 continue;
2469
2470 ti->pid = kd[i].arg1;
2471 continue;
2472
2473 case TRACE_STRING_EXEC:
2474 if ((ti = find_event(thread, BSC_execve))) {
2475 if (ti->pathname[0])
2476 exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2477
2478 } else if ((ti = find_event(thread, BSC_posix_spawn))) {
2479 if (ti->pathname[0])
2480 exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2481 }
2482 if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0)
2483 continue;
2484
2485 create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
2486
2487 delete_event(ti);
2488 continue;
2489
2490 case BSC_thread_terminate:
2491 delete_map_entry(thread);
2492 continue;
2493
2494 case BSC_exit:
2495 continue;
2496
2497 case proc_exit:
2498 kd[i].arg1 = kd[i].arg2 >> 8;
2499 type = BSC_exit;
2500 break;
2501
2502 case BSC_mmap:
2503 if (kd[i].arg4 & MAP_ANON)
2504 continue;
2505 break;
2506
2507 case MACH_idle:
2508 case MACH_sched:
2509 case MACH_stkhandoff:
2510 mark_thread_waited(thread);
2511 continue;
2512
2513 case VFS_LOOKUP:
2514 if ((ti = find_event(thread, 0)) == (struct th_info *)0)
2515 continue;
2516
2517 if (debugid & DBG_FUNC_START) {
2518 if (ti->pathname2[0])
2519 continue;
2520 if (ti->pathname[0] == 0)
2521 sargptr = ti->pathname;
2522 else
2523 sargptr = ti->pathname2;
2524 *sargptr++ = kd[i].arg2;
2525 *sargptr++ = kd[i].arg3;
2526 *sargptr++ = kd[i].arg4;
2527 /*
2528 * NULL terminate the 'string'
2529 */
2530 *sargptr = 0;
2531
2532 ti->pathptr = sargptr;
2533 } else {
2534 sargptr = ti->pathptr;
2535
2536 /*
2537 * We don't want to overrun our pathname buffer if the
2538 * kernel sends us more VFS_LOOKUP entries than we can
2539 * handle and we only handle 2 pathname lookups for
2540 * a given system call
2541 */
2542 if (sargptr == 0)
2543 continue;
2544 if (ti->pathname2[0]) {
2545 if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname2[NUMPARMS])
2546 continue;
2547 } else {
2548 if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname[NUMPARMS])
2549 continue;
2550 }
2551 *sargptr++ = kd[i].arg1;
2552 *sargptr++ = kd[i].arg2;
2553 *sargptr++ = kd[i].arg3;
2554 *sargptr++ = kd[i].arg4;
2555 /*
2556 * NULL terminate the 'string'
2557 */
2558 *sargptr = 0;
2559
2560 if (debugid & DBG_FUNC_END) {
2561 if (ti->pathname2[0])
2562 ti->pathptr = 0;
2563 else
2564 ti->pathptr = ti->pathname2;
2565 } else
2566 ti->pathptr = sargptr;
2567 }
2568 continue;
2569 }
2570
2571 if (debugid & DBG_FUNC_START) {
2572 char * p;
2573
2574 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2575
2576 index = filemgr_index(type);
2577
2578 if (index >= MAX_FILEMGR)
2579 continue;
2580
2581 if ((p = filemgr_calls[index].fm_name) == NULL)
2582 continue;
2583 } else
2584 p = NULL;
2585
2586 enter_event(thread, type, &kd[i], p, (double)now);
2587 continue;
2588 }
2589
2590 switch (type) {
2591
2592 case Throttled:
2593 exit_event(" THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2594 continue;
2595
2596 case P_CS_SYNC_DISK:
2597 exit_event(" SyncCacheCS", thread, type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now);
2598 continue;
2599
2600 case SPEC_ioctl:
2601 if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
2602 exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now);
2603 else {
2604 if ((ti = find_event(thread, type)))
2605 delete_event(ti);
2606 }
2607 continue;
2608
2609 case MACH_pageout:
2610 if (kd[i].arg2)
2611 exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2612 else
2613 exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2614 continue;
2615
2616 case MACH_vmfault:
2617 if (kd[i].arg4 == DBG_PAGEIN_FAULT)
2618 exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2619 else if (kd[i].arg4 == DBG_PAGEINV_FAULT)
2620 exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2621 else if (kd[i].arg4 == DBG_PAGEIND_FAULT)
2622 exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2623 else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
2624 exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
2625 else {
2626 if ((ti = find_event(thread, type)))
2627 delete_event(ti);
2628 }
2629 continue;
2630
2631 case MSC_map_fd:
2632 exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
2633 continue;
2634
2635 case BSC_mmap_extended:
2636 case BSC_mmap_extended2:
2637 case BSC_msync_extended:
2638 case BSC_pread_extended:
2639 case BSC_pwrite_extended:
2640 extend_syscall(thread, type, &kd[i]);
2641 continue;
2642 }
2643
2644 if ((type & CSC_MASK) == BSC_BASE) {
2645
2646 if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
2647 continue;
2648
2649 if (bsd_syscalls[index].sc_name) {
2650 exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2651 bsd_syscalls[index].sc_format, (double)now);
2652
2653 if (type == BSC_exit)
2654 delete_map_entry(thread);
2655 }
2656 } else if ((type & CLASS_MASK) == FILEMGR_BASE) {
2657
2658 if ((index = filemgr_index(type)) >= MAX_FILEMGR)
2659 continue;
2660
2661 if (filemgr_calls[index].fm_name) {
2662 exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2663 FMT_DEFAULT, (double)now);
2664 }
2665 }
2666 }
2667 fflush(0);
2668 }
2669
2670
2671 void
2672 enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2673 {
2674 th_info_t ti;
2675 threadmap_t tme;
2676 int secs;
2677 int usecs;
2678 long long l_usecs;
2679 long curr_time;
2680 int clen = 0;
2681 int tsclen = 0;
2682 int nmclen = 0;
2683 int argsclen = 0;
2684 char buf[MAXWIDTH];
2685
2686 if ((ti = add_event(thread, type)) == NULL)
2687 return;
2688
2689 ti->stime = now;
2690 ti->arg1 = kd->arg1;
2691 ti->arg2 = kd->arg2;
2692 ti->arg3 = kd->arg3;
2693 ti->arg4 = kd->arg4;
2694
2695 if ((type & CLASS_MASK) == FILEMGR_BASE &&
2696 (!RAW_flag || (now >= start_time && now <= end_time))) {
2697
2698 filemgr_in_progress++;
2699 ti->in_filemgr = 1;
2700
2701 if (RAW_flag) {
2702 l_usecs = (long long)((now - bias_now) / divisor);
2703 l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
2704 } else
2705 l_usecs = (long long)(now / divisor);
2706 secs = l_usecs / 1000000;
2707 curr_time = bias_secs + secs;
2708
2709 sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
2710 tsclen = strlen(buf);
2711
2712 if (columns > MAXCOLS || wideflag) {
2713 usecs = l_usecs - (long long)((long long)secs * 1000000);
2714 sprintf(&buf[tsclen], ".%06ld", (long)usecs);
2715 tsclen = strlen(buf);
2716 }
2717
2718 /*
2719 * Print timestamp column
2720 */
2721 printf("%s", buf);
2722
2723 tme = find_map_entry(thread);
2724 if (tme) {
2725 sprintf(buf, " %-25.25s ", name);
2726 nmclen = strlen(buf);
2727 printf("%s", buf);
2728
2729 sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2730 argsclen = strlen(buf);
2731
2732 /*
2733 * Calculate white space out to command
2734 */
2735 if (columns > MAXCOLS || wideflag) {
2736 clen = columns - (tsclen + nmclen + argsclen + 20 + 11);
2737 } else
2738 clen = columns - (tsclen + nmclen + argsclen + 12);
2739
2740 if (clen > 0) {
2741 printf("%s", buf); /* print the kdargs */
2742 memset(buf, ' ', clen);
2743 buf[clen] = '\0';
2744 printf("%s", buf);
2745 }
2746 else if ((argsclen + clen) > 0) {
2747 /*
2748 * no room so wipe out the kdargs
2749 */
2750 memset(buf, ' ', (argsclen + clen));
2751 buf[argsclen + clen] = '\0';
2752 printf("%s", buf);
2753 }
2754 if (columns > MAXCOLS || wideflag)
2755 printf("%s.%d\n", tme->tm_command, (int)thread);
2756 else
2757 printf("%-12.12s\n", tme->tm_command);
2758 } else
2759 printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2760 }
2761 }
2762
2763
2764 void
2765 enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2766 {
2767 int index;
2768
2769 if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl || type == Throttled || type == P_CS_SYNC_DISK) {
2770 enter_event_now(thread, type, kd, name, now);
2771 return;
2772 }
2773 if ((type & CSC_MASK) == BSC_BASE) {
2774
2775 if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
2776 return;
2777
2778 if (bsd_syscalls[index].sc_name)
2779 enter_event_now(thread, type, kd, name, now);
2780 return;
2781 }
2782 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2783
2784 if ((index = filemgr_index(type)) >= MAX_FILEMGR)
2785 return;
2786
2787 if (filemgr_calls[index].fm_name)
2788 enter_event_now(thread, type, kd, name, now);
2789 }
2790 }
2791
2792 /*
2793 * Handle system call extended trace data.
2794 * pread and pwrite:
2795 * Wipe out the kd args that were collected upon syscall_entry
2796 * because it is the extended info that we really want, and it
2797 * is all we really need.
2798 */
2799
2800 void
2801 extend_syscall(uintptr_t thread, int type, kd_buf *kd)
2802 {
2803 th_info_t ti;
2804
2805 switch (type) {
2806 case BSC_mmap_extended:
2807 if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
2808 return;
2809 ti->arg8 = ti->arg3; /* save protection */
2810 ti->arg1 = kd->arg1; /* the fd */
2811 ti->arg3 = kd->arg2; /* bottom half address */
2812 ti->arg5 = kd->arg3; /* bottom half size */
2813 break;
2814 case BSC_mmap_extended2:
2815 if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
2816 return;
2817 ti->arg2 = kd->arg1; /* top half address */
2818 ti->arg4 = kd->arg2; /* top half size */
2819 ti->arg6 = kd->arg3; /* top half file offset */
2820 ti->arg7 = kd->arg4; /* bottom half file offset */
2821 break;
2822 case BSC_msync_extended:
2823 if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) {
2824 if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0)
2825 return;
2826 }
2827 ti->arg4 = kd->arg1; /* top half address */
2828 ti->arg5 = kd->arg2; /* top half size */
2829 break;
2830 case BSC_pread_extended:
2831 if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) {
2832 if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0)
2833 return;
2834 }
2835 ti->arg1 = kd->arg1; /* the fd */
2836 ti->arg2 = kd->arg2; /* nbytes */
2837 ti->arg3 = kd->arg3; /* top half offset */
2838 ti->arg4 = kd->arg4; /* bottom half offset */
2839 break;
2840 case BSC_pwrite_extended:
2841 if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) {
2842 if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
2843 return;
2844 }
2845 ti->arg1 = kd->arg1; /* the fd */
2846 ti->arg2 = kd->arg2; /* nbytes */
2847 ti->arg3 = kd->arg3; /* top half offset */
2848 ti->arg4 = kd->arg4; /* bottom half offset */
2849 break;
2850 default:
2851 return;
2852 }
2853 }
2854
2855
2856 void
2857 exit_event(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4,
2858 int format, double now)
2859 {
2860 th_info_t ti;
2861
2862 if ((ti = find_event(thread, type)) == (struct th_info *)0)
2863 return;
2864
2865 if (check_filter_mode(ti, type, arg1, arg2, sc_name))
2866 format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)ti->pathname, NULL);
2867
2868 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2869 ti->in_filemgr = 0;
2870
2871 if (filemgr_in_progress > 0)
2872 filemgr_in_progress--;
2873 }
2874 delete_event(ti);
2875 }
2876
2877
2878 void
2879 get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off)
2880 {
2881 if (smode & 04)
2882 buf[0] = 'r';
2883 if (smode & 02)
2884 buf[1] = 'w';
2885 if (smode & 01) {
2886 if (special)
2887 buf[2] = x_on;
2888 else
2889 buf[2] = 'x';
2890 } else {
2891 if (special)
2892 buf[2] = x_off;
2893 }
2894 }
2895
2896
2897 void
2898 get_mode_string(int mode, char *buf)
2899 {
2900 memset(buf, '-', 9);
2901 buf[9] = '\0';
2902
2903 get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T');
2904 get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S');
2905 get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S');
2906 }
2907
2908
2909 int clip_64bit(char *s, uint64_t value)
2910 {
2911 int clen = 0;
2912
2913 if ( (value & 0xff00000000000000LL) )
2914 clen = printf("%s0x%16.16qx", s, value);
2915 else if ( (value & 0x00ff000000000000LL) )
2916 clen = printf("%s0x%14.14qx ", s, value);
2917 else if ( (value & 0x0000ff0000000000LL) )
2918 clen = printf("%s0x%12.12qx ", s, value);
2919 else if ( (value & 0x000000ff00000000LL) )
2920 clen = printf("%s0x%10.10qx ", s, value);
2921 else
2922 clen = printf("%s0x%8.8qx ", s, value);
2923
2924 return (clen);
2925 }
2926
2927
2928 void
2929 format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4,
2930 int format, double now, double stime, int waited, char *pathname, struct diskio *dio)
2931 {
2932 int secs;
2933 int usecs;
2934 int nopadding = 0;
2935 long long l_usecs;
2936 long curr_time;
2937 char *command_name;
2938 int in_filemgr = 0;
2939 int len = 0;
2940 int clen = 0;
2941 int tlen = 0;
2942 int class;
2943 uint64_t user_addr;
2944 uint64_t user_size;
2945 char *framework_name;
2946 char *framework_type;
2947 char *p1;
2948 char *p2;
2949 char buf[MAXWIDTH];
2950 char cs_diskname[32];
2951 command_name = "";
2952 static char timestamp[32];
2953 static int last_timestamp = -1;
2954 static int timestamp_len = 0;
2955
2956 if (RAW_flag) {
2957 l_usecs = (long long)((now - bias_now) / divisor);
2958
2959 if ((double)l_usecs < start_time || (double)l_usecs > end_time)
2960 return;
2961
2962 l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
2963 }
2964 else
2965 l_usecs = (long long)(now / divisor);
2966 secs = l_usecs / 1000000;
2967 curr_time = bias_secs + secs;
2968
2969 class = type >> 24;
2970
2971 if (dio)
2972 command_name = dio->issuing_command;
2973 else {
2974 threadmap_t tme;
2975
2976 if ((tme = find_map_entry(thread)))
2977 command_name = tme->tm_command;
2978 }
2979 if (last_timestamp != curr_time) {
2980 timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11]));
2981 last_timestamp = curr_time;
2982 }
2983 if (columns > MAXCOLS || wideflag) {
2984 int usec;
2985
2986 tlen = timestamp_len;
2987 nopadding = 0;
2988 usec = (l_usecs - (long long)((long long)secs * 1000000));
2989
2990 sprintf(&timestamp[tlen], ".%06ld", (long)usec);
2991 tlen += 7;
2992
2993 timestamp[tlen] = '\0';
2994
2995 if (filemgr_in_progress) {
2996 if (class != FILEMGR_CLASS) {
2997 if (find_event(thread, -1))
2998 in_filemgr = 1;
2999 }
3000 }
3001 } else
3002 nopadding = 1;
3003
3004 if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
3005 clen = printf("%s %-20.20s", timestamp, sc_name);
3006 else if (in_filemgr)
3007 clen = printf("%s %-15.15s", timestamp, sc_name);
3008 else
3009 clen = printf("%s %-17.17s", timestamp, sc_name);
3010
3011
3012 framework_name = NULL;
3013
3014 if (columns > MAXCOLS || wideflag) {
3015
3016 off_t offset_reassembled = 0LL;
3017
3018 switch (format) {
3019
3020 case FMT_DEFAULT:
3021 /*
3022 * pathname based system calls or
3023 * calls with no fd or pathname (i.e. sync)
3024 */
3025 if (arg1)
3026 clen += printf(" [%3d] ", arg1);
3027 else
3028 clen += printf(" ");
3029 break;
3030
3031 case FMT_FD:
3032 /*
3033 * fd based system call... no I/O
3034 */
3035 if (arg1)
3036 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3037 else
3038 clen += printf(" F=%-3d", ti->arg1);
3039 break;
3040
3041 case FMT_FD_2:
3042 /*
3043 * accept, dup, dup2
3044 */
3045 if (arg1)
3046 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3047 else
3048 clen += printf(" F=%-3d F=%-3d", ti->arg1, arg2);
3049 break;
3050
3051 case FMT_FD_IO:
3052 /*
3053 * system calls with fd's that return an I/O completion count
3054 */
3055 if (arg1)
3056 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3057 else
3058 clen += printf(" F=%-3d B=0x%-6x", ti->arg1, arg2);
3059 break;
3060
3061 case FMT_PGIN:
3062 /*
3063 * pagein
3064 */
3065 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3066
3067 lookup_name(user_addr, &framework_type, &framework_name);
3068 clen += clip_64bit(" A=", user_addr);
3069 break;
3070
3071 case FMT_CACHEHIT:
3072 /*
3073 * cache hit
3074 */
3075 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3076
3077 lookup_name(user_addr, &framework_type, &framework_name);
3078 clen += clip_64bit(" A=", user_addr);
3079 break;
3080
3081 case FMT_PGOUT:
3082 /*
3083 * pageout
3084 */
3085 clen += printf(" B=0x%-8x", arg2);
3086 break;
3087
3088 case FMT_DISKIO:
3089 /*
3090 * physical disk I/O
3091 */
3092 if (dio->io_errno)
3093 clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
3094 else
3095 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, find_disk_name(dio->dev));
3096 break;
3097
3098 case FMT_DISKIO_CS:
3099 /*
3100 * physical disk I/O
3101 */
3102 if (dio->io_errno)
3103 clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
3104 else
3105 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0]));
3106 break;
3107
3108 case FMT_SYNC_DISK_CS:
3109 /*
3110 * physical disk sync cache
3111 */
3112 clen += printf(" /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0]));
3113
3114 break;
3115
3116 case FMT_MSYNC:
3117 {
3118 /*
3119 * msync
3120 */
3121 int mlen = 0;
3122
3123 buf[0] = '\0';
3124
3125 if (ti->arg3 & MS_ASYNC)
3126 mlen += sprintf(&buf[mlen], "MS_ASYNC | ");
3127 else
3128 mlen += sprintf(&buf[mlen], "MS_SYNC | ");
3129
3130 if (ti->arg3 & MS_INVALIDATE)
3131 mlen += sprintf(&buf[mlen], "MS_INVALIDATE | ");
3132 if (ti->arg3 & MS_KILLPAGES)
3133 mlen += sprintf(&buf[mlen], "MS_KILLPAGES | ");
3134 if (ti->arg3 & MS_DEACTIVATE)
3135 mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | ");
3136
3137 if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE))
3138 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3139
3140 if (mlen)
3141 buf[mlen - 3] = '\0';
3142
3143 if (arg1)
3144 clen += printf(" [%3d]", arg1);
3145
3146 user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1);
3147 clen += clip_64bit(" A=", user_addr);
3148
3149 user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2);
3150
3151 clen += printf(" B=0x%-16qx <%s>", user_size, buf);
3152
3153 break;
3154 }
3155
3156 case FMT_FCNTL:
3157 {
3158 /*
3159 * fcntl
3160 */
3161 char *p = NULL;
3162 int fd = -1;
3163
3164 if (arg1)
3165 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3166 else
3167 clen += printf(" F=%-3d", ti->arg1);
3168
3169 switch(ti->arg2) {
3170
3171 case F_DUPFD:
3172 p = "DUPFD";
3173 break;
3174
3175 case F_GETFD:
3176 p = "GETFD";
3177 break;
3178
3179 case F_SETFD:
3180 p = "SETFD";
3181 break;
3182
3183 case F_GETFL:
3184 p = "GETFL";
3185 break;
3186
3187 case F_SETFL:
3188 p = "SETFL";
3189 break;
3190
3191 case F_GETOWN:
3192 p = "GETOWN";
3193 break;
3194
3195 case F_SETOWN:
3196 p = "SETOWN";
3197 break;
3198
3199 case F_GETLK:
3200 p = "GETLK";
3201 break;
3202
3203 case F_SETLK:
3204 p = "SETLK";
3205 break;
3206
3207 case F_SETLKW:
3208 p = "SETLKW";
3209 break;
3210
3211 case F_PREALLOCATE:
3212 p = "PREALLOCATE";
3213 break;
3214
3215 case F_SETSIZE:
3216 p = "SETSIZE";
3217 break;
3218
3219 case F_RDADVISE:
3220 p = "RDADVISE";
3221 break;
3222
3223 case F_GETPATH:
3224 p = "GETPATH";
3225 break;
3226
3227 case F_FULLFSYNC:
3228 p = "FULLFSYNC";
3229 break;
3230
3231 case F_PATHPKG_CHECK:
3232 p = "PATHPKG_CHECK";
3233 break;
3234
3235 case F_OPENFROM:
3236 p = "OPENFROM";
3237
3238 if (arg1 == 0)
3239 fd = arg2;
3240 break;
3241
3242 case F_UNLINKFROM:
3243 p = "UNLINKFROM";
3244 break;
3245
3246 case F_CHECK_OPENEVT:
3247 p = "CHECK_OPENEVT";
3248 break;
3249
3250 case F_NOCACHE:
3251 if (ti->arg3)
3252 p = "CACHING OFF";
3253 else
3254 p = "CACHING ON";
3255 break;
3256
3257 case F_GLOBAL_NOCACHE:
3258 if (ti->arg3)
3259 p = "CACHING OFF (GLOBAL)";
3260 else
3261 p = "CACHING ON (GLOBAL)";
3262 break;
3263
3264 }
3265 if (p) {
3266 if (fd == -1)
3267 clen += printf(" <%s>", p);
3268 else
3269 clen += printf(" <%s> F=%d", p, fd);
3270 } else
3271 clen += printf(" <CMD=%d>", ti->arg2);
3272
3273 break;
3274 }
3275
3276 case FMT_IOCTL:
3277 {
3278 /*
3279 * fcntl
3280 */
3281 if (arg1)
3282 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3283 else
3284 clen += printf(" F=%-3d", ti->arg1);
3285
3286 clen += printf(" <CMD=0x%x>", ti->arg2);
3287
3288 break;
3289 }
3290
3291 case FMT_SPEC_IOCTL:
3292 {
3293 /*
3294 * fcntl
3295 */
3296 clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
3297
3298 break;
3299 }
3300
3301 case FMT_SELECT:
3302 /*
3303 * select
3304 */
3305 if (arg1)
3306 clen += printf(" [%3d]", arg1);
3307 else
3308 clen += printf(" S=%-3d", arg2);
3309
3310 break;
3311
3312 case FMT_LSEEK:
3313 case FMT_PREAD:
3314 /*
3315 * pread, pwrite, lseek
3316 */
3317 clen += printf(" F=%-3d", ti->arg1);
3318
3319 if (arg1)
3320 clen += printf("[%3d] ", arg1);
3321 else {
3322 if (format == FMT_PREAD)
3323 clen += printf(" B=0x%-8x ", arg2);
3324 else
3325 clen += printf(" ");
3326 }
3327 if (format == FMT_PREAD)
3328 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
3329 else
3330 #ifdef __ppc__
3331 offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3);
3332 #else
3333 offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2);
3334 #endif
3335 clen += clip_64bit("O=", offset_reassembled);
3336
3337 if (format == FMT_LSEEK) {
3338 char *mode;
3339
3340 if (ti->arg4 == SEEK_SET)
3341 mode = "SEEK_SET";
3342 else if (ti->arg4 == SEEK_CUR)
3343 mode = "SEEK_CUR";
3344 else if (ti->arg4 == SEEK_END)
3345 mode = "SEEK_END";
3346 else
3347 mode = "UNKNOWN";
3348
3349 clen += printf(" <%s>", mode);
3350 }
3351 break;
3352
3353 case FMT_MMAP:
3354 /*
3355 * mmap
3356 */
3357 clen += printf(" F=%-3d ", ti->arg1);
3358
3359 if (arg1)
3360 clen += printf("[%3d] ", arg1);
3361 else {
3362
3363 user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3364
3365 clen += clip_64bit("A=", user_addr);
3366
3367 offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7);
3368
3369 clen += clip_64bit("O=", offset_reassembled);
3370
3371 user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5);
3372
3373 clen += printf("B=0x%-16qx", user_size);
3374
3375 clen += printf(" <");
3376
3377 if (ti->arg8 & PROT_READ)
3378 clen += printf("READ");
3379
3380 if (ti->arg8 & PROT_WRITE)
3381 clen += printf("|WRITE");
3382
3383 if (ti->arg8 & PROT_EXEC)
3384 clen += printf("|EXEC");
3385
3386 clen += printf(">");
3387 }
3388 break;
3389
3390 case FMT_TRUNC:
3391 case FMT_FTRUNC:
3392 /*
3393 * ftruncate, truncate
3394 */
3395 if (format == FMT_FTRUNC)
3396 clen += printf(" F=%-3d", ti->arg1);
3397 else
3398 clen += printf(" ");
3399
3400 if (arg1)
3401 clen += printf("[%3d]", arg1);
3402
3403 #ifdef __ppc__
3404 offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3405 #else
3406 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2);
3407 #endif
3408 clen += clip_64bit(" O=", offset_reassembled);
3409
3410 nopadding = 1;
3411 break;
3412
3413 case FMT_FCHFLAGS:
3414 case FMT_CHFLAGS:
3415 {
3416 /*
3417 * fchflags, chflags
3418 */
3419 int mlen = 0;
3420
3421 if (format == FMT_FCHFLAGS) {
3422 if (arg1)
3423 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3424 else
3425 clen += printf(" F=%-3d", ti->arg1);
3426 } else {
3427 if (arg1)
3428 clen += printf(" [%3d] ", arg1);
3429 }
3430 buf[mlen++] = ' ';
3431 buf[mlen++] = '<';
3432
3433 if (ti->arg2 & UF_NODUMP)
3434 mlen += sprintf(&buf[mlen], "UF_NODUMP | ");
3435 if (ti->arg2 & UF_IMMUTABLE)
3436 mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | ");
3437 if (ti->arg2 & UF_APPEND)
3438 mlen += sprintf(&buf[mlen], "UF_APPEND | ");
3439 if (ti->arg2 & UF_OPAQUE)
3440 mlen += sprintf(&buf[mlen], "UF_OPAQUE | ");
3441 if (ti->arg2 & SF_ARCHIVED)
3442 mlen += sprintf(&buf[mlen], "SF_ARCHIVED | ");
3443 if (ti->arg2 & SF_IMMUTABLE)
3444 mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | ");
3445 if (ti->arg2 & SF_APPEND)
3446 mlen += sprintf(&buf[mlen], "SF_APPEND | ");
3447
3448 if (ti->arg2 == 0)
3449 mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | ");
3450 else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND))
3451 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3452
3453 if (mlen >= 3)
3454 mlen -= 3;
3455
3456 buf[mlen++] = '>';
3457 buf[mlen] = '\0';
3458
3459 if (mlen < 19) {
3460 memset(&buf[mlen], ' ', 19 - mlen);
3461 mlen = 19;
3462 }
3463 clen += printf("%s", buf);
3464
3465 nopadding = 1;
3466 break;
3467 }
3468
3469 case FMT_UMASK:
3470 case FMT_FCHMOD:
3471 case FMT_FCHMOD_EXT:
3472 case FMT_CHMOD:
3473 case FMT_CHMOD_EXT:
3474 {
3475 /*
3476 * fchmod, fchmod_extended, chmod, chmod_extended
3477 */
3478 int mode;
3479
3480 if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) {
3481 if (arg1)
3482 clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1);
3483 else
3484 clen += printf(" F=%-3d ", ti->arg1);
3485 } else {
3486 if (arg1)
3487 clen += printf(" [%3d] ", arg1);
3488 else
3489 clen += printf(" ");
3490 }
3491 if (format == FMT_UMASK)
3492 mode = ti->arg1;
3493 else if (format == FMT_FCHMOD || format == FMT_CHMOD)
3494 mode = ti->arg2;
3495 else
3496 mode = ti->arg4;
3497
3498 get_mode_string(mode, &buf[0]);
3499
3500 if (arg1 == 0)
3501 clen += printf("<%s> ", buf);
3502 else
3503 clen += printf("<%s>", buf);
3504 break;
3505 }
3506
3507 case FMT_ACCESS:
3508 {
3509 /*
3510 * access
3511 */
3512 char mode[4];
3513
3514 memset(mode, '_', 4);
3515 mode[4] = '\0';
3516
3517 if (ti->arg2 & R_OK)
3518 mode[0] = 'R';
3519 if (ti->arg2 & W_OK)
3520 mode[1] = 'W';
3521 if (ti->arg2 & X_OK)
3522 mode[2] = 'X';
3523 if (ti->arg2 == F_OK)
3524 mode[3] = 'F';
3525
3526 if (arg1)
3527 clen += printf(" [%3d] (%s) ", arg1, mode);
3528 else
3529 clen += printf(" (%s) ", mode);
3530
3531 nopadding = 1;
3532 break;
3533 }
3534
3535 case FMT_MOUNT:
3536 {
3537 if (arg1)
3538 clen += printf(" [%3d] <FLGS=0x%x> ", arg1, ti->arg3);
3539 else
3540 clen += printf(" <FLGS=0x%x> ", ti->arg3);
3541
3542 nopadding = 1;
3543 break;
3544 }
3545
3546 case FMT_UNMOUNT:
3547 {
3548 char *mountflag;
3549
3550 if (ti->arg2 & MNT_FORCE)
3551 mountflag = "<FORCE>";
3552 else
3553 mountflag = "";
3554
3555 if (arg1)
3556 clen += printf(" [%3d] %s ", arg1, mountflag);
3557 else
3558 clen += printf(" %s ", mountflag);
3559
3560 nopadding = 1;
3561 break;
3562 }
3563
3564 case FMT_OPEN:
3565 {
3566 /*
3567 * open
3568 */
3569 char mode[7];
3570
3571 memset(mode, '_', 6);
3572 mode[6] = '\0';
3573
3574 if (ti->arg2 & O_RDWR) {
3575 mode[0] = 'R';
3576 mode[1] = 'W';
3577 } else if (ti->arg2 & O_WRONLY)
3578 mode[1] = 'W';
3579 else
3580 mode[0] = 'R';
3581
3582 if (ti->arg2 & O_CREAT)
3583 mode[2] = 'C';
3584
3585 if (ti->arg2 & O_APPEND)
3586 mode[3] = 'A';
3587
3588 if (ti->arg2 & O_TRUNC)
3589 mode[4] = 'T';
3590
3591 if (ti->arg2 & O_EXCL)
3592 mode[5] = 'E';
3593
3594 if (arg1)
3595 clen += printf(" [%3d] (%s) ", arg1, mode);
3596 else
3597 clen += printf(" F=%-3d (%s) ", arg2, mode);
3598
3599 nopadding = 1;
3600 break;
3601 }
3602
3603 case FMT_SOCKET:
3604 {
3605 /*
3606 * socket
3607 *
3608 */
3609 char *domain;
3610 char *type;
3611
3612 switch (ti->arg1) {
3613
3614 case AF_UNIX:
3615 domain = "AF_UNIX";
3616 break;
3617
3618 case AF_INET:
3619 domain = "AF_INET";
3620 break;
3621
3622 case AF_ISO:
3623 domain = "AF_ISO";
3624 break;
3625
3626 case AF_NS:
3627 domain = "AF_NS";
3628 break;
3629
3630 case AF_IMPLINK:
3631 domain = "AF_IMPLINK";
3632 break;
3633
3634 default:
3635 domain = "UNKNOWN";
3636 break;
3637 }
3638
3639 switch (ti->arg2) {
3640
3641 case SOCK_STREAM:
3642 type = "SOCK_STREAM";
3643 break;
3644
3645 case SOCK_DGRAM:
3646 type = "SOCK_DGRAM";
3647 break;
3648
3649 case SOCK_RAW:
3650 type = "SOCK_RAW";
3651 break;
3652
3653 case SOCK_SEQPACKET:
3654 type = "SOCK_SEQPACKET";
3655 break;
3656
3657 case SOCK_RDM:
3658 type = "SOCK_RDM";
3659 break;
3660
3661 default:
3662 type = "UNKNOWN";
3663 break;
3664 }
3665
3666 if (arg1)
3667 clen += printf(" [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3);
3668 else
3669 clen += printf(" F=%-3d <%s, %s, 0x%x>", arg2, domain, type, ti->arg3);
3670 break;
3671 }
3672
3673 case FMT_AIO_FSYNC:
3674 {
3675 /*
3676 * aio_fsync [errno] AIOCBP OP
3677 */
3678 char *op;
3679
3680 if (ti->arg1 == O_SYNC || ti->arg1 == 0)
3681 op = "AIO_FSYNC";
3682 #if O_DSYNC
3683 else if (ti->arg1 == O_DSYNC)
3684 op = "AIO_DSYNC";
3685 #endif
3686 else
3687 op = "UNKNOWN";
3688
3689 if (arg1)
3690 clen += printf(" [%3d] P=0x%8.8x <%s>", arg1, ti->arg2, op);
3691 else
3692 clen += printf(" P=0x%8.8x <%s>", ti->arg2, op);
3693 break;
3694 }
3695
3696 case FMT_AIO_RETURN:
3697 /*
3698 * aio_return [errno] AIOCBP IOSIZE
3699 */
3700 if (arg1)
3701 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
3702 else
3703 clen += printf(" P=0x%8.8x B=0x%-8x", ti->arg1, arg2);
3704 break;
3705
3706 case FMT_AIO_SUSPEND:
3707 /*
3708 * aio_suspend [errno] NENTS
3709 */
3710 if (arg1)
3711 clen += printf(" [%3d] N=%d", arg1, ti->arg2);
3712 else
3713 clen += printf(" N=%d", ti->arg2);
3714 break;
3715
3716 case FMT_AIO_CANCEL:
3717 /*
3718 * aio_cancel [errno] FD or AIOCBP (if non-null)
3719 */
3720 if (ti->arg2) {
3721 if (arg1)
3722 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg2);
3723 else
3724 clen += printf(" P=0x%8.8x", ti->arg2);
3725 } else {
3726 if (arg1)
3727 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3728 else
3729 clen += printf(" F=%-3d", ti->arg1);
3730 }
3731 break;
3732
3733 case FMT_AIO:
3734 /*
3735 * aio_error, aio_read, aio_write [errno] AIOCBP
3736 */
3737 if (arg1)
3738 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
3739 else
3740 clen += printf(" P=0x%8.8x", ti->arg1);
3741 break;
3742
3743 case FMT_LIO_LISTIO:
3744 {
3745 /*
3746 * lio_listio [errno] NENTS MODE
3747 */
3748 char *op;
3749
3750 if (ti->arg1 == LIO_NOWAIT)
3751 op = "LIO_NOWAIT";
3752 else if (ti->arg1 == LIO_WAIT)
3753 op = "LIO_WAIT";
3754 else
3755 op = "UNKNOWN";
3756
3757 if (arg1)
3758 clen += printf(" [%3d] N=%d <%s>", arg1, ti->arg3, op);
3759 else
3760 clen += printf(" N=%d <%s>", ti->arg3, op);
3761 break;
3762 }
3763
3764 }
3765 }
3766
3767 /*
3768 * Calculate space available to print pathname
3769 */
3770 if (columns > MAXCOLS || wideflag)
3771 clen = columns - (clen + 14 + 20 + 11);
3772 else
3773 clen = columns - (clen + 14 + 12);
3774
3775 if (class != FILEMGR_CLASS && !nopadding)
3776 clen -= 3;
3777
3778 if (framework_name)
3779 len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
3780 else if (*pathname != '\0') {
3781 len = sprintf(&buf[0], " %s ", pathname);
3782
3783 if (format == FMT_MOUNT && ti->pathname2[0]) {
3784 int len2;
3785
3786 memset(&buf[len], ' ', 2);
3787
3788 len2 = sprintf(&buf[len+2], " %s ", (char *)ti->pathname2);
3789 len = len + 2 + len2;
3790 }
3791 } else
3792 len = 0;
3793
3794 if (clen > len) {
3795 /*
3796 * Add null padding if column length
3797 * is wider than the pathname length.
3798 */
3799 memset(&buf[len], ' ', clen - len);
3800 buf[clen] = '\0';
3801
3802 pathname = buf;
3803
3804 } else if (clen == len) {
3805 pathname = buf;
3806
3807 } else if ((clen > 0) && (clen < len)) {
3808 /*
3809 * This prints the tail end of the pathname
3810 */
3811 buf[len-clen] = ' ';
3812
3813 pathname = &buf[len - clen];
3814
3815 } else {
3816 pathname = "";
3817 }
3818
3819 /*
3820 * fudge some additional system call overhead
3821 * that currently isn't tracked... this also
3822 * insures that we see a minimum of 1 us for
3823 * an elapsed time
3824 */
3825 usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor);
3826 secs = usecs / 1000000;
3827 usecs -= secs * 1000000;
3828
3829 if (class != FILEMGR_CLASS && !nopadding)
3830 p1 = " ";
3831 else
3832 p1 = "";
3833
3834 if (waited)
3835 p2 = " W";
3836 else
3837 p2 = " ";
3838
3839 if (columns > MAXCOLS || wideflag)
3840 printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread);
3841 else
3842 printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
3843 }
3844
3845
3846 void
3847 delete_event(th_info_t ti_to_delete) {
3848 th_info_t ti;
3849 th_info_t ti_prev;
3850 int hashid;
3851
3852 hashid = ti_to_delete->thread & HASH_MASK;
3853
3854 if ((ti = th_info_hash[hashid])) {
3855 if (ti == ti_to_delete)
3856 th_info_hash[hashid] = ti->next;
3857 else {
3858 ti_prev = ti;
3859
3860 for (ti = ti->next; ti; ti = ti->next) {
3861 if (ti == ti_to_delete) {
3862 ti_prev->next = ti->next;
3863 break;
3864 }
3865 ti_prev = ti;
3866 }
3867 }
3868 if (ti) {
3869 ti->next = th_info_freelist;
3870 th_info_freelist = ti;
3871 }
3872 }
3873 }
3874
3875 th_info_t
3876 add_event(uintptr_t thread, int type) {
3877 th_info_t ti;
3878 int hashid;
3879
3880 if ((ti = th_info_freelist))
3881 th_info_freelist = ti->next;
3882 else
3883 ti = (th_info_t)malloc(sizeof(struct th_info));
3884
3885 hashid = thread & HASH_MASK;
3886
3887 ti->next = th_info_hash[hashid];
3888 th_info_hash[hashid] = ti;
3889
3890 ti->thread = thread;
3891 ti->type = type;
3892
3893 ti->waited = 0;
3894 ti->in_filemgr = 0;
3895 ti->pathptr = ti->pathname;
3896 ti->pathname[0] = 0;
3897 ti->pathname2[0] = 0;
3898
3899 return (ti);
3900 }
3901
3902 th_info_t
3903 find_event(uintptr_t thread, int type) {
3904 th_info_t ti;
3905 int hashid;
3906
3907 hashid = thread & HASH_MASK;
3908
3909 for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
3910 if (ti->thread == thread) {
3911 if (type == ti->type)
3912 return (ti);
3913 if (ti->in_filemgr) {
3914 if (type == -1)
3915 return (ti);
3916 continue;
3917 }
3918 if (type == 0)
3919 return (ti);
3920 }
3921 }
3922 return ((th_info_t) 0);
3923 }
3924
3925 void
3926 delete_all_events() {
3927 th_info_t ti = 0;
3928 th_info_t ti_next = 0;
3929 int i;
3930
3931 for (i = 0; i < HASH_SIZE; i++) {
3932
3933 for (ti = th_info_hash[i]; ti; ti = ti_next) {
3934 ti_next = ti->next;
3935 ti->next = th_info_freelist;
3936 th_info_freelist = ti;
3937 }
3938 th_info_hash[i] = 0;
3939 }
3940 }
3941
3942
3943 void
3944 mark_thread_waited(uintptr_t thread) {
3945 th_info_t ti;
3946 int hashid;
3947
3948 hashid = thread & HASH_MASK;
3949
3950 for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
3951 if (ti->thread == thread)
3952 ti->waited = 1;
3953 }
3954 }
3955
3956
3957 void read_command_map()
3958 {
3959 size_t size;
3960 int i;
3961 int total_threads = 0;
3962 kd_threadmap *mapptr = 0;
3963
3964 delete_all_map_entries();
3965
3966 if (!RAW_flag) {
3967
3968 total_threads = bufinfo.nkdthreads;
3969 size = bufinfo.nkdthreads * sizeof(kd_threadmap);
3970
3971 if (size) {
3972 if ((mapptr = (kd_threadmap *) malloc(size))) {
3973 int mib[6];
3974
3975 bzero (mapptr, size);
3976 /*
3977 * Now read the threadmap
3978 */
3979 mib[0] = CTL_KERN;
3980 mib[1] = KERN_KDEBUG;
3981 mib[2] = KERN_KDTHRMAP;
3982 mib[3] = 0;
3983 mib[4] = 0;
3984 mib[5] = 0; /* no flags */
3985
3986 if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) {
3987 /*
3988 * This is not fatal -- just means I cant map command strings
3989 */
3990 free(mapptr);
3991 return;
3992 }
3993 }
3994 }
3995 } else {
3996 RAW_header header;
3997 off_t offset;
3998
3999 RAW_fd = open(RAW_file, O_RDONLY);
4000
4001 if (RAW_fd < 0) {
4002 perror("Can't open RAW file");
4003 exit(1);
4004 }
4005 if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) {
4006 perror("read failed");
4007 exit(2);
4008 }
4009 if (header.version_no != RAW_VERSION1) {
4010 header.version_no = RAW_VERSION0;
4011 header.TOD_secs = time((long *)0);
4012 header.TOD_usecs = 0;
4013
4014 lseek(RAW_fd, (off_t)0, SEEK_SET);
4015
4016 if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) {
4017 perror("read failed");
4018 exit(2);
4019 }
4020 }
4021 sample_TOD_secs = header.TOD_secs;
4022 sample_TOD_usecs = header.TOD_usecs;
4023
4024 total_threads = header.thread_count;
4025 size = total_threads * sizeof(kd_threadmap);
4026
4027 if (size) {
4028 if ((mapptr = (kd_threadmap *) malloc(size))) {
4029 bzero (mapptr, size);
4030
4031 if (read(RAW_fd, mapptr, size) != size) {
4032 free(mapptr);
4033 return;
4034 }
4035 }
4036 }
4037 if (header.version_no != RAW_VERSION0) {
4038 offset = lseek(RAW_fd, (off_t)0, SEEK_CUR);
4039 offset = (offset + (4095)) & ~4095;
4040
4041 lseek(RAW_fd, offset, SEEK_SET);
4042 }
4043 }
4044 for (i = 0; i < total_threads; i++)
4045 create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]);
4046
4047 free(mapptr);
4048 }
4049
4050
4051 void delete_all_map_entries()
4052 {
4053 threadmap_t tme = 0;
4054 threadmap_t tme_next = 0;
4055 int i;
4056
4057 for (i = 0; i < HASH_SIZE; i++) {
4058
4059 for (tme = threadmap_hash[i]; tme; tme = tme_next) {
4060 if (tme->tm_setptr)
4061 free(tme->tm_setptr);
4062 tme_next = tme->tm_next;
4063 tme->tm_next = threadmap_freelist;
4064 threadmap_freelist = tme;
4065 }
4066 threadmap_hash[i] = 0;
4067 }
4068 }
4069
4070
4071 void create_map_entry(uintptr_t thread, int pid, char *command)
4072 {
4073 threadmap_t tme;
4074 int hashid;
4075
4076 if ((tme = threadmap_freelist))
4077 threadmap_freelist = tme->tm_next;
4078 else
4079 tme = (threadmap_t)malloc(sizeof(struct threadmap));
4080
4081 tme->tm_thread = thread;
4082 tme->tm_setsize = 0;
4083 tme->tm_setptr = 0;
4084
4085 (void)strncpy (tme->tm_command, command, MAXCOMLEN);
4086 tme->tm_command[MAXCOMLEN] = '\0';
4087
4088 hashid = thread & HASH_MASK;
4089
4090 tme->tm_next = threadmap_hash[hashid];
4091 threadmap_hash[hashid] = tme;
4092
4093 if (pid != 0 && pid != 1) {
4094 if (!strncmp(command, "LaunchCFMA", 10))
4095 (void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN);
4096 }
4097 }
4098
4099
4100 threadmap_t
4101 find_map_entry(uintptr_t thread)
4102 {
4103 threadmap_t tme;
4104 int hashid;
4105
4106 hashid = thread & HASH_MASK;
4107
4108 for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
4109 if (tme->tm_thread == thread)
4110 return (tme);
4111 }
4112 return (0);
4113 }
4114
4115
4116 void
4117 delete_map_entry(uintptr_t thread)
4118 {
4119 threadmap_t tme = 0;
4120 threadmap_t tme_prev;
4121 int hashid;
4122
4123 hashid = thread & HASH_MASK;
4124
4125 if ((tme = threadmap_hash[hashid])) {
4126 if (tme->tm_thread == thread)
4127 threadmap_hash[hashid] = tme->tm_next;
4128 else {
4129 tme_prev = tme;
4130
4131 for (tme = tme->tm_next; tme; tme = tme->tm_next) {
4132 if (tme->tm_thread == thread) {
4133 tme_prev->tm_next = tme->tm_next;
4134 break;
4135 }
4136 tme_prev = tme;
4137 }
4138 }
4139 if (tme) {
4140 if (tme->tm_setptr)
4141 free(tme->tm_setptr);
4142
4143 tme->tm_next = threadmap_freelist;
4144 threadmap_freelist = tme;
4145 }
4146 }
4147 }
4148
4149
4150 void
4151 fs_usage_fd_set(uintptr_t thread, unsigned int fd)
4152 {
4153 threadmap_t tme;
4154
4155 if ((tme = find_map_entry(thread)) == 0)
4156 return;
4157 /*
4158 * If the map is not allocated, then now is the time
4159 */
4160 if (tme->tm_setptr == (unsigned long *)0) {
4161 if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0)
4162 return;
4163
4164 tme->tm_setsize = FS_USAGE_FD_SETSIZE;
4165 bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
4166 }
4167 /*
4168 * If the map is not big enough, then reallocate it
4169 */
4170 while (tme->tm_setsize <= fd) {
4171 int n;
4172
4173 n = tme->tm_setsize * 2;
4174 tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n)));
4175
4176 bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize)));
4177 tme->tm_setsize = n;
4178 }
4179 /*
4180 * set the bit
4181 */
4182 tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
4183 }
4184
4185
4186 /*
4187 * Return values:
4188 * 0 : File Descriptor bit is not set
4189 * 1 : File Descriptor bit is set
4190 */
4191 int
4192 fs_usage_fd_isset(uintptr_t thread, unsigned int fd)
4193 {
4194 threadmap_t tme;
4195 int ret = 0;
4196
4197 if ((tme = find_map_entry(thread))) {
4198 if (tme->tm_setptr && fd < tme->tm_setsize)
4199 ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
4200 }
4201 return (ret);
4202 }
4203
4204
4205 void
4206 fs_usage_fd_clear(uintptr_t thread, unsigned int fd)
4207 {
4208 threadmap_t tme;
4209
4210 if ((tme = find_map_entry(thread))) {
4211 if (tme->tm_setptr && fd < tme->tm_setsize)
4212 tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
4213 }
4214 }
4215
4216
4217
4218 void
4219 argtopid(char *str)
4220 {
4221 char *cp;
4222 int ret;
4223 int i;
4224
4225 ret = (int)strtol(str, &cp, 10);
4226
4227 if (cp == str || *cp) {
4228 /*
4229 * Assume this is a command string and find matching pids
4230 */
4231 if (!kp_buffer)
4232 find_proc_names();
4233
4234 for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
4235 if (kp_buffer[i].kp_proc.p_stat == 0)
4236 continue;
4237 else {
4238 if (!strncmp(str, kp_buffer[i].kp_proc.p_comm,
4239 sizeof(kp_buffer[i].kp_proc.p_comm) -1))
4240 pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
4241 }
4242 }
4243 }
4244 else if (num_of_pids < (MAX_PIDS - 1))
4245 pids[num_of_pids++] = ret;
4246 }
4247
4248
4249
4250 void
4251 lookup_name(uint64_t user_addr, char **type, char **name)
4252 {
4253 int i;
4254 int start, last;
4255
4256 *name = NULL;
4257 *type = NULL;
4258
4259 if (numFrameworks) {
4260
4261 if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
4262 (user_addr >= framework64.b_address && user_addr < framework64.e_address)) {
4263
4264 start = 0;
4265 last = numFrameworks;
4266
4267 for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
4268 if (user_addr > frameworkInfo[i].e_address)
4269 start = i+1;
4270 else
4271 last = i;
4272 }
4273 if (start < numFrameworks &&
4274 user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
4275 *type = frameworkType[frameworkInfo[start].r_type];
4276 *name = frameworkInfo[start].name;
4277 }
4278 }
4279 }
4280 }
4281
4282
4283 /*
4284 * Comparison routines for sorting
4285 */
4286 static int compareFrameworkAddress(const void *aa, const void *bb)
4287 {
4288 LibraryInfo *a = (LibraryInfo *)aa;
4289 LibraryInfo *b = (LibraryInfo *)bb;
4290
4291 if (a->b_address < b->b_address) return -1;
4292 if (a->b_address == b->b_address) return 0;
4293 return 1;
4294 }
4295
4296
4297 int scanline(char *inputstring, char **argv, int maxtokens)
4298 {
4299 int n = 0;
4300 char **ap = argv, *p, *val;
4301
4302 for (p = inputstring; n < maxtokens && p != NULL; ) {
4303
4304 while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
4305
4306 *ap++ = val;
4307 n++;
4308 }
4309 *ap = 0;
4310
4311 return n;
4312 }
4313
4314
4315 int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name)
4316 {
4317 uint64_t b_address, e_address;
4318 char buf[1024];
4319 char *fnp;
4320 FILE *fd;
4321 char frameworkName[256];
4322 char *tokens[64];
4323 int ntokens;
4324 int type;
4325 int linkedit_found = 0;
4326 char *substring, *ptr;
4327
4328 bzero(buf, sizeof(buf));
4329 bzero(tokens, sizeof(tokens));
4330
4331 lr->b_address = 0;
4332 lr->e_address = 0;
4333
4334 if ((fd = fopen(path, "r")) == 0)
4335 return 0;
4336
4337 while (fgets(buf, 1023, fd)) {
4338 if (strncmp(buf, "mapping", 7))
4339 break;
4340 }
4341 buf[strlen(buf)-1] = 0;
4342
4343 frameworkName[0] = 0;
4344
4345 for (;;) {
4346 /*
4347 * Extract lib name from path name
4348 */
4349 if ((substring = strrchr(buf, '.')))
4350 {
4351 /*
4352 * There is a ".": name is whatever is between the "/" around the "."
4353 */
4354 while ( *substring != '/') /* find "/" before "." */
4355 substring--;
4356 substring++;
4357
4358 strncpy(frameworkName, substring, 256); /* copy path from "/" */
4359 frameworkName[255] = 0;
4360 substring = frameworkName;
4361
4362 while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
4363 substring++;
4364 *substring = 0;
4365 }
4366 else
4367 {
4368 /*
4369 * No ".": take segment after last "/"
4370 */
4371 ptr = buf;
4372 substring = ptr;
4373
4374 while (*ptr) {
4375 if (*ptr == '/')
4376 substring = ptr + 1;
4377 ptr++;
4378 }
4379 strncpy(frameworkName, substring, 256);
4380 frameworkName[255] = 0;
4381 }
4382 fnp = (char *)malloc(strlen(frameworkName) + 1);
4383 strcpy(fnp, frameworkName);
4384
4385 while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) {
4386 /*
4387 * Get rid of EOL
4388 */
4389 buf[strlen(buf)-1] = 0;
4390
4391 ntokens = scanline(buf, tokens, 64);
4392
4393 if (ntokens < 4)
4394 continue;
4395
4396 if (strncmp(tokens[0], "__TEXT", 6) == 0)
4397 type = TEXT_R;
4398 else if (strncmp(tokens[0], "__DATA", 6) == 0)
4399 type = DATA_R;
4400 else if (strncmp(tokens[0], "__OBJC", 6) == 0)
4401 type = OBJC_R;
4402 else if (strncmp(tokens[0], "__IMPORT", 8) == 0)
4403 type = IMPORT_R;
4404 else if (strncmp(tokens[0], "__UNICODE", 9) == 0)
4405 type = UNICODE_R;
4406 else if (strncmp(tokens[0], "__IMAGE", 7) == 0)
4407 type = IMAGE_R;
4408 else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
4409 type = LINKEDIT_R;
4410 else
4411 type = -1;
4412
4413 if (type == LINKEDIT_R && linkedit_found)
4414 break;
4415
4416 if (type != -1) {
4417 b_address = strtoull(tokens[1], 0, 16);
4418 e_address = strtoull(tokens[3], 0, 16);
4419
4420 frameworkInfo[numFrameworks].b_address = b_address;
4421 frameworkInfo[numFrameworks].e_address = e_address;
4422 frameworkInfo[numFrameworks].r_type = type;
4423
4424 if (type == LINKEDIT_R) {
4425 frameworkInfo[numFrameworks].name = linkedit_name;
4426 linkedit_found = 1;
4427 } else
4428 frameworkInfo[numFrameworks].name = fnp;
4429 #if 0
4430 printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address);
4431 #endif
4432 if (lr->b_address == 0 || b_address < lr->b_address)
4433 lr->b_address = b_address;
4434
4435 if (lr->e_address == 0 || e_address > lr->e_address)
4436 lr->e_address = e_address;
4437
4438 numFrameworks++;
4439 }
4440 if (type == LINKEDIT_R)
4441 break;
4442 }
4443 if (fgets(buf, 1023, fd) == 0)
4444 break;
4445
4446 buf[strlen(buf)-1] = 0;
4447 }
4448 fclose(fd);
4449
4450 #if 0
4451 printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address);
4452 #endif
4453 return 1;
4454 }
4455
4456
4457 void
4458 SortFrameworkAddresses()
4459 {
4460
4461 frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000;
4462 frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address;
4463 frameworkInfo[numFrameworks].name = (char *)0;
4464
4465 qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
4466 }
4467
4468
4469 struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime)
4470 {
4471 struct diskio *dio;
4472 threadmap_t tme;
4473
4474 if ((dio = free_diskios))
4475 free_diskios = dio->next;
4476 else {
4477 if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
4478 return (NULL);
4479 }
4480 dio->prev = NULL;
4481
4482 dio->type = type;
4483 dio->bp = bp;
4484 dio->dev = dev;
4485 dio->blkno = blkno;
4486 dio->iosize = io_size;
4487 dio->issued_time = curtime;
4488 dio->issuing_thread = thread;
4489
4490 if ((tme = find_map_entry(thread))) {
4491 strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN);
4492 dio->issuing_command[MAXCOMLEN-1] = '\0';
4493 } else
4494 strcpy(dio->issuing_command, "");
4495
4496 dio->next = busy_diskios;
4497 if (dio->next)
4498 dio->next->prev = dio;
4499 busy_diskios = dio;
4500
4501 return (dio);
4502 }
4503
4504
4505 struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime)
4506 {
4507 struct diskio *dio;
4508
4509 for (dio = busy_diskios; dio; dio = dio->next) {
4510
4511 if (dio->bp == bp) {
4512 if (dio == busy_diskios) {
4513 if ((busy_diskios = dio->next))
4514 dio->next->prev = NULL;
4515 } else {
4516 if (dio->next)
4517 dio->next->prev = dio->prev;
4518 dio->prev->next = dio->next;
4519 }
4520 dio->iosize -= resid;
4521 dio->io_errno = io_errno;
4522 dio->completed_time = curtime;
4523 dio->completion_thread = thread;
4524
4525 return (dio);
4526 }
4527 }
4528 return ((struct diskio *)0);
4529 }
4530
4531
4532 void free_diskio(struct diskio *dio)
4533 {
4534 dio->next = free_diskios;
4535 free_diskios = dio;
4536 }
4537
4538
4539 void print_diskio(struct diskio *dio)
4540 {
4541 char *p = NULL;
4542 int len = 0;
4543 int type;
4544 int format = FMT_DISKIO;
4545 char buf[64];
4546
4547 type = dio->type;
4548
4549
4550 if (type == P_CS_ReadChunk || type == P_CS_WriteChunk || type == P_CS_Originated_Read ||
4551 type == P_CS_Originated_Write || type == P_CS_MetaRead || type == P_CS_MetaWrite) {
4552
4553 switch (type) {
4554
4555 case P_CS_ReadChunk:
4556 p = " RdChunkCS";
4557 len = 13;
4558 format = FMT_DISKIO_CS;
4559 break;
4560 case P_CS_WriteChunk:
4561 p = " WrChunkCS";
4562 len = 13;
4563 format = FMT_DISKIO_CS;
4564 break;
4565 case P_CS_MetaRead:
4566 p = " RdMetaCS";
4567 len = 10;
4568 format = FMT_DISKIO_CS;
4569 break;
4570 case P_CS_MetaWrite:
4571 p = " WrMetaCS";
4572 len = 10;
4573 format = FMT_DISKIO_CS;
4574 break;
4575 case P_CS_Originated_Read:
4576 p = " RdDataCS";
4577 len = 10;
4578 break;
4579 case P_CS_Originated_Write:
4580 p = " WrDataCS";
4581 len = 10;
4582 break;
4583 }
4584 strncpy(buf, p, len);
4585 } else {
4586
4587 switch (type & P_DISKIO_TYPE) {
4588
4589 case P_RdMeta:
4590 p = " RdMeta";
4591 len = 8;
4592 break;
4593 case P_WrMeta:
4594 p = " WrMeta";
4595 len = 8;
4596 break;
4597 case P_RdData:
4598 p = " RdData";
4599 len = 8;
4600 break;
4601 case P_WrData:
4602 p = " WrData";
4603 len = 8;
4604 break;
4605 case P_PgIn:
4606 p = " PgIn";
4607 len = 6;
4608 break;
4609 case P_PgOut:
4610 p = " PgOut";
4611 len = 7;
4612 break;
4613 default:
4614 p = " ";
4615 len = 2;
4616 break;
4617 }
4618 strncpy(buf, p, len);
4619
4620 if (type & (P_DISKIO_ASYNC | P_DISKIO_THROTTLE | P_DISKIO_PASSIVE)) {
4621 buf[len++] = '[';
4622
4623 if (type & P_DISKIO_ASYNC) {
4624 memcpy(&buf[len], "async", 5);
4625 len += 5;
4626 }
4627 if (type & P_DISKIO_THROTTLE)
4628 buf[len++] = 'T';
4629 else if (type & P_DISKIO_PASSIVE)
4630 buf[len++] = 'P';
4631
4632 buf[len++] = ']';
4633 }
4634 }
4635 buf[len] = 0;
4636
4637 if (check_filter_mode(NULL, type, 0, 0, buf))
4638 format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio);
4639 }
4640
4641
4642 void cache_disk_names()
4643 {
4644 struct stat st;
4645 DIR *dirp = NULL;
4646 struct dirent *dir;
4647 struct diskrec *dnp;
4648
4649
4650 if ((dirp = opendir("/dev")) == NULL)
4651 return;
4652
4653 while ((dir = readdir(dirp)) != NULL) {
4654 char nbuf[MAXPATHLEN];
4655
4656 if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
4657 continue;
4658
4659 snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
4660
4661 if (stat(nbuf, &st) < 0)
4662 continue;
4663
4664 if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
4665 continue;
4666
4667 if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
4668 free(dnp);
4669 continue;
4670 }
4671 strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
4672 dnp->diskname[dir->d_namlen] = 0;
4673 dnp->dev = st.st_rdev;
4674
4675 dnp->next = disk_list;
4676 disk_list = dnp;
4677 }
4678 (void) closedir(dirp);
4679 }
4680
4681
4682 void recache_disk_names()
4683 {
4684 struct diskrec *dnp, *next_dnp;
4685
4686 for (dnp = disk_list; dnp; dnp = next_dnp) {
4687 next_dnp = dnp->next;
4688
4689 free(dnp->diskname);
4690 free(dnp);
4691 }
4692 disk_list = NULL;
4693
4694 cache_disk_names();
4695 }
4696
4697
4698 char *find_disk_name(int dev)
4699 {
4700 struct diskrec *dnp;
4701 int i;
4702
4703 if (dev == NFS_DEV)
4704 return ("NFS");
4705
4706 if (dev == CS_DEV)
4707 return ("CS");
4708
4709 for (i = 0; i < 2; i++) {
4710 for (dnp = disk_list; dnp; dnp = dnp->next) {
4711 if (dnp->dev == dev)
4712 return (dnp->diskname);
4713 }
4714 recache_disk_names();
4715 }
4716 return ("NOTFOUND");
4717 }
4718
4719
4720 char *generate_cs_disk_name(int dev, char *s)
4721 {
4722 if (dev == -1)
4723 return ("UNKNOWN");
4724
4725 sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff);
4726
4727 return (s);
4728 }
4729
4730
4731
4732 /*
4733 * ret = 1 means print the entry
4734 * ret = 0 means don't print the entry
4735 */
4736 int
4737 check_filter_mode(struct th_info * ti, int type, int error, int retval, char *sc_name)
4738 {
4739 int ret = 0;
4740 int network_fd_isset = 0;
4741 unsigned int fd;
4742
4743 if (filter_mode == DEFAULT_DO_NOT_FILTER)
4744 return(1);
4745
4746 if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) {
4747 if (filter_mode & CACHEHIT_FILTER)
4748 /* Do not print if cachehit filter is set */
4749 return(0);
4750 return(1);
4751 }
4752
4753 if (filter_mode & EXEC_FILTER) {
4754 if (type == BSC_execve || type == BSC_posix_spawn)
4755 return(1);
4756 return(0);
4757 }
4758
4759 if (filter_mode & PATHNAME_FILTER) {
4760 if (ti && ti->pathname[0])
4761 return(1);
4762 if (type == BSC_close || type == BSC_close_nocancel)
4763 return(1);
4764 return(0);
4765 }
4766
4767 if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER)))
4768 return(1);
4769
4770 if (ti == (struct th_info *)0) {
4771 if (filter_mode & FILESYS_FILTER)
4772 return(1);
4773 return(0);
4774 }
4775
4776 switch (type) {
4777
4778 case BSC_close:
4779 case BSC_close_nocancel:
4780 fd = ti->arg1;
4781 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4782
4783 if (error == 0)
4784 fs_usage_fd_clear(ti->thread,fd);
4785
4786 if (network_fd_isset) {
4787 if (filter_mode & NETWORK_FILTER)
4788 ret = 1;
4789 } else if (filter_mode & FILESYS_FILTER)
4790 ret = 1;
4791 break;
4792
4793 case BSC_read:
4794 case BSC_write:
4795 case BSC_read_nocancel:
4796 case BSC_write_nocancel:
4797 /*
4798 * we don't care about error in these cases
4799 */
4800 fd = ti->arg1;
4801 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4802
4803 if (network_fd_isset) {
4804 if (filter_mode & NETWORK_FILTER)
4805 ret = 1;
4806 } else if (filter_mode & FILESYS_FILTER)
4807 ret = 1;
4808 break;
4809
4810 case BSC_accept:
4811 case BSC_accept_nocancel:
4812 case BSC_socket:
4813 fd = retval;
4814
4815 if (error == 0)
4816 fs_usage_fd_set(ti->thread, fd);
4817 if (filter_mode & NETWORK_FILTER)
4818 ret = 1;
4819 break;
4820
4821 case BSC_recvfrom:
4822 case BSC_sendto:
4823 case BSC_recvmsg:
4824 case BSC_sendmsg:
4825 case BSC_connect:
4826 case BSC_bind:
4827 case BSC_listen:
4828 case BSC_sendto_nocancel:
4829 case BSC_recvfrom_nocancel:
4830 case BSC_recvmsg_nocancel:
4831 case BSC_sendmsg_nocancel:
4832 case BSC_connect_nocancel:
4833 fd = ti->arg1;
4834
4835 if (error == 0)
4836 fs_usage_fd_set(ti->thread, fd);
4837 if (filter_mode & NETWORK_FILTER)
4838 ret = 1;
4839 break;
4840
4841 case BSC_select:
4842 case BSC_select_nocancel:
4843 case BSC_socketpair:
4844 /*
4845 * Cannot determine info about file descriptors
4846 */
4847 if (filter_mode & NETWORK_FILTER)
4848 ret = 1;
4849 break;
4850
4851 case BSC_dup:
4852 case BSC_dup2:
4853 /*
4854 * We track these cases for fd state only
4855 */
4856 fd = ti->arg1;
4857 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4858
4859 if (error == 0 && network_fd_isset) {
4860 /*
4861 * then we are duping a socket descriptor
4862 */
4863 fd = retval; /* the new fd */
4864 fs_usage_fd_set(ti->thread, fd);
4865 }
4866 break;
4867
4868 default:
4869 if (filter_mode & FILESYS_FILTER)
4870 ret = 1;
4871 break;
4872 }
4873
4874 return(ret);
4875 }
4876
4877 /*
4878 * Allocate a buffer that is large enough to hold the maximum arguments
4879 * to execve(). This is used when getting the arguments to programs
4880 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
4881 * simply not resolve the command name.
4882 */
4883
4884 void
4885 init_arguments_buffer()
4886 {
4887 int mib[2];
4888 size_t size;
4889
4890 mib[0] = CTL_KERN;
4891 mib[1] = KERN_ARGMAX;
4892 size = sizeof(argmax);
4893
4894 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
4895 return;
4896 #if 1
4897 /* Hack to avoid kernel bug. */
4898 if (argmax > 8192) {
4899 argmax = 8192;
4900 }
4901 #endif
4902 arguments = (char *)malloc(argmax);
4903 }
4904
4905
4906 int
4907 get_real_command_name(int pid, char *cbuf, int csize)
4908 {
4909 /*
4910 * Get command and arguments.
4911 */
4912 char *cp;
4913 int mib[4];
4914 char *command_beg, *command, *command_end;
4915
4916 if (cbuf == NULL)
4917 return(0);
4918
4919 if (arguments)
4920 bzero(arguments, argmax);
4921 else
4922 return(0);
4923
4924 /*
4925 * A sysctl() is made to find out the full path that the command
4926 * was called with.
4927 */
4928 mib[0] = CTL_KERN;
4929 mib[1] = KERN_PROCARGS2;
4930 mib[2] = pid;
4931 mib[3] = 0;
4932
4933 if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0)
4934 return(0);
4935
4936 /*
4937 * Skip the saved exec_path
4938 */
4939 for (cp = arguments; cp < &arguments[argmax]; cp++) {
4940 if (*cp == '\0') {
4941 /*
4942 * End of exec_path reached
4943 */
4944 break;
4945 }
4946 }
4947 if (cp == &arguments[argmax])
4948 return(0);
4949
4950 /*
4951 * Skip trailing '\0' characters
4952 */
4953 for (; cp < &arguments[argmax]; cp++) {
4954 if (*cp != '\0') {
4955 /*
4956 * Beginning of first argument reached
4957 */
4958 break;
4959 }
4960 }
4961 if (cp == &arguments[argmax])
4962 return(0);
4963
4964 command_beg = cp;
4965 /*
4966 * Make sure that the command is '\0'-terminated. This protects
4967 * against malicious programs; under normal operation this never
4968 * ends up being a problem..
4969 */
4970 for (; cp < &arguments[argmax]; cp++) {
4971 if (*cp == '\0') {
4972 /*
4973 * End of first argument reached
4974 */
4975 break;
4976 }
4977 }
4978 if (cp == &arguments[argmax])
4979 return(0);
4980
4981 command_end = command = cp;
4982
4983 /*
4984 * Get the basename of command
4985 */
4986 for (command--; command >= command_beg; command--) {
4987 if (*command == '/') {
4988 command++;
4989 break;
4990 }
4991 }
4992 (void) strncpy(cbuf, (char *)command, csize);
4993 cbuf[csize-1] = '\0';
4994
4995 return(1);
4996 }