From 9726c1377126b4aeb5693fd4c32d17dafc8c4d7e Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 4 Sep 2015 17:35:54 +0000 Subject: [PATCH 1/1] system_cmds-670.1.2.tar.gz --- dynamic_pager.tproj/generate_plist.sh | 16 + fs_usage.tproj/fs_usage.c | 53 ++- getty.tproj/com.apple.getty.plist | 4 + getty.tproj/generate_plist.sh | 16 + iostat.tproj/iostat.c | 6 + kpgo.tproj/kpgo.c | 128 ++++++ lskq.tproj/common.h | 125 ++++++ lskq.tproj/lskq.1 | 176 +++++++++ lskq.tproj/lskq.c | 549 ++++++++++++++++++++++++++ lsmp.tproj/entitlements.plist | 2 + lsmp.tproj/port_details.c | 2 +- lsmp.tproj/task_details.c | 7 +- nvram.tproj/nvram.c | 14 +- system_cmds.xcodeproj/project.pbxproj | 333 +++++++++++++++- trace.tproj/trace.1 | 380 ++++++++++++++++-- trace.tproj/trace.c | 198 +++++----- zic.tproj/generate_zoneinfo.sh | 13 +- zic.tproj/install_zoneinfo.sh | 21 +- zprint.tproj/entitlements.plist | 12 + zprint.tproj/zprint.c | 348 +++++++++++++++- 20 files changed, 2216 insertions(+), 187 deletions(-) create mode 100644 dynamic_pager.tproj/generate_plist.sh create mode 100644 getty.tproj/generate_plist.sh create mode 100644 kpgo.tproj/kpgo.c create mode 100644 lskq.tproj/common.h create mode 100644 lskq.tproj/lskq.1 create mode 100644 lskq.tproj/lskq.c create mode 100644 zprint.tproj/entitlements.plist diff --git a/dynamic_pager.tproj/generate_plist.sh b/dynamic_pager.tproj/generate_plist.sh new file mode 100644 index 0000000..288f045 --- /dev/null +++ b/dynamic_pager.tproj/generate_plist.sh @@ -0,0 +1,16 @@ +#!/bin/sh +set -e +set -x + +cp "${SCRIPT_INPUT_FILE_0}" "${SCRIPT_OUTPUT_FILE_0}" +case "$PLATFORM_NAME" in +iphone*|appletv*|watch*) + /usr/libexec/PlistBuddy -c "Add :LaunchOnlyOnce bool true" "${SCRIPT_OUTPUT_FILE_0}" + ;; +macosx) + ;; +*) + echo "Unsupported platform: $PLATFORM_NAME" + exit 1 + ;; +esac diff --git a/fs_usage.tproj/fs_usage.c b/fs_usage.tproj/fs_usage.c index 0590569..83b1fda 100644 --- a/fs_usage.tproj/fs_usage.c +++ b/fs_usage.tproj/fs_usage.c @@ -89,8 +89,9 @@ typedef struct LibraryRange { uint64_t e_address; } LibraryRange; -LibraryRange framework32; -LibraryRange framework64; +LibraryRange framework32 = {0,0}; +LibraryRange framework64 = {0,0}; +LibraryRange framework64h = {0,0}; #define TEXT_R 0 @@ -225,6 +226,7 @@ int need_new_map = 1; int bias_secs = 0; long last_time; int wideflag = 0; +int include_waited_flag = 0; int columns = 0; int one_good_pid = 0; /* Used to fail gracefully when bad pids given */ @@ -720,6 +722,7 @@ int quit(); #define FMT_CHMODAT 44 #define FMT_OPENAT 45 #define FMT_RENAMEAT 46 +#define FMT_IOCTL_SYNCCACHE 47 #define MAX_BSD_SYSCALL 526 @@ -2162,9 +2165,9 @@ main(argc, argv) myname++; } - while ((ch = getopt(argc, argv, "bewf:R:S:E:t:")) != EOF) { + while ((ch = getopt(argc, argv, "bewf:R:S:E:t:W")) != EOF) { - switch(ch) { + switch(ch) { case 'e': exclude_pids = 1; @@ -2177,6 +2180,10 @@ main(argc, argv) columns = MAX_WIDE_MODE_COLS; break; + case 'W': + include_waited_flag = 1; + break; + case 'f': if (!strcmp(optarg, "network")) filter_mode |= NETWORK_FILTER; @@ -2280,6 +2287,7 @@ main(argc, argv) /* set up signal handlers */ signal(SIGINT, leave); signal(SIGQUIT, leave); + signal(SIGPIPE, leave); sigaction(SIGHUP, (struct sigaction *)NULL, &osa); @@ -2302,12 +2310,12 @@ main(argc, argv) if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0) quit("can't allocate memory for tracing info\n"); - if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) { - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64"); - } else { - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc"); - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64"); - } + ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386"); + + if (0 == ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64h.map", &framework64h, "/var/db/dyld/dyld_shared_cache_x86_64h")){ + ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64"); + } + SortFrameworkAddresses(); cache_disk_names(); @@ -2440,7 +2448,9 @@ set_filter(void) setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_EXCP_SC)); //0x010c setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_VM)); //0x0130 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140 + + if (include_waited_flag) + setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_FSRW)); //0x0301 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_DKRW)); //0x0302 @@ -2944,9 +2954,11 @@ sample_sc() case SPEC_ioctl: if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE) - exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_SYNC, (double)now); + exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_SYNCCACHE, (double)now); else if (kd[i].arg2 == DKIOCUNMAP) exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_UNMAP, (double)now); + else if (kd[i].arg2 == DKIOCSYNCHRONIZE && (debugid & DBG_FUNC_ALL) == DBG_FUNC_NONE) + exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, 0, FMT_IOCTL_SYNC, (double)now); else { if ((ti = find_event(thread, type))) delete_event(ti); @@ -3327,6 +3339,10 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uint command_name = ""; + // Filter out WindowServer/xcpm iocts in fs_usage + if (format == FMT_IOCTL && ti->arg2 == 0xc030581d) + return; + if (RAW_flag) { l_usecs = (long long)((now - bias_now) / divisor); @@ -3738,6 +3754,16 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uint } case FMT_IOCTL_SYNC: + { + /* + * ioctl + */ + clen += printf(" B=%d /dev/%s", arg3, find_disk_name(arg1)); + + break; + } + + case FMT_IOCTL_SYNCCACHE: { /* * ioctl @@ -4819,7 +4845,8 @@ lookup_name(uint64_t user_addr, char **type, char **name) if (numFrameworks) { if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) || - (user_addr >= framework64.b_address && user_addr < framework64.e_address)) { + (user_addr >= framework64.b_address && user_addr < framework64.e_address) || + (user_addr >= framework64h.b_address && user_addr < framework64h.e_address)) { start = 0; last = numFrameworks; diff --git a/getty.tproj/com.apple.getty.plist b/getty.tproj/com.apple.getty.plist index d8cb902..45b748f 100644 --- a/getty.tproj/com.apple.getty.plist +++ b/getty.tproj/com.apple.getty.plist @@ -2,6 +2,10 @@ + EnablePressuredExit + + EnableTransactions + KeepAlive Label diff --git a/getty.tproj/generate_plist.sh b/getty.tproj/generate_plist.sh new file mode 100644 index 0000000..2170bc9 --- /dev/null +++ b/getty.tproj/generate_plist.sh @@ -0,0 +1,16 @@ +#!/bin/sh +set -e +set -x + +cp "${SCRIPT_INPUT_FILE_0}" "${SCRIPT_OUTPUT_FILE_0}" +case "$PLATFORM_NAME" in +iphone*|appletv*|watch*) + ;; +macosx) + /usr/libexec/PlistBuddy -c "Add :Disabled bool true" "${SCRIPT_OUTPUT_FILE_0}" + ;; +*) + echo "Unsupported platform: $PLATFORM_NAME" + exit 1 + ;; +esac diff --git a/iostat.tproj/iostat.c b/iostat.tproj/iostat.c index 643df3d..a346053 100644 --- a/iostat.tproj/iostat.c +++ b/iostat.tproj/iostat.c @@ -972,6 +972,12 @@ record_device(io_registry_entry_t drive) else errx(1, "device does not have a preferred block size"); + // radar:18700383 + if (drivestat[num_devices].blocksize == 0) { + warnx("%s claims a blocksize of 0; defaulting to 512. Its statistics may be inaccurate.", drivestat[num_devices].name); + drivestat[num_devices].blocksize = 512; + } + /* clean up, return success */ CFRelease(properties); num_devices++; diff --git a/kpgo.tproj/kpgo.c b/kpgo.tproj/kpgo.c new file mode 100644 index 0000000..0b439cf --- /dev/null +++ b/kpgo.tproj/kpgo.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + fprintf (stderr, "usage: %s [-H] [-m] [-w] [uuid] >datafile\n", argv[0]); + fprintf (stderr, " uuid : the UUID of a kext\n"); + fprintf (stderr, " -H : grab data for the HIB segment\n"); + fprintf (stderr, " -w : wait for the kext to be unloaded\n"); + fprintf (stderr, " -m : request metadata\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int flags = 0; + int data_flags = 0; + uuid_t *uuidp = NULL; + uuid_t uuid; + int c; + + while ((c = getopt(argc, argv, "hHwm")) != EOF) { + switch(c) { + case 'H': + flags |= PGO_HIB; + break; + case 'm': + flags |= PGO_METADATA; + break; + case 'w': + data_flags |= PGO_WAIT_FOR_UNLOAD; + break; + case '?': + case 'h': + default: + usage(argv); + break; + } + } + + if (optind < argc) + { + if (optind == argc - 1 && + 0 == uuid_parse(argv[optind], uuid)) + { + uuidp = &uuid; + } else { + usage(argv); + } + } + + ssize_t size = grab_pgo_data(uuidp, flags, NULL, 0); + + if (size < 0) + { + perror("grab_pgo_data"); + return 1; + } + + + fprintf (stderr, "size = %ld\n", (long) size); + + unsigned char *buffer = valloc(size); + if (!buffer) + { + perror("valloc"); + return 1; + } + + ssize_t r = grab_pgo_data(uuidp, flags | data_flags, buffer, size); + + + if (r < 0) + { + perror("grab_pgo_data"); + return 1; + } + + if (isatty(STDOUT_FILENO)) { + fprintf (stderr, "%s: refusing to write binary data to a tty!\n", argv[0]); + return 1; + } + + while (size > 0) { + errno = 0; + r = write(STDOUT_FILENO, buffer, size); + if (r > 0) { + buffer += r; + size -= r; + } else { + perror ("write"); + return 1; + } + } + + return 0; + +} diff --git a/lskq.tproj/common.h b/lskq.tproj/common.h new file mode 100644 index 0000000..eb694f6 --- /dev/null +++ b/lskq.tproj/common.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _LSKQ_COMMON_H_ +#define _LSKQ_COMMON_H_ + +/* + * This file must be kept in sync with xnu headers + */ + +/* + * bsd/sys/event.h + */ +#define KN_ACTIVE 0x01 +#define KN_QUEUED 0x02 +#define KN_DISABLED 0x04 +#define KN_STAYQUEUED 0x40 + + +/* + * bsd/sys/eventvar.h + */ +#define KQ_SEL 0x01 +#define KQ_SLEEP 0x02 +#define KQ_KEV32 0x08 +#define KQ_KEV64 0x10 +#define KQ_KEV_QOS 0x20 + +/* + * bsd/sys/signal.h + */ +static const char * +sig_strs[] = { + [0] = "", + [1] = "SIGHUP", + [2] = "SIGINT", + [3] = "SIGQUIT", + [4] = "SIGILL", + [5] = "SIGTRAP", + [6] = "SIGABRT", + [7] = "SIGEMT", + [8] = "SIGFPE", + [9] = "SIGKILL", + [10] = "SIGBUS", + [11] = "SIGSEGV", + [12] = "SIGSYS", + [13] = "SIGPIPE", + [14] = "SIGALRM", + [15] = "SIGTERM", + [16] = "SIGURG", + [17] = "SIGSTOP", + [18] = "SIGTSTP", + [19] = "SIGCONT", + [20] = "SIGCHLD", + [21] = "SIGTTIN", + [22] = "SIGTTOU", + [23] = "SIGIO", + [24] = "SIGXCPU", + [25] = "SIGXFSZ", + [26] = "SIGVTALRM", + [27] = "SIGPROF", + [28] = "SIGWINCH", + [29] = "SIGINFO", + [30] = "SIGUSR1", + [31] = "SIGUSR2" +}; + +/* + * bsd/sys/event.h: EVFILT_* + */ +static const char * +filt_strs[] = { + NULL, + "READ", + "WRITE", + "AIO", + "VNODE", + "PROC", + "SIGNAL", + "TIMER", + "MACHPORT", + "FS", + "USER", + "", + "VM", + "SOCK", + "MEMSTATUS", +}; + +/* + * bsd/sys/proc_info.h: PROX_FDTYPE_* + */ +static const char * +fdtype_strs[] = { + "ATALK", + "VNODE", + "SOCKET", + "PSHM", + "PSEM", + "KQUEUE", + "PIPE", + "FSEVENTS", +}; + +#endif /* _LSKQ_COMMON_H_ */ diff --git a/lskq.tproj/lskq.1 b/lskq.tproj/lskq.1 new file mode 100644 index 0000000..3660a3a --- /dev/null +++ b/lskq.tproj/lskq.1 @@ -0,0 +1,176 @@ +.\" Copyright (c) 2015, Apple Inc. All rights reserved. +.\" +.Dd Apr 20, 2015 +.Dt lskq 1 +.Os "Mac OS X" +.Sh NAME +.Nm lskq +.Nd display process kqueue state +.Sh SYNOPSIS +.Nm lskq +.Op Fl vhe +.Op Fl p Ar | Fl a +.Sh DESCRIPTION +The +.Nm lskq +command enumerates kqueues and registered kevents of running processes. +.Sh OPTIONS +.Pp +.Bl -tag -width xxx +.It Fl p Ar +Show kqueues of process +.Ar . +.It Fl a +Show kqueues for all running processes. Requires root. +.It Fl v +Verbose: show opaque user data and filter-specific extension fields. +.It Fl e +Ignore empty kqueues. +.It Fl h +Show help and exit. +.El +.Sh OUTPUT +.Nm lskq +prints one line of output for each registered kevent, consisting of process, +kqueue, and kevent information. For kqueues with no registered kevents, a single +line is output with an ident of `-'. See +.Xr kevent 2 +for field semantics. The output columns are: +.Bl -tag -width xxxxxxxxxxxx +.It command +shortened process name. +.It pid +process identifier. +.It kq +file descriptor corresponding to kqueue, or ``wq'' for the special workq kqueue. +.It kqst +kqueue status bitmask. +.Bl -tag -width xxxxxxx -compact +.It Sy k +kqueue is in a +.Fn kevent* +wait set (KQ_SLEEP). +.It Sy s +kqueue is in a +.Fn select +wait set (KQ_SEL). +.It Sy 3 6 q +Type of kevents on this kqueue: KEV32, KEV64, or KEV_QOS. +.El +.It ident +kevent identifier. The meaning depends on the kevent filter specified. Where +possible, +.Nm lskq +prints both numeric and symbolic names. +.It filter +kevent filter type (EVFILT_*). +.It fdtype +file descriptor type, for filters operating on file descriptors. +.It fflags +kevent filter flags bitmask. The meaning of each field depends on the filter type. +.Bl -tag -width xxxxxxx -compact +.Pp +.It EVFILT_READ: +.It Sy l +NOTE_LOWAT +.Pp +.It EVFILT_MACHPORT: +.It Sy r +MACH_RCV_MSG +.Pp +.It EVFILT_VNODE: +.It Sy d +NOTE_DELETE +.It Sy w +NOTE_WRITE +.It Sy e +NOTE_EXTEND +.It Sy a +NOTE_ATTRIB +.It Sy l +NOTE_LINK +.It Sy r +NOTE_RENAME +.It Sy v +NOTE_REVOKE +.Pp +.It EVFILT_PROC: +.It Sy x +NOTE_EXIT +.It Sy t +NOTE_EXITSTATUS +.It Sy f +NOTE_FORK +.It Sy e +NOTE_EXEC +.It Sy s +NOTE_SIGNAL +.It Sy r +NOTE_REAP +.Pp +.It EVFILT_TIMER: +.It Sy s u n +NOTE_SECONDS, NOTE_USECONDS, NOTE_NSECONDS +.It Sy a +NOTE_ABSOLUTE +.It Sy c +NOTE_CRITICAL +.It Sy b +NOTE_BACKGROUND +.It Sy l +NOTE_LEEWAY +.El +.It flags +kevent generic flags bitmask. +.Bl -tag -width xxxxxxx -compact +.It Sy a +EV_ADD +.It Sy n +EV_ENABLE +.It Sy d +EV_DISABLE +.It Sy x +EV_DELETE +.It Sy r +EV_RECEIPT +.It Sy 1 +EV_ONESHOT +.It Sy c +EV_CLEAR +.It Sy o +EV_EOF +.It Sy e +EV_ERROR +.El +.It evst +kevent status bitmask. +.Bl -tag -width xxxxxxx -compact +.It Sy a +Event has triggered (KN_ACTIVE). +.It Sy q +Event has been added to the active list (KN_QUEUED). +.It Sy d +Event is disabled (KN_DISABLED). +.It Sy s +Event is marked as always-enqueued on the active list (KN_STAYQUEUED). +.El +.It data +Filter-specific data. +.El +.Pp +If the +.Fl v +(verbose) option is specified, the opaque user-data field and further +filter-specific extension fields are printed in raw hexadecimal. +.Sh NOTES +The output of +.Nm lskq +is not an atomic snapshot of system state. In cases where +.Nm lskq +is able to detect an inconsistency, a warning will be printed. +.Sh SEE ALSO +.Xr kqueue 2 , +.Xr kevent 2 , +.Xr ddt 1 , +.Xr lsof 8 , +.Xr lsmp 1 diff --git a/lskq.tproj/lskq.c b/lskq.tproj/lskq.c new file mode 100644 index 0000000..48782d8 --- /dev/null +++ b/lskq.tproj/lskq.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define ARRAYLEN(x) (sizeof((x))/sizeof((x[0]))) + +/* command line options */ +static int verbose; +static int all_pids; +static int ignore_empty; + +static char *self = "lskq"; + +static inline const char * +filt_name(int16_t filt) +{ + int idx = -filt; + if (idx >= 0 && idx < ARRAYLEN(filt_strs)) { + return filt_strs[idx]; + } else { + return ""; + } +} + +static inline const char * +fdtype_str(uint32_t type) +{ + if (type < ARRAYLEN(fdtype_strs)) { + return fdtype_strs[type]; + } else { + return ""; + } +} + +static char * +fflags_build(struct kevent_extinfo *info, char *str, int len) +{ + unsigned ff = info->kqext_sfflags; + + switch (info->kqext_kev.filter) { + + case EVFILT_READ: { + snprintf(str, len, "%c ", + (ff & NOTE_LOWAT) ? 'l' : '-' + ); + break; + } + + case EVFILT_MACHPORT: { + snprintf(str, len, "%c ", + (ff & MACH_RCV_MSG) ? 'r' : '-' + ); + break; + } + + case EVFILT_VNODE: { + snprintf(str, len, "%c%c%c%c%c%c%c", + (ff & NOTE_DELETE) ? 'd' : '-', + (ff & NOTE_WRITE) ? 'w' : '-', + (ff & NOTE_EXTEND) ? 'e' : '-', + (ff & NOTE_ATTRIB) ? 'a' : '-', + (ff & NOTE_LINK) ? 'l' : '-', + (ff & NOTE_RENAME) ? 'r' : '-', + (ff & NOTE_REVOKE) ? 'v' : '-' + ); + break; + } + + case EVFILT_PROC: { +/* NOTE_REAP is deprecated, but we still want to show if it's used */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + snprintf(str, len, "%c%c%c%c%c%c ", + (ff & NOTE_EXIT) ? 'x' : '-', + (ff & NOTE_EXITSTATUS) ? 't' : '-', + (ff & NOTE_FORK) ? 'f' : '-', + (ff & NOTE_EXEC) ? 'e' : '-', + (ff & NOTE_SIGNAL) ? 's' : '-', + (ff & NOTE_REAP) ? 'r' : '-' + ); + break; +#pragma clang diagnostic pop + } + + case EVFILT_TIMER: { + snprintf(str, len, "%c%c%c%c%c ", + (ff & NOTE_SECONDS) ? 's' : + (ff & NOTE_USECONDS) ? 'u' : + (ff & NOTE_NSECONDS) ? 'n' : '?', + (ff & NOTE_ABSOLUTE) ? 'a' : '-', + (ff & NOTE_CRITICAL) ? 'c' : '-', + (ff & NOTE_BACKGROUND) ? 'b' : '-', + (ff & NOTE_LEEWAY) ? 'l' : '-' + ); + break; + } + + default: + snprintf(str, len, ""); + break; + }; + + return str; +} + + +static inline int +filter_is_fd_type(int filter) +{ + if (filter <= EVFILT_READ && filter >= EVFILT_VNODE) { + return 1; + } else { + return 0; + } +} + +/* + * find index of fd in a list of fdinfo of length nfds + */ +static inline int +fd_list_getfd(struct proc_fdinfo *fds, int nfds, int fd) +{ + int i; + for (i = 0; i < nfds; i++) { + if (fds[i].proc_fd == fd) { + return i; + } + } + + return -1; +} + +/* + * left truncate URL-form process names + */ +static const char * +shorten_procname(const char *proc, int width) +{ + if (strcasestr(proc, "com.") == proc) { + long len = strlen(proc); + if (len > width) { + return &proc[len - width]; + } else { + return proc; + } + } else { + return proc; + } +} + +/* + * stringify knote ident where possible (signals, processes) + */ +static void +print_ident(uint64_t ident, int16_t filter, int width) +{ + switch (filter) { + + case EVFILT_SIGNAL: + case EVFILT_PROC: { + char str[128] = ""; + char num[128]; + char out[128]; + int numlen = sprintf(num, "%llu", ident); + int strwidth = width - numlen - 3; // add room for brackets and space + + if (filter == EVFILT_SIGNAL) { + if (ident < ARRAYLEN(sig_strs)) { + snprintf(str, strwidth + 1, "%s", sig_strs[ident]); + } + } else { + /* FIXME: this should be cached */ + struct proc_bsdinfo bsdinfo; + int ret = proc_pidinfo((int)ident, PROC_PIDTBSDINFO, 0, &bsdinfo, sizeof(bsdinfo)); + if (ret == sizeof(bsdinfo)) { + char *procname = bsdinfo.pbi_name; + if (strlen(procname) == 0) { + procname = bsdinfo.pbi_comm; + } + snprintf(str, strwidth + 1, "%s", + shorten_procname(procname, strwidth)); + } + } + + if (str[0] != '\0') { + snprintf(out, width + 1, "(%s) %s", str, num); + } else { + snprintf(out, width + 1, "%s", num); + } + + printf("%*s ", width, out); + break; + } + + default: + printf("%*llu ", width, ident); + break; + } + +} + +static void +print_kqfd(int kqfd, int width) +{ + if (kqfd == -1) { + printf("%*s ", width, "wq"); + } else { + printf("%*u ", width, kqfd); + } +} + +static void +print_kq_info(int pid, const char *procname, int kqfd, int state) +{ + char tmpstr[16]; + strlcpy(tmpstr, shorten_procname(procname, 10), 11); + printf("%-10s ", tmpstr); + printf("%5u ", pid); + print_kqfd(kqfd, 5); + printf(" %c%c%c ", + (state & KQ_SLEEP) ? 'k' : '-', + (state & KQ_SEL) ? 's' : '-', + (state & KQ_KEV32) ? '3' : + (state & KQ_KEV64) ? '6' : + (state & KQ_KEV_QOS) ? 'q' : '-' + ); +} + +#define MAXENTRIES 2048 + +static int +process_kqueue_on_fd(int pid, const char *procname, int kqfd, struct proc_fdinfo *fdlist, int nfds) +{ + int ret, i, nknotes; + char tmpstr[256]; + + /* + * get the basic kqueue info + */ + struct kqueue_fdinfo kqfdinfo = {}; + ret = proc_pidfdinfo(pid, kqfd, PROC_PIDFDKQUEUEINFO, &kqfdinfo, sizeof(kqfdinfo)); + if (ret != sizeof(kqfdinfo) && kqfd != -1) { + /* every proc has an implicit workq kqueue, dont warn if its unused */ + fprintf(stderr, "WARN: FD table changed (pid %i, kq %i)\n", pid, kqfd); + } + + /* + * get extended kqueue info + */ + struct kevent_extinfo kqextinfo[MAXENTRIES]; + again: + errno = 0; + nknotes = proc_pidfdinfo(pid, kqfd, PROC_PIDFDKQUEUE_EXTINFO, kqextinfo, sizeof(kqextinfo)); + if (nknotes <= 0) { + if (errno == 0) { + /* proc_*() can't distinguish between error and empty list */ + } else if (errno == EAGAIN) { + goto again; + } else if (errno == EBADF) { + fprintf(stderr, "WARN: FD table changed (pid %i, kq %i)\n", pid, kqfd); + return 0; + } else { + perror("failed to get extended kqueue info"); + return errno; + } + } + + if (nknotes > MAXENTRIES) { + fprintf(stderr, "WARN: truncated knote list (pid %i, kq %i)\n", pid, kqfd); + nknotes = MAXENTRIES; + } + + if (nknotes == 0) { + if (!ignore_empty) { + /* for empty kqueues, print a single empty entry */ + print_kq_info(pid, procname, kqfd, kqfdinfo.kqueueinfo.kq_state); + printf("%20s \n", "-"); + } + return 0; + } + + for (i = 0; i < nknotes; i++) { + struct kevent_extinfo *info = &kqextinfo[i]; + + print_kq_info(pid, procname, kqfd, kqfdinfo.kqueueinfo.kq_state); + print_ident(info->kqext_kev.ident, info->kqext_kev.filter, 20); + printf("%-9s ", filt_name(info->kqext_kev.filter)); + + /* for kevents attached to file descriptors, print the type of FD (file, socket, etc) */ + const char *fdstr = ""; + if (filter_is_fd_type(info->kqext_kev.filter)) { + fdstr = ""; + int knfd = (info->kqext_kev.ident < nfds) + ? fd_list_getfd(fdlist, nfds, (int)info->kqext_kev.ident) + : -1; + if (knfd >= 0) { + fdstr = fdtype_str(fdlist[knfd].proc_fdtype); + } + } + printf("%-8s ", fdstr); + + /* print filter flags */ + printf("%7s ", fflags_build(info, tmpstr, sizeof(tmpstr))); + + /* print generic flags */ + unsigned flg = info->kqext_kev.flags; + printf("%c%c%c%c%c%c%c%c%c ", + (flg & EV_ADD) ? 'a' : '-', + (flg & EV_ENABLE) ? 'n' : '-', + (flg & EV_DISABLE) ? 'd' : '-', + (flg & EV_DELETE) ? 'x' : '-', + (flg & EV_RECEIPT) ? 'r' : '-', + (flg & EV_ONESHOT) ? '1' : '-', + (flg & EV_CLEAR) ? 'c' : '-', + (flg & EV_EOF) ? 'o' : '-', + (flg & EV_ERROR) ? 'e' : '-' + ); + + unsigned st = info->kqext_status; + printf("%c%c%c%c ", + (st & KN_ACTIVE) ? 'a' : '-', + (st & KN_QUEUED) ? 'q' : '-', + (st & KN_DISABLED) ? 'd' : '-', + (st & KN_STAYQUEUED) ? 's' : '-' + ); + + printf("%#18llx ", (unsigned long long)info->kqext_kev.data); + + if (verbose) { + printf("%#18llx ", (unsigned long long)info->kqext_kev.udata); + if (kqfdinfo.kqueueinfo.kq_state & (KQ_KEV64|KQ_KEV_QOS)) { + printf("%#18llx ", (unsigned long long)info->kqext_kev.ext[0]); + printf("%#18llx ", (unsigned long long)info->kqext_kev.ext[1]); + } + if (kqfdinfo.kqueueinfo.kq_state & KQ_KEV_QOS) { + printf("%#18llx ", (unsigned long long)info->kqext_kev.ext[2]); + printf("%#18llx ", (unsigned long long)info->kqext_kev.ext[3]); + printf("%#10lx ", (unsigned long)info->kqext_kev.xflags); + } + } + + printf("\n"); + } + + return 0; +} + +static int +process_pid(pid_t pid) +{ + int i, ret, nfds; + + /* enumerate file descriptors */ + struct proc_fdinfo fdlist[MAXENTRIES]; + nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdlist, sizeof(fdlist)); + if (nfds <= 0) { + fprintf(stderr, "%s: failed enumerating file descriptors of process %i: %s", + self, pid, strerror(errno)); + if (errno == EPERM && geteuid() != 0) { + fprintf(stderr, " (are you root?)"); + } + fprintf(stderr, "\n"); + return 1; + } + + nfds /= sizeof(struct proc_fdinfo); + if (nfds > MAXENTRIES) { + fprintf(stderr, "WARN: truncated FD list (proc %i)\n", pid); + nfds = MAXENTRIES; + } + + /* get bsdinfo for the process name */ + struct proc_bsdinfo bsdinfo; + ret = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &bsdinfo, sizeof(bsdinfo)); + if (ret != sizeof(bsdinfo)) { + perror("failed retrieving process info"); + return 1; + } + + char *procname = bsdinfo.pbi_name; + if (strlen(procname) == 0) { + procname = bsdinfo.pbi_comm; + } + + /* handle the special workq kq */ + ret = process_kqueue_on_fd(pid, procname, -1, fdlist, nfds); + if (ret) { + return ret; + } + + for (i = 0; i < nfds; i++) { + if (fdlist[i].proc_fdtype == PROX_FDTYPE_KQUEUE) { + ret = process_kqueue_on_fd(pid, procname, fdlist[i].proc_fd, fdlist, nfds); + if (ret) { + return ret; + } + } + } + + return 0; +} + +#define MAXPIDS 4096 + +static int +process_all_pids(void) +{ + int i, npids, ret; + int pids[MAXPIDS]; + + npids = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids)); + if (npids <= 0) { + perror("failed enumerating pids"); + return 1; + } + npids /= sizeof(int); + + for (i = 0; i < npids; i++) { + /* listpids gives us pid 0 for some reason */ + if (pids[i]) { + ret = process_pid(pids[i]); + if (ret) { + return ret; + } + } + } + + return 0; +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-vhe] [-a | -p ]\n", self); +} + +int main(int argc, char *argv[]) +{ + pid_t pid = 0; + int opt; + + if (argc > 0) { + self = argv[0]; + } + + while ((opt = getopt(argc, argv, "eahvp:")) != -1) { + switch (opt) { + case 'a': + all_pids = 1; + break; + case 'v': + verbose++; + break; + case 'p': + pid = atoi(optarg); + break; + case 'e': + ignore_empty = 1; + break; + case 'h': + usage(); + return 0; + case '?': + default: + usage(); + return 1; + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) { + /* also allow lskq */ + if (pid || all_pids) { + usage(); + return 1; + } + + pid = atoi(argv[0]); + } else if (argc > 1) { + usage(); + return 1; + } + + /* exactly one of -p or -a is required */ + if (!pid && !all_pids) { + usage(); + return 1; + } else if (pid && all_pids) { + usage(); + return 1; + } + + printf("command pid kq kqst ident filter fdtype fflags flags evst data"); + if (verbose) { + printf(" udata ext0 ext1 ext2 ext3 xflags"); + } + printf("\n"); + printf("---------- ----- ----- ---- -------------------- --------- -------- ------- --------- ---- ------------------"); + if (verbose) { + printf(" ------------------ ------------------ ------------------ ------------------ ------------------ ----------"); + } + printf("\n"); + + if (all_pids) { + return process_all_pids(); + } else { + return process_pid(pid); + } + + return 0; +} + diff --git a/lsmp.tproj/entitlements.plist b/lsmp.tproj/entitlements.plist index b21dbd8..b7b4e6c 100644 --- a/lsmp.tproj/entitlements.plist +++ b/lsmp.tproj/entitlements.plist @@ -4,5 +4,7 @@ task_for_pid-allow + com.apple.system-task-ports + diff --git a/lsmp.tproj/port_details.c b/lsmp.tproj/port_details.c index 481c961..438e604 100644 --- a/lsmp.tproj/port_details.c +++ b/lsmp.tproj/port_details.c @@ -309,7 +309,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p /* show other rights (in this and other tasks) for the port */ for (j = 0; j < taskCount; j++) { - for (k = 0; k < allTaskInfos->tableCount; k++) { + for (k = 0; k < allTaskInfos[j].tableCount; k++) { if (allTaskInfos[j].valid == FALSE || &allTaskInfos[j].table[k] == &taskinfo->table[i] || allTaskInfos[j].table[k].iin_object != taskinfo->table[i].iin_object) diff --git a/lsmp.tproj/task_details.c b/lsmp.tproj/task_details.c index 2538799..6fb8dee 100644 --- a/lsmp.tproj/task_details.c +++ b/lsmp.tproj/task_details.c @@ -209,7 +209,7 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) for (int i = 0; i < threadcount; i++) { if (header_required) { - printf("Threads Thread-ID DispatchQ Port Description."); + printf("Threads Thread-ID Port Description."); header_required = FALSE; } @@ -223,10 +223,10 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) mach_msg_type_number_t th_info_count = THREAD_IDENTIFIER_INFO_COUNT; printf("0x%08x ", th_kobject); if (KERN_SUCCESS == thread_info(threadlist[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&th_info, &th_info_count)) { - printf("%16llu 0x%016llx ", th_info.thread_id, th_info.dispatch_qaddr); + printf("0x%llx ", th_info.thread_id); } else - printf(" "); + printf(" "); } @@ -238,6 +238,7 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) } mach_port_deallocate(mach_task_self(), threadlist[i]); } + printf("\n"); return kret; } diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index 0d82b45..fc6a24a 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -26,6 +26,7 @@ cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ static void NVRamSyncNow(char *name); static char *gToolName; static io_registry_entry_t gOptionsRef; static bool gUseXML; +static bool gUseForceSync; int main(int argc, char **argv) @@ -112,7 +114,11 @@ int main(int argc, char **argv) case 'c': ClearOFVariables(); break; - + case 's': + // -s option is unadvertised -- advises the kernel more forcibly to + // commit the variable to nonvolatile storage + gUseForceSync = true; + break; default: strcpy(errorMessage, "no such option as --"); errorMessage[strlen(errorMessage)-1] = *str; @@ -500,7 +506,11 @@ static void DeleteOFVariable(char *name) static void NVRamSyncNow(char *name) { - SetOFVariable(kIONVRAMSyncNowPropertyKey, name); + if (!gUseForceSync) { + SetOFVariable(kIONVRAMSyncNowPropertyKey, name); + } else { + SetOFVariable(kIONVRAMForceSyncNowPropertyKey, name); + } } // PrintOFVariables() diff --git a/system_cmds.xcodeproj/project.pbxproj b/system_cmds.xcodeproj/project.pbxproj index 33f8f10..f545174 100644 --- a/system_cmds.xcodeproj/project.pbxproj +++ b/system_cmds.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ buildPhases = ( ); dependencies = ( + 97999D351AE84D3A00E8B10F /* PBXTargetDependency */, + 08DC48921A12C6FA008AAF38 /* PBXTargetDependency */, 18597F1A18CBC3B000531A50 /* PBXTargetDependency */, 1865518B18CA7151003B92A7 /* PBXTargetDependency */, 550C19F11804D2B7001DA380 /* PBXTargetDependency */, @@ -167,6 +169,8 @@ buildPhases = ( ); dependencies = ( + 97999D371AE84D4100E8B10F /* PBXTargetDependency */, + 08DC48901A12C6F0008AAF38 /* PBXTargetDependency */, 18597F1C18CBC3B900531A50 /* PBXTargetDependency */, 186551D018CA8154003B92A7 /* PBXTargetDependency */, 550C19EF1804D2AD001DA380 /* PBXTargetDependency */, @@ -245,6 +249,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 08DC488E1A12C2D6008AAF38 /* kpgo.c in Sources */ = {isa = PBXBuildFile; fileRef = 08DC488D1A12C2C6008AAF38 /* kpgo.c */; }; 1523FE6C1595056C00661E82 /* ltop.c in Sources */ = {isa = PBXBuildFile; fileRef = 1523FE6B1595056C00661E82 /* ltop.c */; }; 1523FE6D1595058100661E82 /* ltop.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1523FE6A1595056C00661E82 /* ltop.1 */; }; 1845E41618EB95810010F451 /* TraceFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1845E41418EB95810010F451 /* TraceFile.cpp */; }; @@ -351,6 +356,11 @@ 55CCB17616B84F3600B56979 /* vm_purgeable_stat.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 55CCB16816B84ED100B56979 /* vm_purgeable_stat.1 */; }; 72D1FDD918C4140600C1E05F /* task_details.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D1FDD818C4140600C1E05F /* task_details.c */; }; 72F9316D18C26A8600D804C5 /* port_details.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F9316C18C26A8600D804C5 /* port_details.c */; }; + 97999D321AE84CE400E8B10F /* lskq.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 97999D301AE84C7600E8B10F /* lskq.1 */; }; + 97999D331AE84D0A00E8B10F /* lskq.c in Sources */ = {isa = PBXBuildFile; fileRef = 97999D311AE84C7600E8B10F /* lskq.c */; }; + A624DA861AF6F3CF00F56A5C /* CoreSymbolication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A624DA851AF6F3CF00F56A5C /* CoreSymbolication.framework */; }; + A6738D031AF6FF9F001EF064 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6738D021AF6FF9F001EF064 /* IOKit.framework */; }; + A6738D051AF6FFB5001EF064 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6738D041AF6FFB5001EF064 /* CoreFoundation.framework */; }; ADA9007B1767A02D00161ADF /* purge.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = ADA900791767A02700161ADF /* purge.8 */; }; ADA9007C1767A03200161ADF /* purge.c in Sources */ = {isa = PBXBuildFile; fileRef = ADA9007A1767A02700161ADF /* purge.c */; }; B158E3A3185A836700474677 /* wordexp-helper.c in Sources */ = {isa = PBXBuildFile; fileRef = B158E3A2185A836700474677 /* wordexp-helper.c */; }; @@ -535,6 +545,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 08DC488F1A12C6F0008AAF38 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 08DC48841A12C21B008AAF38; + remoteInfo = kpgo; + }; + 08DC48911A12C6FA008AAF38 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 08DC48841A12C21B008AAF38; + remoteInfo = kpgo; + }; 1523FE6E1595069900661E82 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -640,6 +664,20 @@ remoteGlobalIDString = 55CCB16A16B84EDA00B56979; remoteInfo = vm_purgeable_stat; }; + 97999D341AE84D3A00E8B10F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97999D211AE84C0E00E8B10F; + remoteInfo = lskq; + }; + 97999D361AE84D4100E8B10F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97999D211AE84C0E00E8B10F; + remoteInfo = lskq; + }; ADA9007D1767A31300161ADF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -1357,6 +1395,15 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 08DC48831A12C21B008AAF38 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 1523FE5F1595048900661E82 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1407,6 +1454,16 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 97999D281AE84C0E00E8B10F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + 97999D321AE84CE400E8B10F /* lskq.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; ADA9007317679A8C00161ADF /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1925,6 +1982,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 08DC48851A12C21B008AAF38 /* kpgo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = kpgo; sourceTree = BUILT_PRODUCTS_DIR; }; + 08DC488D1A12C2C6008AAF38 /* kpgo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kpgo.c; sourceTree = ""; }; 1523FE631595048900661E82 /* ltop */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ltop; sourceTree = BUILT_PRODUCTS_DIR; }; 1523FE6A1595056C00661E82 /* ltop.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ltop.1; sourceTree = ""; }; 1523FE6B1595056C00661E82 /* ltop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ltop.c; sourceTree = ""; }; @@ -2060,6 +2119,13 @@ 72D1FDD818C4140600C1E05F /* task_details.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = task_details.c; path = lsmp.tproj/task_details.c; sourceTree = SOURCE_ROOT; }; 72F9316B18C269E500D804C5 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = lsmp.tproj/common.h; sourceTree = SOURCE_ROOT; }; 72F9316C18C26A8600D804C5 /* port_details.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = port_details.c; path = lsmp.tproj/port_details.c; sourceTree = SOURCE_ROOT; }; + 97999D2D1AE84C0E00E8B10F /* lskq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lskq; sourceTree = BUILT_PRODUCTS_DIR; }; + 97999D2F1AE84C7600E8B10F /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = common.h; path = lskq.tproj/common.h; sourceTree = ""; }; + 97999D301AE84C7600E8B10F /* lskq.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; name = lskq.1; path = lskq.tproj/lskq.1; sourceTree = ""; }; + 97999D311AE84C7600E8B10F /* lskq.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = lskq.c; path = lskq.tproj/lskq.c; sourceTree = ""; }; + A624DA851AF6F3CF00F56A5C /* CoreSymbolication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSymbolication.framework; path = ../../../../System/Library/PrivateFrameworks/CoreSymbolication.framework; sourceTree = ""; }; + A6738D021AF6FF9F001EF064 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + A6738D041AF6FFB5001EF064 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = ../../../../System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; ADA9007717679A8C00161ADF /* purge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = purge; sourceTree = BUILT_PRODUCTS_DIR; }; ADA900791767A02700161ADF /* purge.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = purge.8; sourceTree = ""; }; ADA9007A1767A02700161ADF /* purge.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = purge.c; sourceTree = ""; }; @@ -2308,9 +2374,17 @@ C96F50AC15BDCBF0008682F7 /* lsmp.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = lsmp.1; path = lsmp.tproj/lsmp.1; sourceTree = SOURCE_ROOT; }; C96F50AD15BDCE8E008682F7 /* lsmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lsmp.c; path = lsmp.tproj/lsmp.c; sourceTree = SOURCE_ROOT; }; C96F50B715BDCEC3008682F7 /* lsmp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lsmp; sourceTree = BUILT_PRODUCTS_DIR; }; + FEBEE5CF1B0EACEB00166A8B /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 08DC48821A12C21B008AAF38 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 1523FE5D1595048900661E82 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2367,6 +2441,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 97999D261AE84C0E00E8B10F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; ADA9007217679A8C00161ADF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2393,7 +2474,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A6738D051AF6FFB5001EF064 /* CoreFoundation.framework in Frameworks */, BA0A860B13968E8500D2272C /* libutil.dylib in Frameworks */, + A624DA861AF6F3CF00F56A5C /* CoreSymbolication.framework in Frameworks */, + A6738D031AF6FF9F001EF064 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2710,6 +2794,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 08DC488C1A12C2C5008AAF38 /* kpgo.tproj */ = { + isa = PBXGroup; + children = ( + 08DC488D1A12C2C6008AAF38 /* kpgo.c */, + ); + path = kpgo.tproj; + sourceTree = ""; + }; 1523FE691595056C00661E82 /* ltop.tproj */ = { isa = PBXGroup; children = ( @@ -2883,6 +2975,16 @@ path = vm_purgeable_stat.tproj; sourceTree = ""; }; + 97999D2E1AE84C5700E8B10F /* lskq.tproj */ = { + isa = PBXGroup; + children = ( + 97999D2F1AE84C7600E8B10F /* common.h */, + 97999D301AE84C7600E8B10F /* lskq.1 */, + 97999D311AE84C7600E8B10F /* lskq.c */, + ); + name = lskq.tproj; + sourceTree = ""; + }; ADA900781767A02700161ADF /* purge.tproj */ = { isa = PBXGroup; children = ( @@ -2921,6 +3023,10 @@ BA2DE9161372FA9100D1913C = { isa = PBXGroup; children = ( + A6738D041AF6FFB5001EF064 /* CoreFoundation.framework */, + A6738D021AF6FF9F001EF064 /* IOKit.framework */, + A624DA851AF6F3CF00F56A5C /* CoreSymbolication.framework */, + 08DC488C1A12C2C5008AAF38 /* kpgo.tproj */, 186551CD18CA7A1B003B92A7 /* System.framework */, 550C19DF1804C55E001DA380 /* iosim.tproj */, ADA900781767A02700161ADF /* purge.tproj */, @@ -2945,6 +3051,7 @@ BA4FD24F1372FAFA0025925C /* iostat.tproj */, BA4FD2551372FAFA0025925C /* latency.tproj */, BA4FD2591372FAFA0025925C /* login.tproj */, + 97999D2E1AE84C5700E8B10F /* lskq.tproj */, 1523FE691595056C00661E82 /* ltop.tproj */, BA4FD2651372FAFA0025925C /* makekey.tproj */, BA4FD2691372FAFA0025925C /* mean.tproj */, @@ -3485,6 +3592,7 @@ BA4FD2E31372FAFA0025925C /* zprint.tproj */ = { isa = PBXGroup; children = ( + FEBEE5CF1B0EACEB00166A8B /* entitlements.plist */, BA4FD2E51372FAFA0025925C /* zprint.1 */, BA4FD2E61372FAFA0025925C /* zprint.c */, ); @@ -3546,6 +3654,8 @@ 1865517C18CA7104003B92A7 /* msa */, 18597EC418CBC2A300531A50 /* kdprof */, 18C8727F18EA114F00F86DD9 /* libKDBG.a */, + 08DC48851A12C21B008AAF38 /* kpgo */, + 97999D2D1AE84C0E00E8B10F /* lskq */, ); name = Products; sourceTree = ""; @@ -3689,6 +3799,23 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 08DC48841A12C21B008AAF38 /* kpgo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 08DC488B1A12C21C008AAF38 /* Build configuration list for PBXNativeTarget "kpgo" */; + buildPhases = ( + 08DC48811A12C21B008AAF38 /* Sources */, + 08DC48821A12C21B008AAF38 /* Frameworks */, + 08DC48831A12C21B008AAF38 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = kpgo; + productName = kpgo; + productReference = 08DC48851A12C21B008AAF38 /* kpgo */; + productType = "com.apple.product-type.tool"; + }; 1523FE5A1595048900661E82 /* ltop */ = { isa = PBXNativeTarget; buildConfigurationList = 1523FE611595048900661E82 /* Build configuration list for PBXNativeTarget "ltop" */; @@ -3813,6 +3940,23 @@ productReference = 55CCB17316B84EDA00B56979 /* vm_purgeable_stat */; productType = "com.apple.product-type.tool"; }; + 97999D211AE84C0E00E8B10F /* lskq */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97999D2A1AE84C0E00E8B10F /* Build configuration list for PBXNativeTarget "lskq" */; + buildPhases = ( + 97999D221AE84C0E00E8B10F /* Sources */, + 97999D261AE84C0E00E8B10F /* Frameworks */, + 97999D281AE84C0E00E8B10F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = lskq; + productName = ac; + productReference = 97999D2D1AE84C0E00E8B10F /* lskq */; + productType = "com.apple.product-type.tool"; + }; ADA9006F17679A8C00161ADF /* purge */ = { isa = PBXNativeTarget; buildConfigurationList = ADA9007517679A8C00161ADF /* Build configuration list for PBXNativeTarget "purge" */; @@ -4601,6 +4745,11 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0600; + TargetAttributes = { + 08DC48841A12C21B008AAF38 = { + CreatedOnToolsVersion = 6.3; + }; + }; }; buildConfigurationList = BA2DE91B1372FA9100D1913C /* Build configuration list for PBXProject "system_cmds" */; compatibilityVersion = "Xcode 3.2"; @@ -4639,6 +4788,7 @@ BA4B7A6913765D3E00003422 /* iostat */, BA4B7A7D13765F3C00003422 /* latency */, BA473DA01377B2230005CC19 /* login */, + 97999D211AE84C0E00E8B10F /* lskq */, 1523FE5A1595048900661E82 /* ltop */, BACC1D011377B3E6007728F4 /* makekey */, BACC1D0D1377B481007728F4 /* mean */, @@ -4677,6 +4827,7 @@ 18C8727E18EA114F00F86DD9 /* KDBG */, 1865517B18CA7104003B92A7 /* msa */, 18597EC318CBC2A300531A50 /* kdprof */, + 08DC48841A12C21B008AAF38 /* kpgo */, ); }; /* End PBXProject section */ @@ -4709,7 +4860,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -x\nset -e\n\ncp \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\nif [[ \"${PLATFORM_NAME}\" == \"iphoneos\"* ]]; then\n /usr/libexec/PlistBuddy -c \"Add :LaunchOnlyOnce bool true\" \"${SCRIPT_OUTPUT_FILE_0}\"\nfi\n"; + shellScript = ". ${SRCROOT}/dynamic_pager.tproj/generate_plist.sh"; }; BA4B7A221373C01600003422 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -4748,7 +4899,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -x\nset -e\n\ncp \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\nif [[ \"${PLATFORM_NAME}\" != \"iphoneos\"* ]]; then\n /usr/libexec/PlistBuddy -c \"Add :Disabled bool true\" \"${SCRIPT_OUTPUT_FILE_0}\"\nfi\n"; + shellScript = ". ${SRCROOT}/getty.tproj/generate_plist.sh"; }; BA4FD335137306050025925C /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -4994,6 +5145,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 08DC48811A12C21B008AAF38 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 08DC488E1A12C2D6008AAF38 /* kpgo.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 1523FE5B1595048900661E82 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -5081,6 +5240,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 97999D221AE84C0E00E8B10F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97999D331AE84D0A00E8B10F /* lskq.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; ADA9007017679A8C00161ADF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -5486,6 +5653,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 08DC48901A12C6F0008AAF38 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 08DC48841A12C21B008AAF38 /* kpgo */; + targetProxy = 08DC488F1A12C6F0008AAF38 /* PBXContainerItemProxy */; + }; + 08DC48921A12C6FA008AAF38 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 08DC48841A12C21B008AAF38 /* kpgo */; + targetProxy = 08DC48911A12C6FA008AAF38 /* PBXContainerItemProxy */; + }; 1523FE6F1595069900661E82 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1523FE5A1595048900661E82 /* ltop */; @@ -5561,6 +5738,16 @@ target = 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */; targetProxy = 55CCB17916B851F300B56979 /* PBXContainerItemProxy */; }; + 97999D351AE84D3A00E8B10F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97999D211AE84C0E00E8B10F /* lskq */; + targetProxy = 97999D341AE84D3A00E8B10F /* PBXContainerItemProxy */; + }; + 97999D371AE84D4100E8B10F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97999D211AE84C0E00E8B10F /* lskq */; + targetProxy = 97999D361AE84D4100E8B10F /* PBXContainerItemProxy */; + }; ADA9007E1767A31300161ADF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = ADA9006F17679A8C00161ADF /* purge */; @@ -6074,6 +6261,86 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 08DC48891A12C21C008AAF38 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Release; + }; + 08DC488A1A12C21C008AAF38 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + ); + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Debug; + }; 1523FE621595048900661E82 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -6093,7 +6360,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6133,7 +6399,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6173,7 +6438,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6722,7 +6986,13 @@ 1873301718CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_ENTITLEMENTS = zprint.tproj/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); HEADER_SEARCH_PATHS = ( + "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders/mach", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); @@ -6734,7 +7004,7 @@ 1873301818CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = lsmp.tproj/entitlements.plist; + "CODE_SIGN_ENTITLEMENTS[sdk=*]" = lsmp.tproj/entitlements.plist; GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ""; INSTALL_PATH = /usr/local/bin; @@ -6799,7 +7069,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6835,7 +7104,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6871,7 +7139,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -6909,7 +7176,6 @@ AXLE_ENABLE_DEBUG_INFO = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -6956,7 +7222,6 @@ AXLE_ENABLE_DEBUG_INFO = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -7014,6 +7279,26 @@ }; name = Release; }; + 97999D2B1AE84C0E00E8B10F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = lskq; + }; + name = Release; + }; + 97999D2C1AE84C0E00E8B10F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders"; + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = lskq; + }; + name = Debug; + }; ADA9007617679A8C00161ADF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7046,7 +7331,13 @@ BA0A860F13968E8500D2272C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_ENTITLEMENTS = zprint.tproj/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); HEADER_SEARCH_PATHS = ( + "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders/mach", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); @@ -7558,7 +7849,7 @@ C96F50B615BDCEC3008682F7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = lsmp.tproj/entitlements.plist; + "CODE_SIGN_ENTITLEMENTS[sdk=*]" = lsmp.tproj/entitlements.plist; GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ""; INSTALL_PATH = /usr/bin; @@ -7569,6 +7860,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 08DC488B1A12C21C008AAF38 /* Build configuration list for PBXNativeTarget "kpgo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 08DC48891A12C21C008AAF38 /* Release */, + 08DC488A1A12C21C008AAF38 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 1523FE611595048900661E82 /* Build configuration list for PBXNativeTarget "ltop" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -7632,6 +7932,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 97999D2A1AE84C0E00E8B10F /* Build configuration list for PBXNativeTarget "lskq" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97999D2B1AE84C0E00E8B10F /* Release */, + 97999D2C1AE84C0E00E8B10F /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; ADA9007517679A8C00161ADF /* Build configuration list for PBXNativeTarget "purge" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/trace.tproj/trace.1 b/trace.tproj/trace.1 index 5c5b3fe..d860ee0 100644 --- a/trace.tproj/trace.1 +++ b/trace.tproj/trace.1 @@ -1,60 +1,364 @@ .\" Copyright (c) 2010, Apple Inc. All rights reserved. .\" -.Dd October 28, 2010 +.Dd April 3, 2015 .Dt TRACE 1 .Os "Mac OS X" .Sh NAME .Nm trace -.Nd configure and record kernel trace events +.Nd configure, record, and display kernel trace events .Sh SYNOPSIS -.Nm trace -.Fl h +.Bl -hang -compact -width "trace -" +.\" +.It Nm Fl d +.Op Fl a Ar pid | Fl x Ar pid +.\" +.It Nm Fl e +.Op Fl c Ar class Oo Fl p Ar end-class Oc Oo Fl s Ar subclass Oc +.Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code +.Op Fl P +.Op Fl T Ar filter-file +.\" +.It Nm Fl E +.Op Fl c Ar class Oo Fl p Ar end-class Oc Oo Fl s Ar subclass Oc +.Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code +.Op Fl P +.Op Fl T Ar tracefilter +.Ar command +.Op Ar argument ... +.\" +.It Nm Fl h +.\" +.It Nm Fl i +.Op Fl b Ar num-events +.\" +.It Nm Fl g +.\" +.It Nm Fl l Ar rawfile +.\" +.It Nm Fl L Ar rawfile +.Op Fl S Ar secs +.\" +.It Nm Fl n +.\" +.It Nm Fl r +.\" +.It Nm Fl R Ar rawfile +.Op Fl X +.Op Fl F Ar frequency +.Op Fl o Ar outfile +.Op Fl N +.Op Ar codesfile ... +.\" +.It Nm Fl t +.Op Fl o Ar outfile +.Op Fl N +.Op Ar codesfile ... +.El +.Sh DESCRIPTION +.Nm +initializes and configures the kernel trace subsystem. Trace events can +be recorded to an in-memory buffer or logged directly to a file, and +optionally converted to a human-readable, plain-text format. .Pp -.Nm trace -.Fl i -.Op Fl b Ar numbufs +.Nm +operates according to the command flag specified. +.Sh COMMANDS +.Bl -tag -width Ds +.It Fl h +Print a succinct help message to +.Xr stdout 4 . +.\" +.\" ## trace -i ## +.It Fl i Op Fl b Ar num-events .Pp -.Nm trace -.Fl g +Initialize the kernel trace buffer. This command is required before +tracing. +.Bl -tag -width Ds +.It Fl b Ar num-events +Set the number of events that can be stored in the kernel trace buffer. +.Ar num-events +is a decimal number of events. The default (and minimum) value is 8192 +event records per logical CPU. No more than half of available +memory may be used by trace buffers, though running with a buffer this +large is not recommended. +.El +.\" +.\" ## trace -g ## +.It Fl g +Print the current kernel trace buffer settings to +.Xr stdout 4 . +.\" +.\" ## trace -d ## +.It Fl d Op Fl a Ar pid | Fl x Ar pid .Pp -.Nm trace -.Fl d +By default, disable collection of events. This command does not remove +the kernel trace buffer. +.Bl -tag -width Ds +.It Fl a Ar pid +Disable event collection for the process identified by +.Ar pid . +.It Fl x Ar pid +Stop excluding +.Ar pid +from the trace. +This reenables event collection of events for. +.Ar pid . +.El +.\" +.\" ## trace -r ## +.It Fl r +Remove the kernel trace buffer. +.\" +.\" ## trace -n ## +.It Fl n +Disable ring buffer mode. When set, the trace buffer will fill to capacity +and then stop collecting events. Ring buffer mode is sometimes called +"head," "stop," or "no-wrap" mode. By default, the trace buffer will +wrap around, overwriting previous events. The default behavior is +sometimes called windowed or wrap-around mode. +.\" +.\" ## trace -e ## +.Bk -words +.It Xo Fl e +.Op Fl c Ar class Oo Fl p Ar end-class Oc Oo Fl s Ar subclass Oc .Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code ... +.Op Fl P +.Op Fl T Ar filter-file +.Ek +.Xc .Pp -.Nm trace -.Fl r +Enable collection of events. By default, all events are collected. .Pp -.Nm trace -.Fl n +Options can be used to restrict collection to specific classes, class +ranges, subclasses, and codes. Classes and subclasses can be specified +any number of times, but only 4 codes can be filtered at once. Values +can be specified in hex (0x...), decimal, or octal (0...). +.Bl -tag -width " " +.It Fl c Ar class +Restrict collection to the events with the specified +.Ar class . +This option can be specified any number of times to collect events from +more classes. +.Bl -tag -width " " +.It Fl p Ar end-class +Provide an ending class to restrict collection to events in an inclusive +range of classes between +.Ar class +and +.Ar end-class . +.It Fl s Ar subclass +Restrict collection to the events with the specified +.Ar subclass . +.El +.It Fl a Ar pid +Restrict collection to to those events emitted by the process identified +by +.Ar pid . +.It Fl x Ar pid +Exclude events emitted by the process identified by +.Ar pid . +.It Fl k Ar code +Restrict collection to events with the specified +.Ar code . +This option can be specified up to 4 times, and applies to all classes +being collected. +.It Fl T Ar filter-file +Restrict collection to events specified in the provided +.Ar filter-file . +See +.Sx TRACEFILTER FORMAT +for details. +.It Xo Fl P +Restrict collection to PPT events. This special collection of trace +events provides insight into system performance. +.Xc +.El +.\" +.\" ## trace -E ## +.Bk -words +.It Xo Fl E +.Op Fl c Ar class Oo Fl p Ar end-class Oc Oo Fl s Ar subclass Oc +.Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code ... +.Op Fl P +.Op Fl T Ar filter-file +.Ar command Op args ... +.Ek +.Xc .Pp -.Nm trace +Execute +.Ar command +with trace collection enabled for events emitted by the process. See .Fl e -.Op Fl c Ar class Oo Fl p Ar class Oc Oo Fl s Ar subclass Oc -.Op Fl a Ar pid | Fl x Ar pid -.Op Fl k Ar code | Fl k Ar code | Fl k Ar code | Fl k Ar code +for more information. +.\" +.\" ## trace -t ## +.It Fl t Oo Fl o Ar outfile Oc Oo Fl N Oc Oo Ar codesfile ... Oc .Pp -.Nm trace -.Fl E -.Op Fl c Ar class Oo Fl p Ar class Oc Oo Fl s Ar subclass Oc -.Op Fl a Ar pid | Fl x Ar pid -.Op Fl k Ar code | Fl k Ar code | Fl k Ar code | Fl k Ar code -.Ar executable_path -.Op Ar optional args to executable +Extract events from the kernel trace buffer and print them in a formatted, +plain-text representation. Additional code files can be specified to +help +.Nm +find the names of unknown events. For more information on the formatting +process, see +.Sx TRACE CODES FORMAT . +.Bl -tag -width Ds +.It Fl o Ar outfile +Output the plain-text events to +.Ar outfile . +.It Fl N +Ignore the system-wide trace codes file when getting names of events. +Additional trace codes files specified will still be used. +.El +.\" +.\" ## trace -l ## +.It Fl l Ar rawfile .Pp -.Nm trace +Empty the current kernel trace buffer into +.Ar rawfile +in a binary format. +.\" +.\" ## trace -L ## +.It Fl L Ar rawfile Fl S Ar seconds +.Pp +Copy the current trace buffer to +.Ar rawfile +and send all future trace events to +.Ar rawfile . +.Bl -tag -width Ds +.It Fl S Ar seconds +After +.Ar seconds +have elapsed, stop recording and exit. +.El +.\" +.\" ## trace -R ## +.It Fl R Ar rawfile Oo Fl o Ar outfile Oc Oo Fl N Oc Oo Fl F Ar frequency Oc Oo Fl X Oc Op Ar codesfile ... +.Pp +Read events from +.Ar rawfile +and print them in a human-readable format. +.Bl -tag -width " " +.It Fl F Ar frequency +If +.Ar rawfile +does not contain clock frequency information, it can be specified with +.Fl F . +.It Fl X +Force the binary format to be interpreted as 32-bit, as opposed to +matching the width of the system running +.Nm . +.El +.Pp +See .Fl t -.Op Fl R Ar rawfile -.Op Fl o Ar OutputFilename -.Op Fl N -.Op Ar ExtraCodeFilename1 ExtraCodeFilename2 ... -.Sh DESCRIPTION -The -.Nm trace -command allows developers to initialize and configure -the kernel trace subsystem. Trace events can be recorded -to an in-memory buffer, or logged directly to a file. Raw -data files can later be decoded to a plaintext format. +for additional options. +.El +.Sh TRACE CODES FORMAT +Event classes, subclasses, and codes are matched to names using a trace +codes file. Any events that cannot be matched will be referred to by +their debugid in hex. +.Pp +The system-wide trace codes file is located at +.Pa /usr/share/misc/trace.codes . +Additional files are typically stored in +.Pa /usr/local/share/misc . +.Pp +A code file consists of a list of tracepoints, one per line, with the +tracepoint's debugid (component, subclass, and code) in hex, followed by +a tab, followed by the tracepoint's name. +.Pp +For instance, the MSC_mach_msg_trap tracepoint is defined by +.Pp +.Dl 0x010c007c MSC_mach_msg_trap +.Pp +This describes the tracepoint with the following info: +.Pp +.Bl -column -offset indent "Subclass" "MSC_mach_msg_trap" +.\" is this right? We should refer to the shifting and kdebug.h +.It Sy Name Ta MSC_mach_msg_trap +.It Sy Class Ta 0x01 Ta (Mach events) +.It Sy Subclass Ta 0x0c Ta (Mach system calls) +.It Sy Code Ta 0x007c Ta (msg_trap) +.El +.Pp +See +.\" this absolute path no longer exists thanks to SDKs. :P +.Pa /usr/include/sys/kdebug.h +for class and subclass values. +.Sh TRACEFILTER FORMAT +A tracefilter description file consists of a list of class and subclass +filters in hex, one per line, which are applied as if they were passed +with +.Fl c +and +.Fl s . +Pass +.Fl v +to see what classes and subclasses are being set. +.Pp +Comment lines start with +.Ql # , +class filter lines start with +.Ql C , +and subclass filter lines start with +.Ql S +and include the class they apply to. +.Pp +For example, to trace Mach events (class 1): +.Pp +.Dl C 0x01 +.Pp +And to trace Mach system calls (class 1, subclass 13): +.Pp +.Dl S 0x010C +.Pp +.Sh EXAMPLES +.Nm +usually requires multiple invocations in order to set up the trace +buffers, enable the correct events, and collect the events. A typical +session with trace is: +.Pp +.Dl trace -i +.Dl trace -e -c 1 -s 31 +.Dl sleep 1 +.Dl trace -d +.Dl trace -t +.Pp +This initializes the trace buffers to their default values, enables the +mach_msg_trap subclass of the MACH_SysCall class, waits for one second, +then disables tracing and prints it to +.Xr stdout 4 . +This is useful for investigating isolated issues or gaining some +understanding about a kernel subsystem. If a specific execuable should +be traced, with the events saved for later analysis, the sequence of +commands would be: +.Pp +.Dl trace -i +.Dl trace -E -c 0x4 ./my_prog +.Dl trace -d +.Dl trace -l tracefile +.Dl trace -R tracefile +.Pp +This initializes the trace buffers, enables all events in the BSC_SysCall class and runs +.Li my_prog , +disables tracing, collects events into +.Li tracefile , +and finally prints those events out in a human-readable form. +.Sh CAVEATS +Almost all +.Nm +command flags require superuser (root) privileges. +.Pp +After failures, the trace buffers usually need to be re-initialized. +.Pp +.Sh DIAGNOSTICS +.Ex -std .Sh SEE ALSO +.Xr trace 4 , .Xr fs_usage 1 , .Xr sc_usage 1 , .Xr latency 1 , diff --git a/trace.tproj/trace.c b/trace.tproj/trace.c index 59d657f..d664890 100644 --- a/trace.tproj/trace.c +++ b/trace.tproj/trace.c @@ -28,6 +28,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -93,6 +97,7 @@ extern char **environ; uint8_t* type_filter_bitmap; +#define SIZE_4KB (4 * (1 << 10)) #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) #define DBG_FUNC_MASK 0xfffffffc @@ -183,7 +188,6 @@ struct threadmap { char tm_command[MAXCOMLEN + 1]; }; - #define HASH_SIZE 1024 #define HASH_MASK 1023 @@ -242,6 +246,7 @@ static void delete_thread_entry(uintptr_t); static void find_and_insert_tmp_map_entry(uintptr_t, char *); static void create_tmp_map_entry(uintptr_t, uintptr_t); static void find_thread_name(uintptr_t, char **, boolean_t); +static void execute_process(char * const argv[]); static int writetrace(int); static int write_command_map(int); @@ -315,8 +320,12 @@ void set_enable(int val) #endif mib[4] = 0; mib[5] = 0; - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) { + if (errno == EINVAL) { + quit_args("trace facility failure, KERN_KDENABLE: trace buffer is uninitialized\n"); + } quit_args("trace facility failure, KERN_KDENABLE: %s\n", strerror(errno)); + } } void set_remove() @@ -390,11 +399,20 @@ void set_pidcheck(int pid, int on_off_flag) mib[5] = 0; if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) { - if (on_off_flag == 1) + if (errno == EACCES) + { + quit_args("trace facility failure, setting pid filter: %s\n", + strerror(errno)); + } + else if (on_off_flag == 1 && errno == ESRCH) { - printf("trace facility failure, KERN_KDPIDTR,\n\tpid %d does not exist\n", pid); set_remove(); - exit(2); + quit_args("trace facility failure, setting pid filter: " + "pid %d does not exist\n", pid); + } + else + { + quit_args("trace facility failure, KERN_KDPIDTR: %s\n", strerror(errno)); } } } @@ -703,15 +721,13 @@ uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now) void log_trace() { - char *buffer; - uint32_t buffer_size; - int fd; - int size; - int pad_size; - char pad_buf[4096]; + int fd = -1; + int ret = 0; + char *buffer; + uint32_t buffer_size = 1000000 * sizeof(kd_buf); - - if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) { + fd = open(logfile, O_TRUNC | O_WRONLY | O_CREAT, 0777); + if (fd == -1) { perror("Can't open logfile"); exit(1); } @@ -729,47 +745,33 @@ log_trace() else printf("Buffer has not wrapped\n"); } - buffer_size = 1000000 * sizeof(kd_buf); - buffer = malloc(buffer_size); - - if (buffer == (char *) 0) - quit("can't allocate memory for tracing info\n"); - - read_command_map(0, 0); - read_cpu_map(0); - - raw_header.version_no = RAW_VERSION1; - raw_header.thread_count = total_threads; - raw_header.TOD_secs = time((long *)0); - raw_header.TOD_usecs = 0; - - write(fd, &raw_header, sizeof(RAW_header)); - - size = total_threads * sizeof(kd_threadmap); - write(fd, (char *)mapptr, size); - pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095); - - if (cpumap_header) { - size_t cpumap_size = sizeof(kd_cpumap_header) + cpumap_header->cpu_count * sizeof(kd_cpumap); - if (pad_size >= cpumap_size) { - write(fd, (char *)cpumap_header, cpumap_size); - pad_size -= cpumap_size; - } + ret = write_command_map(fd); + if (ret) { + close(fd); + perror("failed to write logfile"); + exit(1); } - memset(pad_buf, 0, pad_size); - write(fd, pad_buf, pad_size); + buffer = malloc(buffer_size); + if (buffer == NULL) { + quit("can't allocate memory for events\n"); + } for (;;) { needed = buffer_size; readtrace(buffer); - if (needed == 0) + if (needed == 0) { break; + } + write(fd, buffer, needed * sizeof(kd_buf)); } + + free(buffer); + close(fd); } @@ -836,35 +838,9 @@ Log_trace() set_enable(1); if (write_command_map(fd)) { - int pad_size; - char pad_buf[4096]; - - read_command_map(0, 0); - read_cpu_map(0); - - raw_header.version_no = RAW_VERSION1; - raw_header.thread_count = total_threads; - raw_header.TOD_secs = time((long *)0); - raw_header.TOD_usecs = 0; - - write(fd, &raw_header, sizeof(RAW_header)); - - size = total_threads * sizeof(kd_threadmap); - write(fd, (char *)mapptr, size); - - pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095); - - if (cpumap_header) { - size_t cpumap_size = sizeof(kd_cpumap_header) + cpumap_header->cpu_count * sizeof(kd_cpumap); - if (pad_size >= cpumap_size) { - write(fd, (char *)cpumap_header, cpumap_size); - pad_size -= cpumap_size; - } - } - - memset(pad_buf, 0, pad_size); - write(fd, pad_buf, pad_size); + quit("can't write tracefile header\n"); } + sample_window_abs = (uint64_t)((double)US_TO_SLEEP * divisor); next_window_begins = mach_absolute_time() + sample_window_abs; @@ -1301,7 +1277,6 @@ char **env; { extern char *optarg; extern int optind; - int status; int ch; int i; char *output_filename = NULL; @@ -1520,21 +1495,21 @@ char **env; if (pid_flag) { set_pidcheck(pid, 0); /* disable pid check for given pid */ - exit(1); + exit(0); } else if (pid_exflag) { set_pidexclude(pid, 0); /* disable pid exclusion for given pid */ - exit(1); + exit(0); } set_enable(0); - exit(1); + exit(0); } if (remove_flag) { set_remove(); - exit(1); + exit(0); } if (bufset_flag ) @@ -1634,26 +1609,8 @@ char **env; fflush(stdout); fflush(stderr); - switch ((pid = vfork())) - { - case -1: - perror("vfork: "); - exit(1); - case 0: /* child */ - setsid(); - ptrace(PT_TRACE_ME, 0, (caddr_t)0, 0); - execve(argv[optind], &argv[optind], environ); - perror("execve:"); - exit(1); - } - sleep(1); + execute_process(&(argv[optind])); - signal(SIGINT, signal_handler); - set_pidcheck(pid, 1); - set_enable(1); - ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); - waitpid(pid, &status, 0); - /* child is gone; no need to disable the pid */ exit(0); } else if (enable_flag) @@ -1695,6 +1652,49 @@ char **env; } /* end main */ +static void +execute_process(char * const argv[]) +{ + int status = 0; + int rc = 0; + posix_spawnattr_t spawn_attrs; + + assert(argv); + + /* ensure that the process being spawned starts suspended */ + rc = posix_spawnattr_init(&spawn_attrs); + if (rc != 0) { + quit_args("Failed to initialize spawn attrs: %s\n", strerror(rc)); + } + rc = posix_spawnattr_setflags(&spawn_attrs, + POSIX_SPAWN_START_SUSPENDED); + if (rc != 0) { + quit_args("Unable to start process suspended: %s\n", strerror(rc)); + } + + /* spawn the process with the rest of the arguments */ + rc = posix_spawnp(&pid, argv[0], NULL, &spawn_attrs, argv, environ); + if (rc != 0) { + quit_args("Unabled to start process: %s\n", strerror(rc)); + } + + signal(SIGINT, signal_handler); + set_pidcheck(pid, 1); + set_enable(1); + + /* start the child process */ + rc = kill(pid, SIGCONT); + if (rc != 0) { + perror("Failed to continue child process:"); + exit(EX_OSERR); + } + + rc = waitpid(pid, &status, 0); + if (rc == -1) { + perror("Failed to wait for process: "); + } +} + static void quit_args(const char *fmt, ...) { @@ -2512,11 +2512,10 @@ read_cpu_map(int fd) * cpu maps exist in a RAW_VERSION1+ header only */ if (raw_header.version_no == RAW_VERSION1) { - off_t base_offset = lseek(fd, (off_t)0, SEEK_CUR); - off_t aligned_offset = (base_offset + (4095)) & ~4095; /* */ - - size_t padding_bytes = (size_t)(aligned_offset - base_offset); - + off_t cpumap_position = lseek(fd, 0, SEEK_CUR); + /* cpumap is part of the last 4KB of padding in the preamble */ + size_t padding_bytes = SIZE_4KB - (cpumap_position & (SIZE_4KB - 1)); + if (read(fd, cpumap_header, padding_bytes) == padding_bytes) { if (cpumap_header->version_no == RAW_VERSION1) { cpumap = (kd_cpumap*)&cpumap_header[1]; @@ -2630,6 +2629,7 @@ read_command_map(int fd, uint32_t count) mapptr[i].command); } } + return (int)size; } diff --git a/zic.tproj/generate_zoneinfo.sh b/zic.tproj/generate_zoneinfo.sh index e0a0176..6b921d1 100755 --- a/zic.tproj/generate_zoneinfo.sh +++ b/zic.tproj/generate_zoneinfo.sh @@ -67,16 +67,23 @@ if [ $? -ne 0 ]; then exit 1 fi -if [[ "${PLATFORM_NAME}" == "iphoneos"* ]]; then +case "$PLATFORM_NAME" in +iphone*|appletv*|watch*) mkdir -p "${PRIVATEDIR}/var/db" mkdir -p -m a+rx "${PRIVATEDIR}/var/db/timezone" # This link must precisely start with TZDIR followed by a slash. radar:13532660 ln -hfs "/var/db/timezone/zoneinfo/${LOCALTIME}" "${PRIVATEDIR}/var/db/timezone/localtime" -else + ;; +macosx) mkdir -p "${PRIVATEDIR}/etc" ln -hfs "/usr/share/zoneinfo/${LOCALTIME}" "${PRIVATEDIR}/etc/localtime" -fi + ;; +*) + echo "Unsupported platform: $PLATFORM_NAME" + exit 1 + ;; +esac rm -f "${VERSIONFILE}" echo ${DATVERS} > "${VERSIONFILE}" diff --git a/zic.tproj/install_zoneinfo.sh b/zic.tproj/install_zoneinfo.sh index ed372b4..94846aa 100755 --- a/zic.tproj/install_zoneinfo.sh +++ b/zic.tproj/install_zoneinfo.sh @@ -1,8 +1,17 @@ #!/bin/sh +set -e +set -x -if [[ "${PLATFORM_NAME}" == "iphoneos"* ]]; then -ditto "${BUILT_PRODUCTS_DIR}/zoneinfo" "${DSTROOT}/usr/share/zoneinfo.default" -ln -hfs "/var/db/timezone/zoneinfo" "${DSTROOT}/usr/share/zoneinfo" -else -ditto "${BUILT_PRODUCTS_DIR}/zoneinfo" "${DSTROOT}/usr/share/zoneinfo" -fi +case "$PLATFORM_NAME" in +iphone*|appletv*|watch*) + ditto "${BUILT_PRODUCTS_DIR}/zoneinfo" "${DSTROOT}/usr/share/zoneinfo.default" + ln -hfs "/var/db/timezone/zoneinfo" "${DSTROOT}/usr/share/zoneinfo" + ;; +macosx) + ditto "${BUILT_PRODUCTS_DIR}/zoneinfo" "${DSTROOT}/usr/share/zoneinfo" + ;; +*) + echo "Unsupported platform: $PLATFORM_NAME" + exit 1 + ;; +esac diff --git a/zprint.tproj/entitlements.plist b/zprint.tproj/entitlements.plist new file mode 100644 index 0000000..50ad69c --- /dev/null +++ b/zprint.tproj/entitlements.plist @@ -0,0 +1,12 @@ + + + + + com.apple.system-task-ports + + task_for_pid-allow + + com.apple.private.kernel.get-kext-info + + + diff --git a/zprint.tproj/zprint.c b/zprint.tproj/zprint.c index 74a7d58..fed4172 100644 --- a/zprint.tproj/zprint.c +++ b/zprint.tproj/zprint.c @@ -65,6 +65,9 @@ * to zones but not currently in use. */ + + +#include #include #include #include @@ -73,16 +76,35 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + #define streql(a, b) (strcmp((a), (b)) == 0) #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0) +#define PRINTK(fmt, value) \ + printf(fmt "K", (value) / 1024 ) /* ick */ static void usage(void); static void printzone(mach_zone_name_t *, task_zone_info_t *); static void colprintzone(mach_zone_name_t *, task_zone_info_t *); static int find_deltas(mach_zone_name_t *, task_zone_info_t *, task_zone_info_t *, char *, int, int); static void colprintzoneheader(void); -static boolean_t substr(const char *a, int alen, const char *b, int blen); +static boolean_t substr(const char *a, size_t alen, const char *b, size_t blen); + +static int SortName(const void * left, const void * right); +static int SortSize(const void * left, const void * right); +static void PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, int (*func)(const void *, const void *), boolean_t column); static char *program; @@ -93,6 +115,7 @@ static boolean_t ShowPid = FALSE; static boolean_t ShowDeltas = FALSE; static boolean_t ShowWasted = FALSE; static boolean_t ShowTotal = FALSE; +static boolean_t ShowLarge = TRUE; static boolean_t SortZones = FALSE; static boolean_t ColFormat = TRUE; static boolean_t PrintHeader = TRUE; @@ -105,7 +128,7 @@ static unsigned long long pidsum = 0; static int last_time = 0; static char *zname = NULL; -static int znamelen = 0; +static size_t znamelen = 0; static void sigintr(__unused int signum) @@ -127,7 +150,8 @@ main(int argc, char **argv) unsigned int nameCnt = 0; task_zone_info_t *info = NULL; unsigned int infoCnt = 0; - + mach_memory_info_t *wiredInfo = NULL; + unsigned int wiredInfoCnt = 0; task_zone_info_t *max_info = NULL; char *deltas = NULL; @@ -156,6 +180,10 @@ main(int argc, char **argv) ShowWasted = TRUE; else if (streql(argv[i], "-W")) ShowWasted = FALSE; + else if (streql(argv[i], "-l")) + ShowLarge = TRUE; + else if (streql(argv[i], "-L")) + ShowLarge = FALSE; else if (streql(argv[i], "-s")) SortZones = TRUE; else if (streql(argv[i], "-S")) @@ -223,13 +251,15 @@ main(int argc, char **argv) } else { mach_zone_info_t *zinfo = NULL; - kr = mach_zone_info(mach_host_self(), - &name, &nameCnt, &zinfo, &infoCnt); + kr = mach_memory_info(mach_host_self(), + &name, &nameCnt, &zinfo, &infoCnt, + &wiredInfo, &wiredInfoCnt); if (kr != KERN_SUCCESS) { fprintf(stderr, "%s: mach_zone_info: %s\n", program, mach_error_string(kr)); exit(1); } + kr = vm_allocate(mach_task_self(), (vm_address_t *)&info, infoCnt * sizeof *info, VM_FLAGS_ANYWHERE); if (kr != KERN_SUCCESS) { @@ -266,7 +296,7 @@ main(int argc, char **argv) if (SortZones) { for (i = 0; i < nameCnt-1; i++) for (j = i+1; j < nameCnt; j++) { - int wastei, wastej; + unsigned long long wastei, wastej; wastei = (info[i].tzi_cur_size - (info[i].tzi_elem_size * @@ -305,6 +335,11 @@ main(int argc, char **argv) printzone(&name[i], &info[i]); } } + + if (ShowLarge && first_time) { + PrintLarge(wiredInfo, wiredInfoCnt, + SortZones ? &SortSize : &SortName, ColFormat); + } } first_time = 0; @@ -329,6 +364,16 @@ main(int argc, char **argv) } } + if ((wiredInfo != NULL) && (wiredInfoCnt != 0)) { + kr = vm_deallocate(mach_task_self(), (vm_address_t) wiredInfo, + (vm_size_t) (wiredInfoCnt * sizeof *wiredInfo)); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s: vm_deallocate: %s\n", + program, mach_error_string(kr)); + exit(1); + } + } + if ((ShowWasted||ShowTotal) && PrintHeader && !ShowDeltas) { printf("TOTAL SIZE = %llu\n", totalsize); printf("TOTAL USED = %llu\n", totalused); @@ -347,7 +392,7 @@ main(int argc, char **argv) } static boolean_t -substr(const char *a, int alen, const char *b, int blen) +substr(const char *a, size_t alen, const char *b, size_t blen) { int i; @@ -406,9 +451,6 @@ printzone(mach_zone_name_t *name, task_zone_info_t *info) } } -#define PRINTK(fmt, value) \ - printf(fmt "K", (value) / 1024 ) /* ick */ - static void colprintzone(mach_zone_name_t *zone_name, task_zone_info_t *info) { @@ -533,3 +575,289 @@ find_deltas(mach_zone_name_t *name, task_zone_info_t *info, task_zone_info_t *ma } return(found_one); } + +/********************************************************************* +*********************************************************************/ + +static char * +kern_vm_tag_name(uint64_t tag) +{ + char * result; + const char * name; + switch (tag) + { + case (VM_KERN_MEMORY_NONE): name = "VM_KERN_MEMORY_NONE"; break; + case (VM_KERN_MEMORY_OSFMK): name = "VM_KERN_MEMORY_OSFMK"; break; + case (VM_KERN_MEMORY_BSD): name = "VM_KERN_MEMORY_BSD"; break; + case (VM_KERN_MEMORY_IOKIT): name = "VM_KERN_MEMORY_IOKIT"; break; + case (VM_KERN_MEMORY_LIBKERN): name = "VM_KERN_MEMORY_LIBKERN"; break; + case (VM_KERN_MEMORY_OSKEXT): name = "VM_KERN_MEMORY_OSKEXT"; break; + case (VM_KERN_MEMORY_KEXT): name = "VM_KERN_MEMORY_KEXT"; break; + case (VM_KERN_MEMORY_IPC): name = "VM_KERN_MEMORY_IPC"; break; + case (VM_KERN_MEMORY_STACK): name = "VM_KERN_MEMORY_STACK"; break; + case (VM_KERN_MEMORY_CPU): name = "VM_KERN_MEMORY_CPU"; break; + case (VM_KERN_MEMORY_PMAP): name = "VM_KERN_MEMORY_PMAP"; break; + case (VM_KERN_MEMORY_PTE): name = "VM_KERN_MEMORY_PTE"; break; + case (VM_KERN_MEMORY_ZONE): name = "VM_KERN_MEMORY_ZONE"; break; + case (VM_KERN_MEMORY_KALLOC): name = "VM_KERN_MEMORY_KALLOC"; break; + case (VM_KERN_MEMORY_COMPRESSOR): name = "VM_KERN_MEMORY_COMPRESSOR"; break; + case (VM_KERN_MEMORY_COMPRESSED_DATA): name = "VM_KERN_MEMORY_COMPRESSED_DATA"; break; + case (VM_KERN_MEMORY_PHANTOM_CACHE): name = "VM_KERN_MEMORY_PHANTOM_CACHE"; break; + case (VM_KERN_MEMORY_WAITQ): name = "VM_KERN_MEMORY_WAITQ"; break; + case (VM_KERN_MEMORY_DIAG): name = "VM_KERN_MEMORY_DIAG"; break; + case (VM_KERN_MEMORY_LOG): name = "VM_KERN_MEMORY_LOG"; break; + case (VM_KERN_MEMORY_FILE): name = "VM_KERN_MEMORY_FILE"; break; + case (VM_KERN_MEMORY_MBUF): name = "VM_KERN_MEMORY_MBUF"; break; + case (VM_KERN_MEMORY_UBC): name = "VM_KERN_MEMORY_UBC"; break; + case (VM_KERN_MEMORY_SECURITY): name = "VM_KERN_MEMORY_SECURITY"; break; + case (VM_KERN_MEMORY_MLOCK): name = "VM_KERN_MEMORY_MLOCK"; break; + case (VM_KERN_MEMORY_ANY): name = "VM_KERN_MEMORY_ANY"; break; + default: name = NULL; break; + } + if (name) asprintf(&result, "%s", name); + else asprintf(&result, "VM_KERN_MEMORY_%lld", tag); + return (result); + } + +static char * +kern_vm_counter_name(uint64_t tag) +{ + char * result; + const char * name; + switch (tag) + { + case (VM_KERN_COUNT_MANAGED): name = "VM_KERN_COUNT_MANAGED"; break; + case (VM_KERN_COUNT_RESERVED): name = "VM_KERN_COUNT_RESERVED"; break; + case (VM_KERN_COUNT_WIRED): name = "VM_KERN_COUNT_WIRED"; break; + case (VM_KERN_COUNT_WIRED_MANAGED): name = "VM_KERN_COUNT_WIRED_MANAGED"; break; + case (VM_KERN_COUNT_STOLEN): name = "VM_KERN_COUNT_STOLEN"; break; + case (VM_KERN_COUNT_LOPAGE): name = "VM_KERN_COUNT_LOPAGE"; break; + case (VM_KERN_COUNT_MAP_KERNEL): name = "VM_KERN_COUNT_MAP_KERNEL"; break; + case (VM_KERN_COUNT_MAP_ZONE): name = "VM_KERN_COUNT_MAP_ZONE"; break; + case (VM_KERN_COUNT_MAP_KALLOC): name = "VM_KERN_COUNT_MAP_KALLOC"; break; + default: name = NULL; break; + } + if (name) asprintf(&result, "%s", name); + else asprintf(&result, "VM_KERN_COUNT_%lld", tag); + return (result); +} + +static void +MakeLoadTagKeys(const void * key, const void * value, void * context) +{ + CFMutableDictionaryRef newDict = context; + CFDictionaryRef kextInfo = value; + CFNumberRef loadTag; + uint32_t loadTagValue; + + loadTag = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleLoadTagKey)); + CFNumberGetValue(loadTag, kCFNumberSInt32Type, &loadTagValue); + key = (const void *)(uintptr_t) loadTagValue; + CFDictionarySetValue(newDict, key, value); +} + +static CSSymbolicatorRef gSym; +static CFMutableDictionaryRef gTagDict; +static mach_memory_info_t * gSites; + +static char * +GetSiteName(int siteIdx) +{ + const char * name; + char * result; + mach_vm_address_t addr; + CFDictionaryRef kextInfo; + CFStringRef bundleID; + uint32_t type; + + const mach_memory_info_t * site; + const char * fileName; + CSSymbolRef symbol; + const char * symbolName; + CSSourceInfoRef sourceInfo; + + name = NULL; + result = NULL; + site = &gSites[siteIdx]; + addr = site->site; + type = (VM_KERN_SITE_TYPE & site->flags); + switch (type) + { + case VM_KERN_SITE_TAG: + result = kern_vm_tag_name(addr); + break; + + case VM_KERN_SITE_COUNTER: + result = kern_vm_counter_name(addr); + break; + + case VM_KERN_SITE_KMOD: + kextInfo = CFDictionaryGetValue(gTagDict, (const void *)(uintptr_t) addr); + if (kextInfo) + { + bundleID = (CFStringRef)CFDictionaryGetValue(kextInfo, kCFBundleIdentifierKey); + name = CFStringGetCStringPtr(bundleID, kCFStringEncodingUTF8); + // wiredSize = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleWiredSizeKey)); + } + asprintf(&result, "%-64s%3lld", name ? name : "(unknown kmod)", addr); + break; + + case VM_KERN_SITE_KERNEL: + symbolName = NULL; + if (addr) + { + symbol = CSSymbolicatorGetSymbolWithAddressAtTime(gSym, addr, kCSNow); + symbolName = CSSymbolGetName(symbol); + } + if (symbolName) + { + asprintf(&result, "%s", symbolName); + sourceInfo = CSSymbolicatorGetSourceInfoWithAddressAtTime(gSym, addr, kCSNow); + fileName = CSSourceInfoGetPath(sourceInfo); + if (fileName) printf(" (%s:%d)", fileName, CSSourceInfoGetLineNumber(sourceInfo)); + } + else + { + asprintf(&result, "site 0x%qx", addr); + } + break; + default: + asprintf(&result, ""); + break; + } + + return (result); +} + +static int +SortName(const void * left, const void * right) +{ + const int * idxL; + const int * idxR; + char * l; + char * r; + int result; + + idxL = (typeof(idxL)) left; + idxR = (typeof(idxR)) right; + l = GetSiteName(*idxL); + r = GetSiteName(*idxR); + + result = strcmp(l, r); + free(l); + free(r); + + return (result); +} + +static int +SortSize(const void * left, const void * right) +{ + const mach_memory_info_t * siteL; + const mach_memory_info_t * siteR; + const int * idxL; + const int * idxR; + + idxL = (typeof(idxL)) left; + idxR = (typeof(idxR)) right; + siteL = &gSites[*idxL]; + siteR = &gSites[*idxR]; + + if (siteL->size > siteR->size) return (-1); + else if (siteL->size < siteR->size) return (1); + return (0); +} + + +static void +PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, + int (*func)(const void *, const void *), boolean_t column) +{ + uint64_t zonetotal; + uint64_t top_wired; + + CFDictionaryRef allKexts; + unsigned int idx, site, first; + int sorted[wiredInfoCnt]; + char totalstr[40]; + char * name; + + zonetotal = totalsize; + + gSites = wiredInfo; + + gSym = CSSymbolicatorCreateWithMachKernel(); + + allKexts = OSKextCopyLoadedKextInfo(NULL, NULL); + gTagDict = CFDictionaryCreateMutable( + kCFAllocatorDefault, (CFIndex) 0, + (CFDictionaryKeyCallBacks *) 0, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryApplyFunction(allKexts, &MakeLoadTagKeys, gTagDict); + CFRelease(allKexts); + + top_wired = 0; + + for (idx = 0; idx < wiredInfoCnt; idx++) sorted[idx] = idx; + first = 0; // VM_KERN_MEMORY_FIRST_DYNAMIC + qsort(&sorted[first], + wiredInfoCnt - first, + sizeof(sorted[0]), + func); + + printf("-------------------------------------------------------------------------------------------------------------\n"); + printf(" kmod vm cur\n"); + printf("wired memory id tag size\n"); + printf("-------------------------------------------------------------------------------------------------------------\n"); + + for (idx = 0; idx < wiredInfoCnt; idx++) + { + site = sorted[idx]; + if (!gSites[site].size) continue; + if (VM_KERN_COUNT_WIRED == gSites[site].site) top_wired = gSites[site].size; + if (VM_KERN_SITE_HIDE & gSites[site].flags) continue; + if (!(VM_KERN_SITE_WIRED & gSites[site].flags)) continue; + + name = GetSiteName(site); + printf("%-67s", name); + free(name); + printf("%12d", site); + + printf(" %11s", ""); + PRINTK(" %12llu", gSites[site].size); + totalsize += gSites[site].size; + + printf("\n"); + } + + printf("%-67s", "zones"); + printf("%12s", ""); + printf(" %11s", ""); + PRINTK(" %12llu", zonetotal); + snprintf(totalstr, sizeof(totalstr), "%6.2fM of %6.2fM", totalsize / 1024.0 / 1024.0, top_wired / 1024.0 / 1024.0); + printf("\ntotal%100s\n", totalstr); + + printf("-------------------------------------------------------------------------------------------------------------\n"); + printf(" largest\n"); + printf("maps free free size\n"); + printf("-------------------------------------------------------------------------------------------------------------\n"); + + for (idx = 0; idx < wiredInfoCnt; idx++) + { + site = sorted[idx]; + if (!gSites[site].size) continue; + if (VM_KERN_SITE_HIDE & gSites[site].flags) continue; + if (VM_KERN_SITE_WIRED & gSites[site].flags) continue; + + name = GetSiteName(site); + printf("%-67s", name); + free(name); + + PRINTK(" %10llu", gSites[site].free); + PRINTK(" %10llu", gSites[site].largest); + PRINTK(" %12llu", gSites[site].size); + + printf("\n"); + } +} -- 2.45.2