]> git.saurik.com Git - apple/system_cmds.git/blobdiff - fs_usage.tproj/fs_usage.c
system_cmds-279.6.1.tar.gz
[apple/system_cmds.git] / fs_usage.tproj / fs_usage.c
index 1027e59ccfc18f4e5416ddf8dc5276f5d20a8cd0..041d30c88163e6d7dba45b3feedebf8313179127 100644 (file)
@@ -35,6 +35,7 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 #include <nlist.h>
 #include <fcntl.h>
 #include <string.h>
 #include <nlist.h>
 #include <fcntl.h>
 #include <string.h>
+#include <dirent.h>
 
 #include <sys/types.h>
 #include <sys/param.h>
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -42,7 +43,6 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 
 #include <libc.h>
 #include <termios.h>
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
 #include <sys/ioctl.h>
 
 #ifndef KERNEL_PRIVATE
 #include <sys/ioctl.h>
 
 #ifndef KERNEL_PRIVATE
@@ -61,19 +61,47 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 extern int errno;
 
 
 extern int errno;
 
 
+
+#define MAXINDEX 2048
+
+typedef struct LibraryInfo {
+     unsigned long address;
+     char     *name;
+} LibraryInfo;
+
+LibraryInfo frameworkInfo[MAXINDEX];
+int numFrameworks = 0;
+
+char seg_addr_table[256]="/AppleInternal/Developer/seg_addr_table";
+
+char *lookup_name();
+
+
+/* 
+   MAXCOLS controls when extra data kicks in.
+   MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
+   If NUMPARMS changes to match the kernel, it will automatically
+   get reflected in the -w mode output.
+*/
+#define NUMPARMS 23
+#define PATHLENGTH (NUMPARMS*sizeof(long))
+#define MAXCOLS 131
+#define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
+
 struct th_info {
         int  in_filemgr;
         int  thread;
 struct th_info {
         int  in_filemgr;
         int  thread;
+        int  pid;
         int  type;
         int  arg1;
         int  arg2;
         int  arg3;
         int  arg4;
         int  type;
         int  arg1;
         int  arg2;
         int  arg3;
         int  arg4;
-        int  vfslookup;
         int  child_thread;
         int  waited;
         double stime;
         int  child_thread;
         int  waited;
         double stime;
-        char pathname[32];
+        long *pathptr;
+        char pathname[PATHLENGTH + 1];   /* add room for null terminator */
 };
 
 #define MAX_THREADS 512
 };
 
 #define MAX_THREADS 512
@@ -84,11 +112,68 @@ int  cur_max = 0;
 int  need_new_map = 1;
 int  bias_secs;
 int  wideflag = 0;
 int  need_new_map = 1;
 int  bias_secs;
 int  wideflag = 0;
+int  columns = 0;
 int  select_pid_mode = 0;  /* Flag set indicates that output is restricted
                              to selected pids or commands */
 
 int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 
 int  select_pid_mode = 0;  /* Flag set indicates that output is restricted
                              to selected pids or commands */
 
 int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 
+char   *arguments = 0;
+int     argmax = 0;
+
+/*
+ * Network only or filesystem only output filter
+ * Default of zero means report all activity - no filtering
+ */
+#define FILESYS_FILTER 0x01
+#define NETWORK_FILTER 0x02
+#define DEFAULT_DO_NOT_FILTER 0x0
+int filter_mode = DEFAULT_DO_NOT_FILTER;
+
+#define NFS_DEV -1
+
+struct diskrec {
+        struct diskrec *next;
+        char *diskname;
+        int   dev;
+};
+
+struct diskio {
+        struct diskio *next;
+        struct diskio *prev;
+        int  type;
+        int  bp;
+        int  dev;
+        int  blkno;
+        int  iosize;
+        int  io_errno;
+        int  issuing_thread;
+        int  completion_thread;
+        char issuing_command[MAXCOMLEN];
+        double issued_time;
+        double completed_time;
+};
+
+struct diskrec *disk_list = NULL;
+struct diskio *free_diskios = NULL;
+struct diskio *busy_diskios = NULL;
+
+struct diskio *insert_diskio();
+struct diskio *complete_diskio();
+void           free_diskio();
+void           print_diskio();
+void           format_print();
+char           *find_disk_name();
+void           cache_disk_names();
+int            ReadSegAddrTable();
+void           mark_thread_waited(int);
+int            check_filter_mode(struct th_info *, int, int, int);
+void           fs_usage_fd_set(unsigned int, unsigned int);
+int            fs_usage_fd_isset(unsigned int, unsigned int);
+void           fs_usage_fd_clear(unsigned int, unsigned int);
+void           init_arguments_buffer();
+int            get_real_command_name(int, char *, int);
+void            create_map_entry(int, int, char *);
 
 #define DBG_ZERO_FILL_FAULT   1
 #define DBG_PAGEIN_FAULT      2
 
 #define DBG_ZERO_FILL_FAULT   1
 #define DBG_PAGEIN_FAULT      2
@@ -96,20 +181,58 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define DBG_CACHE_HIT_FAULT   4
 
 #define TRACE_DATA_NEWTHREAD   0x07000004
 #define DBG_CACHE_HIT_FAULT   4
 
 #define TRACE_DATA_NEWTHREAD   0x07000004
+#define TRACE_DATA_EXEC        0x07000008
 #define TRACE_STRING_NEWTHREAD 0x07010004
 #define TRACE_STRING_EXEC      0x07010008
 
 #define MACH_vmfault    0x01300000
 #define TRACE_STRING_NEWTHREAD 0x07010004
 #define TRACE_STRING_EXEC      0x07010008
 
 #define MACH_vmfault    0x01300000
+#define MACH_pageout    0x01300004
 #define MACH_sched      0x01400000
 #define MACH_stkhandoff 0x01400008
 #define VFS_LOOKUP      0x03010090
 #define BSC_exit        0x040C0004
 
 #define MACH_sched      0x01400000
 #define MACH_stkhandoff 0x01400008
 #define VFS_LOOKUP      0x03010090
 #define BSC_exit        0x040C0004
 
+#define P_WrData       0x03020000
+#define P_RdData       0x03020008
+#define P_WrMeta       0x03020020
+#define P_RdMeta       0x03020028
+#define P_PgOut                0x03020040
+#define P_PgIn         0x03020048
+#define P_WrDataAsync  0x03020010
+#define P_RdDataAsync  0x03020018
+#define P_WrMetaAsync  0x03020030
+#define P_RdMetaAsync  0x03020038
+#define P_PgOutAsync   0x03020050
+#define P_PgInAsync    0x03020058
+
+#define P_WrDataDone   0x03020004
+#define P_RdDataDone   0x0302000C
+#define P_WrMetaDone   0x03020024
+#define P_RdMetaDone   0x0302002C
+#define P_PgOutDone    0x03020044
+#define P_PgInDone     0x0302004C
+#define P_WrDataAsyncDone      0x03020014
+#define P_RdDataAsyncDone      0x0302001C
+#define P_WrMetaAsyncDone      0x03020034
+#define P_RdMetaAsyncDone      0x0302003C
+#define P_PgOutAsyncDone       0x03020054
+#define P_PgInAsyncDone                0x0302005C
+
+
 #define MSC_map_fd   0x010c00ac
 #define MSC_map_fd   0x010c00ac
+
+// Network related codes
 #define        BSC_recvmsg  0x040C006C
 #define        BSC_sendmsg  0x040C0070
 #define        BSC_recvfrom 0x040C0074
 #define        BSC_recvmsg  0x040C006C
 #define        BSC_sendmsg  0x040C0070
 #define        BSC_recvfrom 0x040C0074
+#define BSC_accept   0x040C0078
+#define BSC_select   0x040C0174
+#define BSC_socket   0x040C0184
+#define BSC_connect  0x040C0188
+#define BSC_bind     0x040C01A0
+#define BSC_listen   0x040C01A8
 #define        BSC_sendto   0x040C0214
 #define        BSC_sendto   0x040C0214
+#define BSC_socketpair 0x040C021C
 
 #define BSC_read     0x040C000C
 #define BSC_write    0x040C0010
 
 #define BSC_read     0x040C000C
 #define BSC_write    0x040C0010
@@ -117,23 +240,36 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define BSC_close    0x040C0018
 #define BSC_link     0x040C0024
 #define BSC_unlink   0x040C0028
 #define BSC_close    0x040C0018
 #define BSC_link     0x040C0024
 #define BSC_unlink   0x040C0028
+#define BSC_chdir    0x040c0030
+#define BSC_fchdir   0x040c0034
 #define BSC_mknod    0x040C0038        
 #define BSC_chmod    0x040C003C        
 #define BSC_chown    0x040C0040        
 #define BSC_access   0x040C0084        
 #define BSC_chflags  0x040C0088        
 #define BSC_fchflags 0x040C008C
 #define BSC_mknod    0x040C0038        
 #define BSC_chmod    0x040C003C        
 #define BSC_chown    0x040C0040        
 #define BSC_access   0x040C0084        
 #define BSC_chflags  0x040C0088        
 #define BSC_fchflags 0x040C008C
-#define BSC_sync     0x040C0090        
+#define BSC_sync     0x040C0090
+#define BSC_dup      0x040C00A4
+#define BSC_revoke   0x040C00E0
 #define BSC_symlink  0x040C00E4        
 #define BSC_symlink  0x040C00E4        
-#define BSC_readlink 0x040C00E8        
+#define BSC_readlink 0x040C00E8
+#define BSC_chroot   0x040C00F4
+#define BSC_dup2     0x040C0168
 #define BSC_fsync    0x040C017C        
 #define BSC_readv    0x040C01E0        
 #define BSC_writev   0x040C01E4        
 #define BSC_fchown   0x040C01EC        
 #define BSC_fchmod   0x040C01F0        
 #define BSC_fsync    0x040C017C        
 #define BSC_readv    0x040C01E0        
 #define BSC_writev   0x040C01E4        
 #define BSC_fchown   0x040C01EC        
 #define BSC_fchmod   0x040C01F0        
