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