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