-#define BSC_rename   0x040C0200        
+#define BSC_rename   0x040C0200
+#define BSC_mkfifo   0x040c0210        
 #define BSC_mkdir    0x040C0220        
 #define BSC_mkdir    0x040C0220        
-#define BSC_rmdir    0x040C0224        
+#define BSC_rmdir    0x040C0224
+#define BSC_utimes   0x040C0228
+#define BSC_futimes  0x040C022C
+#define BSC_pread    0x040C0264
+#define BSC_pread_extended    0x040E0264
+#define BSC_pwrite   0x040C0268
+#define BSC_pwrite_extended   0x040E0268
 #define BSC_statfs   0x040C0274        
 #define BSC_fstatfs  0x040C0278        
 #define BSC_stat     0x040C02F0        
 #define BSC_statfs   0x040C0274        
 #define BSC_fstatfs  0x040C0278        
 #define BSC_stat     0x040C02F0        
@@ -145,17 +281,22 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define BSC_mmap     0x040c0314
 #define BSC_lseek    0x040c031c
 #define BSC_truncate 0x040C0320
 #define BSC_mmap     0x040c0314
 #define BSC_lseek    0x040c031c
 #define BSC_truncate 0x040C0320
-#define BSC_ftruncate     0x040C0324   
+#define BSC_ftruncate     0x040C0324
+#define BSC_undelete 0x040C0334
 #define BSC_statv    0x040C0364        
 #define BSC_lstatv   0x040C0368        
 #define BSC_fstatv   0x040C036C        
 #define BSC_statv    0x040C0364        
 #define BSC_lstatv   0x040C0368        
 #define BSC_fstatv   0x040C036C        
-#define BSC_mkcomplex     0x040C0360   
+#define BSC_mkcomplex   0x040C0360     
 #define BSC_getattrlist 0x040C0370     
 #define BSC_setattrlist 0x040C0374     
 #define BSC_getdirentriesattr 0x040C0378       
 #define BSC_exchangedata  0x040C037C   
 #define BSC_checkuseraccess   0x040C0380       
 #define BSC_getattrlist 0x040C0370     
 #define BSC_setattrlist 0x040C0374     
 #define BSC_getdirentriesattr 0x040C0378       
 #define BSC_exchangedata  0x040C037C   
 #define BSC_checkuseraccess   0x040C0380       
-#define BSC_searchfs    0x040C0384     
+#define BSC_searchfs    0x040C0384
+#define BSC_delete      0x040C0388
+#define BSC_copyfile    0x040C038C
+#define BSC_fsctl       0x040C03C8
+#define BSC_load_shared_file  0x040C04A0
 
 // Carbon File Manager support
 #define FILEMGR_PBGETCATALOGINFO                0x1e000020
 
 // Carbon File Manager support
 #define FILEMGR_PBGETCATALOGINFO                0x1e000020
@@ -234,6 +375,7 @@ int    pids[MAX_PIDS];
 
 int    num_of_pids = 0;
 int    exclude_pids = 0;
 
 int    num_of_pids = 0;
 int    exclude_pids = 0;
+int    exclude_default_pids = 1;
 
 struct kinfo_proc *kp_buffer = 0;
 int kp_nentries = 0;
 
 struct kinfo_proc *kp_buffer = 0;
 int kp_nentries = 0;
@@ -248,18 +390,32 @@ int kp_nentries = 0;
 #define DBG_FUNC_ALL   (DBG_FUNC_START | DBG_FUNC_END)
 #define DBG_FUNC_MASK  0xfffffffc
 
 #define DBG_FUNC_ALL   (DBG_FUNC_START | DBG_FUNC_END)
 #define DBG_FUNC_MASK  0xfffffffc
 
-/* Default divisor */
-#define DIVISOR 16.6666        /* Trace divisor converts to microseconds */
-double divisor = DIVISOR;
+double divisor = 0.0;       /* Trace divisor converts to microseconds */
 
 int mib[6];
 size_t needed;
 char  *my_buffer;
 
 
 int mib[6];
 size_t needed;
 char  *my_buffer;
 
-kbufinfo_t bufinfo = {0, 0, 0, 0};
+kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
 
 int total_threads = 0;
 
 int total_threads = 0;
-kd_threadmap *mapptr = 0;
+kd_threadmap *mapptr = 0;      /* pointer to list of threads */
+
+/* defines for tracking file descriptor state */
+#define FS_USAGE_FD_SETSIZE 256                /* Initial number of file descriptors per
+                                          thread that we will track */
+
+#define FS_USAGE_NFDBITS      (sizeof (unsigned long) * 8)
+#define FS_USAGE_NFDBYTES(n)  (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
+
+typedef struct {
+    unsigned int   fd_valid;       /* set if this is a valid entry */
+    unsigned int   fd_thread;
+    unsigned int   fd_setsize;     /* this is a bit count */
+    unsigned long  *fd_setptr;     /* file descripter bitmap */
+} fd_threadmap;
+
+fd_threadmap *fdmapptr = 0;    /* pointer to list of threads for fd tracking */
 
 int trace_enabled = 0;
 int set_remove_flag = 1;
 
 int trace_enabled = 0;
 int set_remove_flag = 1;
@@ -297,24 +453,45 @@ void leave()                      /* exit under normal conditions -- INT handler */
 }
 
 
 }
 
 
+void get_screenwidth()
+{
+        struct winsize size;
+
+       columns = MAXCOLS;
+
+       if (isatty(1)) {
+               if (ioctl(1, TIOCGWINSZ, &size) != -1)
+                       columns = size.ws_col;
+       }
+}
+
+
 void sigwinch()
 {
 void sigwinch()
 {
-       initscr();
+        if (!wideflag)
+               get_screenwidth();
 }
 
 int
 }
 
 int
-exit_usage(myname) {
+exit_usage(char *myname) {
 
 
-        fprintf(stderr, "Usage: %s [-e] [-w] [pid | cmd [pid | cmd]....]\n", myname);
-       fprintf(stderr, "  -e    exclude the pids specified from the sample\n");
+        fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname);
+       fprintf(stderr, "  -e    exclude the specified list of pids from the sample\n");
+       fprintf(stderr, "        and exclude fs_usage by default\n");
        fprintf(stderr, "  -w    force wider, detailed, output\n");
        fprintf(stderr, "  -w    force wider, detailed, output\n");
+       fprintf(stderr, "  -f    Output is filtered based on the mode provided\n");
+       fprintf(stderr, "          mode = \"network\"  Show only network related output\n");
+       fprintf(stderr, "          mode = \"filesys\"  Show only file system  related output\n");
        fprintf(stderr, "  pid   selects process(s) to sample\n");
        fprintf(stderr, "  cmd   selects process(s) matching command string to sample\n");
        fprintf(stderr, "  pid   selects process(s) to sample\n");
        fprintf(stderr, "  cmd   selects process(s) matching command string to sample\n");
+       fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
+       fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
+       fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
 
        exit(1);
 }
 
 
        exit(1);
 }
 
-
+int
 main(argc, argv)
        int     argc;
        char    *argv[];
 main(argc, argv)
        int     argc;
        char    *argv[];
@@ -333,8 +510,7 @@ main(argc, argv)
             printf("'fs_usage' must be run as root...\n");
             exit(1);
         }
             printf("'fs_usage' must be run as root...\n");
             exit(1);
         }
-
-       initscr();
+       get_screenwidth();
 
        /* get our name */
        if (argc > 0) {
 
        /* get our name */
        if (argc > 0) {
@@ -345,15 +521,26 @@ main(argc, argv)
                        myname++;
                }
        }
                        myname++;
                }
        }
+
        
        
-       while ((ch = getopt(argc, argv, "ew")) != EOF) {
+       while ((ch = getopt(argc, argv, "ewf:")) != EOF) {
                switch(ch) {
                 case 'e':
                    exclude_pids = 1;
                switch(ch) {
                 case 'e':
                    exclude_pids = 1;
+                   exclude_default_pids = 0;
                    break;
                 case 'w':
                    wideflag = 1;
                    break;
                 case 'w':
                    wideflag = 1;
-                   break;
+                   if ((uint)columns < MAX_WIDE_MODE_COLS)
+                     columns = MAX_WIDE_MODE_COLS;
+                   break;
+              case 'f':
+                  if (!strcmp(optarg, "network"))
+                      filter_mode |= NETWORK_FILTER;
+                  else if (!strcmp(optarg, "filesys"))
+                      filter_mode |= FILESYS_FILTER;
+                  break;
+                      
               default:
                 exit_usage(myname);             
               }
               default:
                 exit_usage(myname);             
               }
@@ -362,6 +549,10 @@ main(argc, argv)
         argc -= optind;
         argv += optind;
 
         argc -= optind;
         argv += optind;
 
+       /* If we process any list of pids/cmds, then turn off the defaults */
+       if (argc > 0)
+         exclude_default_pids = 0;
+
        while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
          select_pid_mode++;
          argtopid(argv[0]);
        while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
          select_pid_mode++;
          argtopid(argv[0]);
@@ -369,8 +560,27 @@ main(argc, argv)
          argv++;
        }
 
          argv++;
        }
 
+       /* Exclude a set of default pids */
+       if (exclude_default_pids)
+         {
+           argtopid("Terminal");
+           argtopid("telnetd");
+           argtopid("telnet");
+           argtopid("sshd");
+           argtopid("rlogind");
+           argtopid("tcsh");
+           argtopid("csh");
+           argtopid("sh");
+           exclude_pids = 1;
+         }
+
        if (exclude_pids)
        if (exclude_pids)
+         {
+           if (num_of_pids < (MAX_PIDS - 1))
                pids[num_of_pids++] = getpid();
                pids[num_of_pids++] = getpid();
+           else
+             exit_usage(myname);
+         }
 
 #if 0
        for (i = 0; i < num_of_pids; i++)
 
 #if 0
        for (i = 0; i < num_of_pids; i++)
@@ -385,12 +595,16 @@ main(argc, argv)
        /* set up signal handlers */
        signal(SIGINT, leave);
        signal(SIGQUIT, leave);
        /* set up signal handlers */
        signal(SIGINT, leave);
        signal(SIGQUIT, leave);
