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