+       signal(SIGHUP, leave);
        signal(SIGTERM, leave);
        signal(SIGWINCH, sigwinch);
 
        if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
            quit("can't allocate memory for tracing info\n");
 
        signal(SIGTERM, leave);
        signal(SIGWINCH, sigwinch);
 
        if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
            quit("can't allocate memory for tracing info\n");
 
+       ReadSegAddrTable();
+        cache_disk_names();
+
        set_remove();
        set_numbufs(SAMPLE_SIZE);
        set_init();
        set_remove();
        set_numbufs(SAMPLE_SIZE);
        set_init();
@@ -415,12 +629,13 @@ main(argc, argv)
 
        set_enable(1);
        getdivisor();
 
        set_enable(1);
        getdivisor();
+       init_arguments_buffer();
 
 
        /* main loop */
 
        while (1) {
 
 
        /* main loop */
 
        while (1) {
-               usleep(1000 * 50);
+               usleep(1000 * 25);
 
                sample_sc();
        }
 
                sample_sc();
        }
@@ -429,7 +644,7 @@ main(argc, argv)
 void
 find_proc_names()
 {
 void
 find_proc_names()
 {
-       size_t                  bufSize = 0;
+        size_t                 bufSize = 0;
        struct kinfo_proc       *kp;
        int quit();
 
        struct kinfo_proc       *kp;
        int quit();
 
@@ -471,6 +686,19 @@ struct th_info *find_thread(int thread, int type) {
        return ((struct th_info *)0);
 }
 
        return ((struct th_info *)0);
 }
 
+
+void
+mark_thread_waited(int thread) {
+       struct th_info *ti;
+
+       for (ti = th_state; ti < &th_state[cur_max]; ti++) {
+              if (ti->thread == thread) {
+                    ti->waited = 1;
+              }
+       }
+}
+
+
 void
 set_enable(int val) 
 {
 void
 set_enable(int val) 
 {
@@ -583,8 +811,6 @@ get_bufinfo(kbufinfo_t *val)
 void
 set_remove() 
 {
 void
 set_remove() 
 {
-        extern int errno;
-
         errno = 0;
 
        mib[0] = CTL_KERN;
         errno = 0;
 
        mib[0] = CTL_KERN;
@@ -638,6 +864,7 @@ sample_sc()
 {
        kd_buf *kd;
        int i, count;
 {
        kd_buf *kd;
        int i, count;
+       size_t needed;
        void read_command_map();
        void create_map_entry();
 
        void read_command_map();
        void create_map_entry();
 
@@ -665,7 +892,8 @@ sample_sc()
 
                for (i = 0; i < cur_max; i++) {
                        th_state[i].thread = 0;
 
                for (i = 0; i < cur_max; i++) {
                        th_state[i].thread = 0;
-                       th_state[i].vfslookup = 0;
+                       th_state[i].pid = 0;
+                       th_state[i].pathptr = (long *)0;
                        th_state[i].pathname[0] = 0;
                }
                cur_max = 0;
                        th_state[i].pathname[0] = 0;
                }
                cur_max = 0;
@@ -682,20 +910,75 @@ sample_sc()
                int debugid, thread;
                int type, n;
                long *sargptr;
                int debugid, thread;
                int type, n;
                long *sargptr;
-               unsigned long long now;
+               uint64_t now;
+               long long l_usecs;
+               int secs;
+               long curr_time;
                struct th_info *ti;
                struct th_info *ti;
+                struct diskio  *dio;
                void enter_syscall();
                void exit_syscall();
                void enter_syscall();
                void exit_syscall();
+               void extend_syscall();
                void kill_thread_map();
 
                thread  = kd[i].arg5 & KDBG_THREAD_MASK;
                debugid = kd[i].debugid;
                type    = kd[i].debugid & DBG_FUNC_MASK;
                void kill_thread_map();
 
                thread  = kd[i].arg5 & KDBG_THREAD_MASK;
                debugid = kd[i].debugid;
                type    = kd[i].debugid & DBG_FUNC_MASK;
+                
+                now = kd[i].timestamp;
+
+               if (i == 0)
+               {
+                   /*
+                    * Compute bias seconds after each trace buffer read.
+                    * This helps resync timestamps with the system clock
+                    * in the event of a system sleep.
+                    */
+                   l_usecs = (long long)(now / divisor);
+                   secs = l_usecs / 1000000;
+                   curr_time = time((long *)0);
+                   bias_secs = curr_time - secs;
+               }
+
 
                switch (type) {
 
 
                switch (type) {
 
+                case P_RdMeta:
+                case P_WrMeta:
+                case P_RdData:
+                case P_WrData:
+                case P_PgIn:
+                case P_PgOut:
+                case P_RdMetaAsync:
+                case P_WrMetaAsync:
+                case P_RdDataAsync:
+                case P_WrDataAsync:
+                case P_PgInAsync:
+                case P_PgOutAsync:
+                    insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
+                    continue;
+                
+                case P_RdMetaDone:
+                case P_WrMetaDone:
+                case P_RdDataDone:
+                case P_WrDataDone:
+                case P_PgInDone:
+                case P_PgOutDone:
+                case P_RdMetaAsyncDone:
+                case P_WrMetaAsyncDone:
+                case P_RdDataAsyncDone:
+                case P_WrDataAsyncDone:
+                case P_PgInAsyncDone:
+                case P_PgOutAsyncDone:
+                    if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
+                        print_diskio(dio);
+                        free_diskio(dio);
+                    }
+                    continue;
+
+
                case TRACE_DATA_NEWTHREAD:
                case TRACE_DATA_NEWTHREAD:
-                  
+                   
                    for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
                        if (ti->thread == 0)
                           break;
                    for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
                        if (ti->thread == 0)
                           break;
@@ -707,6 +990,7 @@ sample_sc()
 
                    ti->thread = thread;
                    ti->child_thread = kd[i].arg1;
 
                    ti->thread = thread;
                    ti->child_thread = kd[i].arg1;
+                   ti->pid = kd[i].arg2;
                    continue;
 
                case TRACE_STRING_NEWTHREAD:
                    continue;
 
                case TRACE_STRING_NEWTHREAD:
@@ -714,16 +998,44 @@ sample_sc()
                            continue;
                    if (ti->child_thread == 0)
                            continue;
                            continue;
                    if (ti->child_thread == 0)
                            continue;
-                   create_map_entry(ti->child_thread, (char *)&kd[i].arg1);
+                   create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
 
                    if (ti == &th_state[cur_max - 1])
                        cur_max--;
                    ti->child_thread = 0;
                    ti->thread = 0;
 
                    if (ti == &th_state[cur_max - 1])
                        cur_max--;
                    ti->child_thread = 0;
                    ti->thread = 0;
+                   ti->pid = 0;
                    continue;
                    continue;
+       
+               case TRACE_DATA_EXEC:
+
+                   for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
+                       if (ti->thread == 0)
+                          break;
+                   }
+                   if (ti == &th_state[MAX_THREADS])
+                       continue;
+                   if (n >= cur_max)
+                       cur_max = n + 1;
+
+                   ti->thread = thread;
+                   ti->pid = kd[i].arg1;
+                   continue;       
 
                case TRACE_STRING_EXEC:
 
                case TRACE_STRING_EXEC:
-                   create_map_entry(thread, (char *)&kd[i].arg1);
+                   if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
+                   {
+                       /* this is for backwards compatibility */
+                       create_map_entry(thread, 0, (char *)&kd[i].arg1);
+                   }
+                   else
+                   {
+                       create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
+                       if (ti == &th_state[cur_max - 1])
+                           cur_max--;
+                       ti->thread = 0;
+                       ti->pid = 0;
+                   }
                    continue;
 
                case BSC_exit:
                    continue;
 
                case BSC_exit:
@@ -732,36 +1044,53 @@ sample_sc()
 
                case MACH_sched:
                case MACH_stkhandoff:
 
                case MACH_sched:
                case MACH_stkhandoff:
-                   if (ti = find_thread(thread, 0))
-                           ti->waited = 1;
+                    mark_thread_waited(thread);
                    continue;
 
                case VFS_LOOKUP:
                    if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
                            continue;
 
                    continue;
 
                case VFS_LOOKUP:
                    if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
                            continue;
 
-                   if (ti->vfslookup == 0) {
-                           ti->vfslookup = 1;
-                           memset(&ti->pathname[0], 0, 32);
+                   if (!ti->pathptr) {
                            sargptr = (long *)&ti->pathname[0];
                            sargptr = (long *)&ti->pathname[0];
-                               
+                           memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
                            *sargptr++ = kd[i].arg2;
                            *sargptr++ = kd[i].arg3;
                            *sargptr++ = kd[i].arg4;
                            *sargptr++ = kd[i].arg2;
                            *sargptr++ = kd[i].arg3;
                            *sargptr++ = kd[i].arg4;
+                           ti->pathptr = sargptr;
+                   } else {
+                           sargptr = ti->pathptr;
+
+                           /* 
+                              We don't want to overrun our pathname buffer if the
+                              kernel sends us more VFS_LOOKUP entries than we can
+                              handle.
+                           */
+
+                           if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
+                             continue;
+
+                            /*
+                             We need to detect consecutive vfslookup entries.
+                             So, if we get here and find a START entry,
+                             fake the pathptr so we can bypass all further
+                             vfslookup entries.
+                           */
+
+                           if (debugid & DBG_FUNC_START)
+                             {
+                               (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
+                               continue;
+                             }
 
 
-                   } else if (ti->vfslookup == 1) {
-                           ti->vfslookup = 2;
-         
-                           sargptr = (long *)&ti->pathname[12];
                            *sargptr++ = kd[i].arg1;
                            *sargptr++ = kd[i].arg2;
                            *sargptr++ = kd[i].arg3;
                            *sargptr++ = kd[i].arg4;
                            *sargptr++ = kd[i].arg1;
                            *sargptr++ = kd[i].arg2;
                            *sargptr++ = kd[i].arg3;
                            *sargptr++ = kd[i].arg4;
+                           ti->pathptr = sargptr;
                    }
                    continue;
                }
                    }
                    continue;
                }
-               now = (((unsigned long long)kd[i].timestamp.tv_sec) << 32) |
-                       (unsigned long long)((unsigned int)(kd[i].timestamp.tv_nsec));
 
                if (debugid & DBG_FUNC_START) {
                       char *p;
 
                if (debugid & DBG_FUNC_START) {
                       char *p;
@@ -973,13 +1302,27 @@ sample_sc()
                        enter_syscall(thread, type, &kd[i], p, (double)now);
                        continue;
                }
                        enter_syscall(thread, type, &kd[i], p, (double)now);
                        continue;
                }
+               
                switch (type) {
                switch (type) {
+                   
+               case BSC_pread_extended:
+               case BSC_pwrite_extended:
+                   extend_syscall(thread, type, &kd[i], (double)now);
+
+               case MACH_pageout:
+                   if (kd[i].arg2) 
+                           exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
+                   else
+                           exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
+                   break;
 
                case MACH_vmfault:
                    if (kd[i].arg2 == DBG_PAGEIN_FAULT)
 
                case MACH_vmfault:
                    if (kd[i].arg2 == DBG_PAGEIN_FAULT)
-                           exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
+                           exit_syscall("PAGE_IN", thread, type, kd[i].arg4, kd[i].arg1, 0, 6, (double)now);
+                    else if (kd[i].arg2 == DBG_CACHE_HIT_FAULT)
+                           exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
                    else {
                    else {
-                           if (ti = find_thread(thread, type)) {
+                           if ((ti = find_thread(thread, type))) {
                                    if (ti == &th_state[cur_max - 1])
                                            cur_max--;
                                    ti->thread = 0;
                                    if (ti == &th_state[cur_max - 1])
                                            cur_max--;
                                    ti->thread = 0;
@@ -994,7 +1337,7 @@ sample_sc()
                case BSC_mmap:
                    exit_syscall("mmap", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
                case BSC_mmap:
                    exit_syscall("mmap", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
-
+                   
                case BSC_recvmsg:
                    exit_syscall("recvmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
                case BSC_recvmsg:
                    exit_syscall("recvmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
@@ -1007,18 +1350,58 @@ sample_sc()
                    exit_syscall("recvfrom", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
                    exit_syscall("recvfrom", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
+               case BSC_accept:
+                   exit_syscall("accept", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
+                   break;
+                   
+               case BSC_select:
+                   exit_syscall("select", thread, type, kd[i].arg1, kd[i].arg2, 0, 8, (double)now);
+                   break;
+                   
+               case BSC_socket:
+                   exit_syscall("socket", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
+                   break;
+
+               case BSC_connect:
+                   exit_syscall("connect", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_bind:
+                   exit_syscall("bind", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_listen:
+                   exit_syscall("listen", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
                case BSC_sendto:
                    exit_syscall("sendto", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
                case BSC_sendto:
                    exit_syscall("sendto", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
+               case BSC_socketpair:
+                   exit_syscall("socketpair", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                   
                case BSC_stat:
                    exit_syscall("stat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
                case BSC_stat:
                    exit_syscall("stat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_load_shared_file:
+                   exit_syscall("load_sf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
 
                case BSC_open:
                    exit_syscall("open", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
                    break;
 
 
                case BSC_open:
                    exit_syscall("open", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
                    break;
 
+               case BSC_dup:
+                   exit_syscall("dup", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
+                   break;
+
+               case BSC_dup2:
+                   exit_syscall("dup2", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
+                   break;                  
+
                case BSC_close:
                    exit_syscall("close", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
                case BSC_close:
                    exit_syscall("close", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
@@ -1063,13 +1446,49 @@ sample_sc()
                    exit_syscall("access", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
 
                    exit_syscall("access", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
 
+               case BSC_chdir:
+                   exit_syscall("chdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_chroot:
+                   exit_syscall("chroot", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_utimes:
+                   exit_syscall("utimes", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_delete:
+                   exit_syscall("delete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_undelete:
+                   exit_syscall("undelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_revoke:
+                   exit_syscall("revoke", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_fsctl:
+                   exit_syscall("fsctl", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
                case BSC_chflags:
                    exit_syscall("chflags", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
                case BSC_chflags:
                    exit_syscall("chflags", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
-
+                    
                case BSC_fchflags:
                    exit_syscall("fchflags", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
                case BSC_fchflags:
                    exit_syscall("fchflags", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
+                    
+               case BSC_fchdir:
+                   exit_syscall("fchdir", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+                    
+               case BSC_futimes:
+                   exit_syscall("futimes", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
 
                case BSC_sync:
                    exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
 
                case BSC_sync:
                    exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1095,6 +1514,14 @@ sample_sc()
                    exit_syscall("writev", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
                    exit_syscall("writev", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
                    break;
 
+               case BSC_pread:
+                   exit_syscall("pread", thread, type, kd[i].arg1, kd[i].arg2, 1, 9, (double)now);
+                   break;
+
+               case BSC_pwrite:
+                   exit_syscall("pwrite", thread, type, kd[i].arg1, kd[i].arg2, 1, 9, (double)now);
+                   break;
+
                case BSC_fchown:
                    exit_syscall("fchown", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
                case BSC_fchown:
                    exit_syscall("fchown", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
@@ -1103,13 +1530,13 @@ sample_sc()
                    exit_syscall("fchmod", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
 
                    exit_syscall("fchmod", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
 
-               case BSC_rename:
-                   exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
-                   break;
-
                case BSC_mkdir:
                    exit_syscall("mkdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
                case BSC_mkdir:
                    exit_syscall("mkdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_mkfifo:
+                   exit_syscall("mkfifo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
 
                case BSC_rmdir:
                    exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
 
                case BSC_rmdir:
                    exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1175,9 +1602,19 @@ sample_sc()
                    exit_syscall("getdirentriesattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 1, (double)now);
                    break;
 
                    exit_syscall("getdirentriesattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 1, (double)now);
                    break;
 
+
                case BSC_exchangedata:
                    exit_syscall("exchangedata", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
                case BSC_exchangedata:
                    exit_syscall("exchangedata", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_rename:
+                   exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_copyfile:
+                   exit_syscall("copyfile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
 
                case BSC_checkuseraccess:
                    exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
 
                case BSC_checkuseraccess:
                    exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1401,20 +1838,36 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
        int    usecs;
        long long l_usecs;
        long curr_time;
        int    usecs;
        long long l_usecs;
        long curr_time;
-          kd_threadmap *map;
-          kd_threadmap *find_thread_map();
+       kd_threadmap *map;
+       kd_threadmap *find_thread_map();
+       int clen = 0;
+       int tsclen = 0;
+       int nmclen = 0;
+       int argsclen = 0;
+       char buf[MAXCOLS];
 
        switch (type) {
 
 
        switch (type) {
 
+       case MACH_pageout:
        case MACH_vmfault:
        case MSC_map_fd:
        case BSC_mmap:
        case BSC_recvmsg:
        case BSC_sendmsg:
        case BSC_recvfrom:
        case MACH_vmfault:
        case MSC_map_fd:
        case BSC_mmap:
        case BSC_recvmsg:
        case BSC_sendmsg:
        case BSC_recvfrom:
+       case BSC_accept:
+       case BSC_select:
+       case BSC_socket:
+       case BSC_connect:
+       case BSC_bind:
+       case BSC_listen:
        case BSC_sendto:
        case BSC_sendto:
+       case BSC_socketpair:
        case BSC_stat:
        case BSC_stat:
+       case BSC_load_shared_file:
        case BSC_open:
        case BSC_open:
+       case BSC_dup:
+       case BSC_dup2:
        case BSC_close:
        case BSC_read:
        case BSC_write:
        case BSC_close:
        case BSC_read:
        case BSC_write:
@@ -1428,16 +1881,29 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
        case BSC_access:
        case BSC_chflags:
        case BSC_fchflags:
        case BSC_access:
        case BSC_chflags:
        case BSC_fchflags:
+       case BSC_fchdir:
+       case BSC_futimes:
+       case BSC_chdir:
+       case BSC_utimes:
+       case BSC_chroot:
+       case BSC_undelete:
+       case BSC_delete:
+       case BSC_revoke:
+       case BSC_fsctl:
+       case BSC_copyfile:
        case BSC_sync:
        case BSC_symlink:
        case BSC_readlink:
        case BSC_fsync:
        case BSC_readv:
        case BSC_writev:
        case BSC_sync:
        case BSC_symlink:
        case BSC_readlink:
        case BSC_fsync:
        case BSC_readv:
        case BSC_writev:
+       case BSC_pread:
+       case BSC_pwrite:
        case BSC_fchown:
        case BSC_fchmod:
        case BSC_rename:
        case BSC_mkdir:
        case BSC_fchown:
        case BSC_fchmod:
        case BSC_rename:
        case BSC_mkdir:
+       case BSC_mkfifo:
        case BSC_rmdir:
        case BSC_statfs:
        case BSC_fstatfs:
        case BSC_rmdir:
        case BSC_statfs:
        case BSC_fstatfs:
@@ -1534,55 +2000,71 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
                   return;
           if (i >= cur_max)
                   cur_max = i + 1;
                   return;
           if (i >= cur_max)
                   cur_max = i + 1;
+                   
 
           if ((type >> 24) == FILEMGR_CLASS) {
                   ti->in_filemgr = 1;
 
                   l_usecs = (long long)(now / divisor);
                   secs = l_usecs / 1000000;
 
           if ((type >> 24) == FILEMGR_CLASS) {
                   ti->in_filemgr = 1;
 
                   l_usecs = (long long)(now / divisor);
                   secs = l_usecs / 1000000;
-
-                  if (bias_secs == 0) {
-                          curr_time = time((long *)0);
-                          bias_secs = curr_time - secs;
-                  }
                   curr_time = bias_secs + secs;
                   curr_time = bias_secs + secs;
-                  printf("%-8.8s", &(ctime(&curr_time)[11]));
+                  
+                  sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
+                  tsclen = strlen(buf);
 
 
-                  if (COLS > 110 || wideflag) {
+                  if (columns > MAXCOLS || wideflag) {
                           usecs = l_usecs - (long long)((long long)secs * 1000000);
                           usecs = l_usecs - (long long)((long long)secs * 1000000);
-                          printf(".%03ld", (long)usecs / 1000);
+                          sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
+                          tsclen = strlen(buf);
                   }
                   }
-                  map = find_thread_map(thread);
-                  if (map) {
-                      char buf[128];
-                      int  clen;
-
-                      sprintf(buf, "  %s", name);
-                      clen = strlen(buf);
-
-                      if (clen > 25)
-                          clen = 25;
-                      memset(&buf[clen], ' ', 26 - clen);
 
 
-                      sprintf(&buf[25], "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
-                      clen = strlen(&buf[25]) + 25;
-                      memset(&buf[clen], ' ', 128 - clen);
+                  /* Print timestamp column */
+                  printf("%s", buf);
 
 
-                      if (COLS > 110 || wideflag)
-                          sprintf(&buf[81], "%s\n", map->command); 
+                  map = find_thread_map(thread);
+                  if (map) {
+                      sprintf(buf, "  %-25.25s ", name);
+                      nmclen = strlen(buf);
+                      printf("%s", buf);
+
+                      sprintf(buf, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
+                      argsclen = strlen(buf);
+                      
+                      /*
+                        Calculate white space out to command
+                      */
+                      if (columns > MAXCOLS || wideflag)
+                        {
+                          clen = columns - (tsclen + nmclen + argsclen + 20);
+                        }
                       else
                       else
-                          sprintf(&buf[60], "%.12s\n", map->command); 
-
-                      printf(buf);
-
+                        clen = columns - (tsclen + nmclen + argsclen + 12);
+
+                      if(clen > 0)
+                        {
+                          printf("%s", buf);   /* print the kdargs */
+                          memset(buf, ' ', clen);
+                          buf[clen] = '\0';
+                          printf("%s", buf);
+                        }
+                      else if ((argsclen + clen) > 0)
+                        {
+                          /* no room so wipe out the kdargs */
+                          memset(buf, ' ', (argsclen + clen));
+                          buf[argsclen + clen] = '\0';
+                          printf("%s", buf);
+                        }
+
+                      if (columns > MAXCOLS || wideflag)
+                          printf("%-20.20s\n", map->command); 
+                      else
+                          printf("%-12.12s\n", map->command); 
                   } else
                           printf("  %-24.24s (%5d, %#x, 0x%x, 0x%x)\n",         name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
                   } else
                           printf("  %-24.24s (%5d, %#x, 0x%x, 0x%x)\n",         name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
-      
           } else {
                           ti->in_filemgr = 0;
           }
           ti->thread = thread;
           } else {
                           ti->in_filemgr = 0;
           }
           ti->thread = thread;
-          ti->vfslookup = 0;
           ti->waited = 0;
           ti->type   = type;
           ti->stime  = now;
           ti->waited = 0;
           ti->type   = type;
           ti->stime  = now;
@@ -1590,111 +2072,245 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
           ti->arg2   = kd->arg2;
           ti->arg3   = kd->arg3;
           ti->arg4   = kd->arg4;
           ti->arg2   = kd->arg2;
           ti->arg3   = kd->arg3;
           ti->arg4   = kd->arg4;
+          ti->pathptr = (long *)0;
           ti->pathname[0] = 0;
           ti->pathname[0] = 0;
-
           break;
 
        default:
           break;
        }
           break;
 
        default:
           break;
        }
+       fflush (0);
 }
 
 }
 
+/*
+ * Handle system call extended trace data.
+ * pread and pwrite:
+ *     Wipe out the kd args that were collected upon syscall_entry
+ *     because it is the extended info that we really want, and it
+ *     is all we really need.
+*/
+
+void
+extend_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+{
+       struct th_info *ti;
+
+       switch (type) {
+       case BSC_pread_extended:
+          if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0)
+              return;
+          ti->arg1   = kd->arg1;  /* the fd */
+          ti->arg2   = kd->arg2;  /* nbytes */
+          ti->arg3   = kd->arg3;  /* top half offset */
+          ti->arg4   = kd->arg4;  /* bottom half offset */        
+          break;
+       case BSC_pwrite_extended:
+          if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0)
+              return;
+          ti->arg1   = kd->arg1;  /* the fd */
+          ti->arg2   = kd->arg2;  /* nbytes */
+          ti->arg3   = kd->arg3;  /* top half offset */
+          ti->arg4   = kd->arg4;  /* bottom half offset */
+          break;
+       default:
+          return;
+       }
+}
 
 void
 exit_syscall(char *sc_name, int thread, int type, int error, int retval,
                            int has_fd, int has_ret, double now)
 {
 
 void
 exit_syscall(char *sc_name, int thread, int type, int error, int retval,
                            int has_fd, int has_ret, double now)
 {
-       struct th_info *ti;
+    struct th_info *ti;
+      
+    if ((ti = find_thread(thread, type)) == (struct th_info *)0)
+        return;
+
+    if (check_filter_mode(ti, type, error, retval))
+       format_print(ti, sc_name, thread, type, error, retval, has_fd, has_ret, now, ti->stime, ti->waited, ti->pathname, NULL);
+
+    if (ti == &th_state[cur_max - 1])
+        cur_max--;
+    ti->thread = 0;
+}
+
+
+
+void
+format_print(struct th_info *ti, char *sc_name, int thread, int type, int error, int retval,
+                           int has_fd, int has_ret, double now, double stime, int waited, char *pathname, struct diskio *dio)
+{
        int secs;
        int usecs;
        int nopadding;
        long long l_usecs;
        long curr_time;
        int secs;
        int usecs;
        int nopadding;
        long long l_usecs;
        long curr_time;
+       char *command_name;
        kd_threadmap *map;
        kd_threadmap *find_thread_map();
        kd_threadmap *map;
        kd_threadmap *find_thread_map();
+       int len = 0;
+       int clen = 0;
+       char *framework_name;
+       char buf[MAXCOLS];
       
       
-       if ((ti = find_thread(thread, type)) == (struct th_info *)0)
-              return;
-       map = find_thread_map(thread);
+       command_name = "";
+       
+       if (dio)
+            command_name = dio->issuing_command;
+       else {
+          if ((map = find_thread_map(thread)))
+                command_name = map->command;
+       }
+       
        l_usecs = (long long)(now / divisor);
        secs = l_usecs / 1000000;
        l_usecs = (long long)(now / divisor);
        secs = l_usecs / 1000000;
-
-       if (bias_secs == 0) {
-              curr_time = time((long *)0);
-              bias_secs = curr_time - secs;
-       }
        curr_time = bias_secs + secs;
        curr_time = bias_secs + secs;
-       printf("%-8.8s", &(ctime(&curr_time)[11]));
+       sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
+       clen = strlen(buf);
 
 
-
-       if (COLS > 110 || wideflag) {
+       if (columns > MAXCOLS || wideflag) {
               nopadding = 0;
               usecs = l_usecs - (long long)((long long)secs * 1000000);
               nopadding = 0;
               usecs = l_usecs - (long long)((long long)secs * 1000000);
-              printf(".%03ld", (long)usecs / 1000);
-
+              sprintf(&buf[clen], ".%03ld", (long)usecs / 1000);
+              clen = strlen(buf);
+               
               if ((type >> 24) != FILEMGR_CLASS) {
                   if (find_thread(thread, -1)) {
               if ((type >> 24) != FILEMGR_CLASS) {
                   if (find_thread(thread, -1)) {
-                      printf("   ");
+                      sprintf(&buf[clen], "   ");
+                      clen = strlen(buf);
                       nopadding = 1;
                   }
               }
        } else
               nopadding = 1;
 
                       nopadding = 1;
                   }
               }
        } else
               nopadding = 1;
 
-       if (((type >> 24) == FILEMGR_CLASS) && (COLS > 110 || wideflag)) 
-              printf("  %-18.18s", sc_name);
+       if (((type >> 24) == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
+              sprintf(&buf[clen], "  %-18.18s", sc_name);
        else
        else
-              printf("  %-15.15s", sc_name);
-
-       if (COLS > 110 || wideflag) {
+              sprintf(&buf[clen], "  %-15.15s", sc_name);
+
+       clen = strlen(buf);
+       
+       framework_name = (char *)0;
+
+       if (columns > MAXCOLS || wideflag) {
+            if (has_ret == 7) {
+                sprintf(&buf[clen], " D=0x%8.8x", dio->blkno);
+                
+                clen = strlen(buf);
+                
+                if (dio->io_errno)
+                    sprintf(&buf[clen], "  [%3d]       ", dio->io_errno);
+                else
+                    sprintf(&buf[clen], "  B=0x%-6x   /dev/%s", dio->iosize, find_disk_name(dio->dev));
+            } else {
+
+               off_t offset_reassembled = 0LL;
+               
               if (has_fd == 2 && error == 0)
               if (has_fd == 2 && error == 0)
-                      printf(" F=%-3d", retval);
+                      sprintf(&buf[clen], " F=%-3d", retval);
               else if (has_fd == 1)
               else if (has_fd == 1)
-                      printf(" F=%-3d", ti->arg1);
-              else if (has_ret != 2)
-                      printf("      ");
+                      sprintf(&buf[clen], " F=%-3d", ti->arg1);
+              else if (has_ret != 2 && has_ret != 6)
+                      sprintf(&buf[clen], "      ");
+
+              clen = strlen(buf);
+
+              if (has_ret == 2 || has_ret == 6)
+                      framework_name = lookup_name(retval);
 
 
-              if (error)
-                      printf("[%3d]       ", error);
+              if (error && has_ret != 6)
+                      sprintf(&buf[clen], "[%3d]       ", error);
               else if (has_ret == 3)
               else if (has_ret == 3)
-                      printf("O=0x%8.8x", ti->arg3);
+                      sprintf(&buf[clen], "O=0x%8.8x", ti->arg3);
               else if (has_ret == 5)
               else if (has_ret == 5)
-                      printf("O=0x%8.8x", retval);
+                      sprintf(&buf[clen], "O=0x%8.8x", retval);
               else if (has_ret == 2) 
               else if (has_ret == 2) 
-                      printf(" A=0x%8.8x     ", retval);
+                      sprintf(&buf[clen], " A=0x%8.8x              ", retval);
+              else if (has_ret == 6) 
+                      sprintf(&buf[clen], " A=0x%8.8x  B=0x%-8x", retval, error);
               else if (has_ret == 1)
               else if (has_ret == 1)
-                      printf("  B=0x%-6x", retval);
+                      sprintf(&buf[clen], "  B=0x%-6x", retval);
               else if (has_ret == 4)
               else if (has_ret == 4)
-                      printf("R=0x%-8x", retval);
+                      sprintf(&buf[clen], "B=0x%-8x", retval);
+              else if (has_ret == 8)  /* BSC_select */
+                      sprintf(&buf[clen], "  S=%-3d     ", retval);           
+              else if (has_ret == 9)  /* BSC_pread, BSC_pwrite */
+              {
+                  sprintf(&buf[clen], "B=0x%-8x", retval);
+                  clen = strlen(buf);
+                  offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
+                  if ((offset_reassembled >> 32) != 0)
+                      sprintf(&buf[clen], "O=0x%16.16qx", (off_t)offset_reassembled);
+                  else
+                      sprintf(&buf[clen], "O=0x%8.8qx", (off_t)offset_reassembled);
+              }
               else
               else
-                      printf("            ");
+                      sprintf(&buf[clen], "            ");
+            }
+            clen = strlen(buf);
        }
        }
-       printf(" %-28.28s ",  ti->pathname);
+       printf("%s", buf);
+
+       /*
+        Calculate space available to print pathname
+       */
+       if (columns > MAXCOLS || wideflag)
+        clen =  columns - (clen + 13 + 20);
+       else
+        clen =  columns - (clen + 13 + 12);
 
 
-       usecs = (unsigned long)(((double)now - ti->stime) / divisor);
+       if ((type >> 24) != FILEMGR_CLASS && !nopadding)
+        clen -= 3;
+
+       if (framework_name)
+        sprintf(&buf[0], " %s ", framework_name);
+       else
+        sprintf(&buf[0], " %s ", pathname);
+       len = strlen(buf);
+       
+       if (clen > len)
+        {
+          /* 
+             Add null padding if column length
+             is wider than the pathname length.
+          */
+          memset(&buf[len], ' ', clen - len);
+          buf[clen] = '\0';
+          printf("%s", buf);
+        }
+       else if (clen == len)
+        {
+          printf("%s", buf);
+        }
+       else if ((clen > 0) && (clen < len))
+        {
+          /* This prints the tail end of the pathname */
+          buf[len-clen] = ' ';
+          printf("%s", &buf[len - clen]);
+        }
+
+       usecs = (unsigned long)((now - stime) / divisor);
        secs = usecs / 1000000;
        usecs -= secs * 1000000;
 
        if ((type >> 24) != FILEMGR_CLASS && !nopadding)
               printf("   ");
               
        secs = usecs / 1000000;
        usecs -= secs * 1000000;
 
        if ((type >> 24) != FILEMGR_CLASS && !nopadding)
               printf("   ");
               
-       printf(" %2ld.%06ld", (long)secs, (long)usecs);
-       if (ti->waited)
+       printf(" %2ld.%06ld", (unsigned long)secs, (unsigned long)usecs);
+       
+       if (waited)
               printf(" W");
        else
               printf("  ");
 
               printf(" W");
        else
               printf("  ");
 
-       if (map) {
-              if (COLS > 110 || wideflag)
-                      printf(" %s", map->command);
-              else
-                      printf(" %.12s", map->command);
-       }
-       printf("\n");
+       if (columns > MAXCOLS || wideflag)
+               printf(" %-20.20s", command_name);
+       else
+               printf(" %-12.12s", command_name);
 
 
-       if (ti == &th_state[cur_max - 1])
-                cur_max--;
-       ti->thread = 0;
+       printf("\n");
+       fflush (0);
 }
 
 int
 }
 
 int
@@ -1728,7 +2344,7 @@ void getdivisor()
     unsigned int proc_to_abs_num;
     unsigned int proc_to_abs_denom;
 
     unsigned int proc_to_abs_num;
     unsigned int proc_to_abs_denom;
 
-       extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
+    extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
 
     MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
                       &proc_to_abs_num,  &proc_to_abs_denom);
 
     MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
                       &proc_to_abs_num,  &proc_to_abs_denom);
@@ -1740,58 +2356,113 @@ void getdivisor()
 void read_command_map()
 {
     size_t size;
 void read_command_map()
 {
     size_t size;
+    int i;
+    int prev_total_threads;
     int mib[6];
   
     if (mapptr) {
        free(mapptr);
        mapptr = 0;
     }
     int mib[6];
   
     if (mapptr) {
        free(mapptr);
        mapptr = 0;
     }
+
+    prev_total_threads = total_threads;
     total_threads = bufinfo.nkdthreads;
     size = bufinfo.nkdthreads * sizeof(kd_threadmap);
 
     if (size)
     {
     total_threads = bufinfo.nkdthreads;
     size = bufinfo.nkdthreads * sizeof(kd_threadmap);
 
     if (size)
     {
-        if (mapptr = (kd_threadmap *) malloc(size))
-            bzero (mapptr, size);
-       else
+        if ((mapptr = (kd_threadmap *) malloc(size)))
        {
        {
-           printf("Thread map is not initialized -- this is not fatal\n");
-           return;
+            bzero (mapptr, size);
+            /* Now read the threadmap */
+            mib[0] = CTL_KERN;
+            mib[1] = KERN_KDEBUG;
+            mib[2] = KERN_KDTHRMAP;
+            mib[3] = 0;
+            mib[4] = 0;
+            mib[5] = 0;                /* no flags */
+            if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
+            {
+                /* This is not fatal -- just means I cant map command strings */
+                free(mapptr);
+                mapptr = 0;
+            }
        }
     }
        }
     }
-    /* Now read the threadmap */
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_KDEBUG;
-    mib[2] = KERN_KDTHRMAP;
-    mib[3] = 0;
-    mib[4] = 0;
-    mib[5] = 0;                /* no flags */
-    if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
+
+    if (mapptr && (filter_mode != DEFAULT_DO_NOT_FILTER))
     {
     {
-        /* This is not fatal -- just means I cant map command strings */
+       if (fdmapptr)
+       {
+           /* We accept the fact that we lose file descriptor state if the
+              kd_buffer wraps */
+           for (i = 0; i < prev_total_threads; i++)
+           {
+               if (fdmapptr[i].fd_setptr)
+                   free (fdmapptr[i].fd_setptr);
+           }
+           free(fdmapptr);
+           fdmapptr = 0;
+       }
 
 
-        printf("Can't read the thread map -- this is not fatal\n");
-       free(mapptr);
-       mapptr = 0;
-       return;
+       size = total_threads * sizeof(fd_threadmap);
+       if ((fdmapptr = (fd_threadmap *) malloc(size)))
+       {
+           bzero (fdmapptr, size);
+           /* reinitialize file descriptor state map */
+           for (i = 0; i < total_threads; i++)
+           {
+               fdmapptr[i].fd_thread = mapptr[i].thread;
+               fdmapptr[i].fd_valid = mapptr[i].valid;
+               fdmapptr[i].fd_setsize = 0;
+               fdmapptr[i].fd_setptr = 0;
+           }
+       }
+    }
+
+    /* Resolve any LaunchCFMApp command names */
+    if (mapptr && arguments)
+    {
+       for (i=0; i < total_threads; i++)
+       {
+           int pid;
+
+           pid = mapptr[i].valid;
+           
+           if (pid == 0 || pid == 1)
+               continue;
+           else if (!strncmp(mapptr[i].command,"LaunchCFMA", 10))
+           {
+               (void)get_real_command_name(pid, mapptr[i].command, sizeof(mapptr[i].command));
+           }
+       }
     }
     }
-    return;
 }
 
 
 }
 
 
-void create_map_entry(int thread, char *command)
+void create_map_entry(int thread, int pid, char *command)
 {
     int i, n;
     kd_threadmap *map;
 {
     int i, n;
     kd_threadmap *map;
+    fd_threadmap *fdmap = 0;
 
     if (!mapptr)
         return;
 
     for (i = 0, map = 0; !map && i < total_threads; i++)
     {
 
     if (!mapptr)
         return;
 
     for (i = 0, map = 0; !map && i < total_threads; i++)
     {
-        if (mapptr[i].thread == thread )       
-           map = &mapptr[i];   /* Reuse this entry, the thread has been reassigned */
+        if ((int)mapptr[i].thread == thread )
+       {
+           map = &mapptr[i];   /* Reuse this entry, the thread has been
+                                * reassigned */
+           if(filter_mode && fdmapptr)
+           {
+               fdmap = &fdmapptr[i];
+               if (fdmap->fd_thread != thread)    /* This shouldn't happen */
+                   fdmap = (fd_threadmap *)0;
+           }
+       }
     }
 
     if (!map)   /* look for invalid entries that I can reuse*/
     }
 
     if (!map)   /* look for invalid entries that I can reuse*/
@@ -1800,6 +2471,10 @@ void create_map_entry(int thread, char *command)
        {
            if (mapptr[i].valid == 0 )  
                map = &mapptr[i];   /* Reuse this invalid entry */
        {
            if (mapptr[i].valid == 0 )  
                map = &mapptr[i];   /* Reuse this invalid entry */
+           if (filter_mode && fdmapptr)
+           {
+               fdmap = &fdmapptr[i];
+           }
        }
     }
   
        }
     }
   
@@ -1814,13 +2489,43 @@ void create_map_entry(int thread, char *command)
        mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
        bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
        map = &mapptr[total_threads];
        mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
        bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
        map = &mapptr[total_threads];
+
+       if (filter_mode && fdmapptr)
+       {
+           fdmapptr = (fd_threadmap *)realloc(fdmapptr, n * sizeof(fd_threadmap));
+           bzero(&fdmapptr[total_threads], total_threads*sizeof(fd_threadmap));
+           fdmap = &fdmapptr[total_threads];       
+       }
+       
        total_threads = n;
     }
 
     map->valid = 1;
     map->thread = thread;
        total_threads = n;
     }
 
     map->valid = 1;
     map->thread = thread;
-    (void)strncpy (map->command, command, sizeof(map->command));
-    map->command[sizeof(map->command)-1] = '\0';
+    /*
+      The trace entry that returns the command name will hold
+      at most, MAXCOMLEN chars, and in that case, is not
+      guaranteed to be null terminated.
+    */
+    (void)strncpy (map->command, command, MAXCOMLEN);
+    map->command[MAXCOMLEN] = '\0';
+
+    if (fdmap)
+    {
+       fdmap->fd_valid = 1;
+       fdmap->fd_thread = thread;
+       if (fdmap->fd_setptr)
+       {
+           free(fdmap->fd_setptr);
+           fdmap->fd_setptr = (unsigned long *)0;
+       }
+       fdmap->fd_setsize = 0;
+    }
+
+    if (pid == 0 || pid == 1)
+       return;
+    else if (!strncmp(map->command, "LaunchCFMA", 10))
+       (void)get_real_command_name(pid, map->command, sizeof(map->command));
 }
 
 
 }
 
 
@@ -1835,7 +2540,7 @@ kd_threadmap *find_thread_map(int thread)
     for (i = 0; i < total_threads; i++)
     {
         map = &mapptr[i];
     for (i = 0; i < total_threads; i++)
     {
         map = &mapptr[i];
-       if (map->valid && (map->thread == thread))
+       if (map->valid && ((int)map->thread == thread))
        {
            return(map);
        }
        {
            return(map);
        }
@@ -1843,17 +2548,52 @@ kd_threadmap *find_thread_map(int thread)
     return ((kd_threadmap *)0);
 }
 
     return ((kd_threadmap *)0);
 }
 
+fd_threadmap *find_fd_thread_map(int thread)
+{
+    int i;
+    fd_threadmap *fdmap = 0;
+
+    if (!fdmapptr)
+        return((fd_threadmap *)0);
+
+    for (i = 0; i < total_threads; i++)
+    {
+        fdmap = &fdmapptr[i];
+       if (fdmap->fd_valid && ((int)fdmap->fd_thread == thread))
+       {
+           return(fdmap);
+       }
+    }
+    return ((fd_threadmap *)0);
+}
+
 
 void
 kill_thread_map(int thread)
 {
     kd_threadmap *map;
 
 void
 kill_thread_map(int thread)
 {
     kd_threadmap *map;
+    fd_threadmap *fdmap;
 
 
-    if (map = find_thread_map(thread)) {
+    if ((map = find_thread_map(thread))) {
         map->valid = 0;
        map->thread = 0;
        map->command[0] = '\0';
     }
         map->valid = 0;
        map->thread = 0;
        map->command[0] = '\0';
     }
+
+    if (filter_mode)
+    {
+       if ((fdmap = find_fd_thread_map(thread)))
+       {
+           fdmap->fd_valid = 0;
+           fdmap->fd_thread = 0;
+           if (fdmap->fd_setptr)
+           {
+               free (fdmap->fd_setptr);
+               fdmap->fd_setptr = (unsigned long *)0;
+           }
+           fdmap->fd_setsize = 0;
+       }       
+    }
 }
 
 void
 }
 
 void
@@ -1886,3 +2626,689 @@ argtopid(str)
 }
 
 
 }
 
 
+
+char *lookup_name(unsigned long addr) 
+{       
+        register int i;
+       register int start, last;
+
+
+       if (numFrameworks == 0 || addr < frameworkInfo[0].address || addr > frameworkInfo[numFrameworks].address)
+               return (0);
+
+       start = 0;
+       last  = numFrameworks;
+
+       for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) {
+
+               if (addr >= frameworkInfo[i].address && addr < frameworkInfo[i+1].address)
+                       return(frameworkInfo[i].name);
+
+               if (addr >= frameworkInfo[i].address) {
+                       start = i;
+                       i = start + ((last - i) / 2);
+               } else {
+                       last = i;
+                       i = start + ((i - start) / 2);
+               }
+       }
+       return (0);
+}
+
+
+/*
+ * Comparison routines for sorting
+ */
+static int compareFrameworkAddress(const void  *aa, const void *bb)
+{
+    LibraryInfo *a = (LibraryInfo *)aa;
+    LibraryInfo *b = (LibraryInfo *)bb;
+
+    if (a->address < b->address) return -1;
+    if (a->address == b->address) return 0;
+    return 1;
+}
+
+
+int scanline(char *inputstring,char **argv)
+{
+     int n = 0;
+     char **ap = argv, *p, *val;  
+
+     for (p = inputstring; p != NULL; ) 
+     {
+        while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
+        *ap++ = val;
+        n++; 
+     }
+     *ap = 0;
+     return n;
+}
+
+
+int ReadSegAddrTable()
+{
+    char buf[1024];
+
+    FILE *fd;
+    unsigned long frameworkAddress, frameworkDataAddress, previousFrameworkAddress;
+    char frameworkName[256];
+    char *tokens[64];
+    int  ntokens;
+    char *substring,*ptr;
+    int  founddylib = 0;
+
+
+    bzero(buf, sizeof(buf));
+    bzero(tokens, sizeof(tokens));
+    
+    numFrameworks = 0;
+
+    if ((fd = fopen(seg_addr_table, "r")) == 0)
+    {
+        return 0;
+    }
+    fgets(buf, 1023, fd);
+
+    if (*buf == '#')
+    {
+        founddylib = 0;
+        frameworkName[0] = 0;
+        previousFrameworkAddress = 0;
+
+        while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
+        {
+           /*
+            * Get rid of EOL
+            */
+           buf[strlen(buf)-1] = 0;
+
+           if (strncmp(buf, "# dyld:", 7) == 0) {
+               /*
+                * the next line in the file will contain info about dyld
+                */
+               founddylib = 1;
+               continue;
+           }
+           /*
+            * This is a split library line: parse it into 3 tokens
+            */
+           ntokens = scanline(buf, tokens);
+
+           if (ntokens < 3)
+               continue;
+
+           frameworkAddress     = strtoul(tokens[0], 0, 16);
+           frameworkDataAddress = strtoul(tokens[1], 0, 16);
+
+           if (founddylib) {
+               /*
+                * dyld entry is of a different form from the std split library
+                * it consists of a base address and a size instead of a code
+                * and data base address
+                */
+               frameworkInfo[numFrameworks].address   = frameworkAddress;
+               frameworkInfo[numFrameworks+1].address = frameworkAddress + frameworkDataAddress;
+
+               frameworkInfo[numFrameworks].name   = (char *)"dylib";
+               frameworkInfo[numFrameworks+1].name = (char *)0;
+
+               numFrameworks += 2;
+               founddylib = 0;
+
+               continue;
+           }  
+
+           /*
+            * Make sure that we have 2 addresses and a path
+            */
+           if (!frameworkAddress)
+               continue;
+           if (!frameworkDataAddress)
+               continue;
+           if (*tokens[2] != '/')
+               continue;
+           if (frameworkAddress == previousFrameworkAddress) 
+               continue;
+           previousFrameworkAddress = frameworkAddress;
+
+            /*
+            * Extract lib name from path name
+            */
+           if ((substring = strrchr(tokens[2], '.')))
+           {           
+               /*
+                * There is a ".": name is whatever is between the "/" around the "." 
+                */
+             while ( *substring != '/') {                  /* find "/" before "." */
+                   substring--;
+               }
+               substring++;
+               strcpy(frameworkName, substring);           /* copy path from "/" */
+               substring = frameworkName;
+
+               while ( *substring != '/' && *substring)    /* find "/" after "." and stop string there */
+                   substring++;
+               *substring = 0;
+           }
+           else 
+           {
+               /*
+                * No ".": take segment after last "/"
+                */
+               ptr = tokens[2];
+               substring = ptr;
+
+               while (*ptr) 
+               {
+                   if (*ptr == '/')
+                       substring = ptr + 1;
+                   ptr++;
+               }
+               strcpy(frameworkName, substring);
+           }
+           frameworkInfo[numFrameworks].address   = frameworkAddress;
+           frameworkInfo[numFrameworks+1].address = frameworkDataAddress;
+
+           frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
+           strcpy(frameworkInfo[numFrameworks].name, frameworkName);
+           frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
+
+           numFrameworks += 2;
+        }
+    }
+    frameworkInfo[numFrameworks].address = frameworkInfo[numFrameworks - 1].address + 0x800000;
+    frameworkInfo[numFrameworks].name = (char *)0;
+
+    fclose(fd);
+
+    qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
+
+    return 1;
+}
+
+
+struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, int thread, double curtime)
+{
+    register struct diskio *dio;
+    register kd_threadmap  *map;
+    
+    if ((dio = free_diskios))
+        free_diskios = dio->next;
+    else {
+        if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
+            return (NULL);
+    }
+    dio->prev = NULL;
+    
+    dio->type = type;
+    dio->bp = bp;
+    dio->dev = dev;
+    dio->blkno = blkno;
+    dio->iosize = io_size;
+    dio->issued_time = curtime;
+    dio->issuing_thread = thread;
+    
+    if ((map = find_thread_map(thread)))
+    {
+        strncpy(dio->issuing_command, map->command, MAXCOMLEN);
+       dio->issuing_command[MAXCOMLEN-1] = '\0';
+    }
+    else
+        strcpy(dio->issuing_command, "");
+    
+    dio->next = busy_diskios;
+    if (dio->next)
+        dio->next->prev = dio;
+    busy_diskios = dio;
+
+    return (dio);
+}
+
+
+struct diskio *complete_diskio(int bp, int io_errno, int resid, int thread, double curtime)
+{
+    register struct diskio *dio;
+    
+    for (dio = busy_diskios; dio; dio = dio->next) {
+        if (dio->bp == bp) {
+        
+            if (dio == busy_diskios) {
+                if ((busy_diskios = dio->next))
+                    dio->next->prev = NULL;
+            } else {
+                if (dio->next)
+                    dio->next->prev = dio->prev;
+                dio->prev->next = dio->next;
+            }
+            dio->iosize -= resid;
+            dio->io_errno = io_errno;
+            dio->completed_time = curtime;
+            dio->completion_thread = thread;
+            
+           return (dio);
+        }    
+    }
+    return ((struct diskio *)0);
+}
+
+
+void free_diskio(struct diskio *dio)
+{
+    dio->next = free_diskios;
+    free_diskios = dio;
+}
+
+
+void print_diskio(struct diskio *dio)
+{
+    register char  *p;
+
+    switch (dio->type) {
+
+        case P_RdMeta:
+            p = "  RdMeta";
+            break;
+        case P_WrMeta:
+            p = "  WrMeta";
+            break;
+        case P_RdData:
+            p = "  RdData";
+            break;
+        case P_WrData:
+            p = "  WrData";
+            break;        
+        case P_PgIn:
+            p = "  PgIn";
+            break;
+        case P_PgOut:
+            p = "  PgOut";
+            break;
+        case P_RdMetaAsync:
+            p = "  RdMeta[async]";
+            break;
+        case P_WrMetaAsync:
+            p = "  WrMeta[async]";
+            break;
+        case P_RdDataAsync:
+            p = "  RdData[async]";
+            break;
+        case P_WrDataAsync:
+            p = "  WrData[async]";
+            break;        
+        case P_PgInAsync:
+            p = "  PgIn[async]";
+            break;
+        case P_PgOutAsync:
+            p = "  PgOut[async]";
+            break;
+        default:
+            p = "  ";
+           break;
+    }
+    if (check_filter_mode(NULL, dio->type,0, 0))
+       format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 7, dio->completed_time, dio->issued_time, 1, "", dio);
+}
+
+
+void cache_disk_names()
+{
+    struct stat    st;
+    DIR            *dirp = NULL;
+    struct dirent  *dir;
+    struct diskrec *dnp;
+
+
+    if ((dirp = opendir("/dev")) == NULL)
+        return;
+        
+    while ((dir = readdir(dirp)) != NULL) {
+        char nbuf[MAXPATHLEN];
+        
+        if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
+            continue;
+        sprintf(nbuf, "%s/%s", "/dev", dir->d_name);
+        
+       if (stat(nbuf, &st) < 0)
+            continue;
+
+        if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
+            continue;
+            
+        if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
+            free(dnp);
+            continue;
+        }
+        strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
+        dnp->diskname[dir->d_namlen] = 0;
+        dnp->dev = st.st_rdev;
+        
+        dnp->next = disk_list;
+        disk_list = dnp;
+    }
+    (void) closedir(dirp);
+}
+
+
+char *find_disk_name(int dev)
+{
+    struct diskrec *dnp;
+    
+    if (dev == NFS_DEV)
+        return ("NFS");
+        
+    for (dnp = disk_list; dnp; dnp = dnp->next) {
+        if (dnp->dev == dev)
+            return (dnp->diskname);
+    }
+    return ("NOTFOUND");
+}
+
+void
+fs_usage_fd_set(thread, fd)
+    unsigned int thread;
+    unsigned int fd;
+{
+    int n;
+    fd_threadmap *fdmap;
+
+    if(!(fdmap = find_fd_thread_map(thread)))
+       return;
+
+    /* If the map is not allocated, then now is the time */
+    if (fdmap->fd_setptr == (unsigned long *)0)
+    {
+       fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE));
+       if (fdmap->fd_setptr)
+       {
+           fdmap->fd_setsize = FS_USAGE_FD_SETSIZE;
+           bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
+       }
+       else
+           return;
+    }
+
+    /* If the map is not big enough, then reallocate it */
+    while (fdmap->fd_setsize < fd)
+    {
+       printf("reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
+         thread, fd, fdmap->fd_setsize);
+       n = fdmap->fd_setsize * 2;
+       fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n)));
+       bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize)));
+       fdmap->fd_setsize = n;
+    }
+
+    /* set the bit */
+    fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
+
+    return;
+}
+
+/*
+  Return values:
+  0 : File Descriptor bit is not set
+  1 : File Descriptor bit is set
+*/
+    
+int
+fs_usage_fd_isset(thread, fd)
+    unsigned int thread;
+    unsigned int fd;
+{
+    int ret = 0;
+    fd_threadmap *fdmap;
+
+    if(!(fdmap = find_fd_thread_map(thread)))
+       return(ret);
+
+    if (fdmap->fd_setptr == (unsigned long *)0)
+       return (ret);
+
+    if (fd < fdmap->fd_setsize)
+       ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
+    
+    return (ret);
+}
+    
+void
+fs_usage_fd_clear(thread, fd)
+    unsigned int thread;
+    unsigned int fd;
+{
+    fd_threadmap *map;
+
+    if (!(map = find_fd_thread_map(thread)))
+       return;
+
+    if (map->fd_setptr == (unsigned long *)0)
+       return;
+
+    /* clear the bit */
+    if (fd < map->fd_setsize)
+       map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
+    
+    return;
+}
+
+
+/*
+ * ret = 1 means print the entry
+ * ret = 0 means don't print the entry
+ */
+int
+check_filter_mode(struct th_info * ti, int type, int error, int retval)
+{
+    int ret = 0;
+    int network_fd_isset = 0;
+    unsigned int fd;
+
+    if (filter_mode == DEFAULT_DO_NOT_FILTER)
+       return(1);
+
+    if (ti == (struct th_info *)0)
+    {
+       if(filter_mode & FILESYS_FILTER)
+           ret = 1;
+       else
+           ret = 0;
+       return(ret);
+    }
+       
+
+    switch (type) {
+    case BSC_close:
+       fd = ti->arg1;
+       network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+       if (error == 0)
+       {
+           fs_usage_fd_clear(ti->thread,fd);
+       }
+       
+       if (network_fd_isset)
+       {
+           if (filter_mode & NETWORK_FILTER)
+               ret = 1;
+       }
+       else if (filter_mode & FILESYS_FILTER)
+           ret = 1;
+       break;
+    case BSC_read:
+    case BSC_write:
+       /* we don't care about error in this case */
+       fd = ti->arg1;
+       network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+       if (network_fd_isset)
+       {
+           if (filter_mode & NETWORK_FILTER)
+               ret = 1;
+       }
+       else if (filter_mode & FILESYS_FILTER)
+           ret = 1;    
+       break;
+    case BSC_accept:
+    case BSC_socket:
+       fd = retval;
+       if (error == 0)
+           fs_usage_fd_set(ti->thread, fd);
+       if (filter_mode & NETWORK_FILTER)
+           ret = 1;
+       break;
+    case BSC_recvfrom:
+    case BSC_sendto:
+    case BSC_recvmsg:
+    case BSC_sendmsg:
+    case BSC_connect:
+    case BSC_bind:
+    case BSC_listen:       
+       fd = ti->arg1;
+       if (error == 0)
+           fs_usage_fd_set(ti->thread, fd);
+       if (filter_mode & NETWORK_FILTER)
+           ret = 1;
+       break;
+    case BSC_select:
+    case BSC_socketpair:
+       /* Cannot determine info about file descriptors */
+       if (filter_mode & NETWORK_FILTER)
+           ret = 1;
+       break;
+    case BSC_dup:
+    case BSC_dup2:
+       ret=0;   /* We track these cases for fd state only */
+       fd = ti->arg1;  /* oldd */
+       network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+       if (error == 0 && network_fd_isset)
+       {
+           /* then we are duping a socket descriptor */
+           fd = retval;  /* the new fd */
+           fs_usage_fd_set(ti->thread, fd);
+       }
+       break;
+
+    default:
+       if (filter_mode & FILESYS_FILTER)
+           ret = 1;
+       break;
+    }
+
+    return(ret);
+}
+
+/*
+ * Allocate a buffer that is large enough to hold the maximum arguments
+ * to execve().  This is used when getting the arguments to programs
+ * when we see LaunchCFMApps.  If this fails, it is not fatal, we will
+ * simply not resolve the command name.
+ */
+
+void
+init_arguments_buffer()
+{
+
+    int     mib[2];
+    size_t  size;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_ARGMAX;
+    size = sizeof(argmax);
+    if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
+       return;
+
+#if 1
+    /* Hack to avoid kernel bug. */
+    if (argmax > 8192) {
+       argmax = 8192;
+    }
+#endif
+
+    arguments = (char *)malloc(argmax);
+    
+    return;
+}
+
+
+int
+get_real_command_name(int pid, char *cbuf, int csize)
+{
+    /*
+     *      Get command and arguments.
+     */
+    char  *cp;
+    int             mib[4];
+    char    *command_beg, *command, *command_end;
+
+    if (cbuf == NULL) {
+       return(0);
+    }
+
+    if (arguments)
+       bzero(arguments, argmax);
+    else
+       return(0);
+
+    /*
+     * A sysctl() is made to find out the full path that the command
+     * was called with.
+     */
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROCARGS;
+    mib[2] = pid;
+    mib[3] = 0;
+
+    if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) {
+       return(0);
+    }
+
+    /* Skip the saved exec_path. */
+    for (cp = arguments; cp < &arguments[argmax]; cp++) {
+       if (*cp == '\0') {
+           /* End of exec_path reached. */
+           break;
+       }
+    }
+    if (cp == &arguments[argmax]) {
+       return(0);
+    }
+
+    /* Skip trailing '\0' characters. */
+    for (; cp < &arguments[argmax]; cp++) {
+       if (*cp != '\0') {
+           /* Beginning of first argument reached. */
+           break;
+       }
+    }
+    if (cp == &arguments[argmax]) {
+       return(0);
+    }
+    command_beg = cp;
+
+    /*
+     * Make sure that the command is '\0'-terminated.  This protects
+     * against malicious programs; under normal operation this never
+     * ends up being a problem..
+     */
+    for (; cp < &arguments[argmax]; cp++) {
+       if (*cp == '\0') {
+           /* End of first argument reached. */
+           break;
+       }
+    }
+    if (cp == &arguments[argmax]) {
+       return(0);
+    }
+    command_end = command = cp;
+
+    /* Get the basename of command. */
+    for (command--; command >= command_beg; command--) {
+       if (*command == '/') {
+           command++;
+           break;
+       }
+    }
+
+    (void) strncpy(cbuf, (char *)command, csize);
+    cbuf[csize-1] = '\0';
+
+    return(1);
+}