From cf37c2996a8b83ccbcb7e2e413f749f6e60a3845 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 22 Sep 2016 18:04:38 +0000 Subject: [PATCH] system_cmds-735.tar.gz --- CPPUtil/CPPUtil.h | 61 - CPPUtil/UtilAbsInterval.cpp | 74 - CPPUtil/UtilAbsInterval.hpp | 92 - CPPUtil/UtilAbsTime.cpp | 30 - CPPUtil/UtilAbsTime.hpp | 62 - CPPUtil/UtilAssert.hpp | 50 - CPPUtil/UtilBase.hpp | 15 - CPPUtil/UtilException.hpp | 34 - CPPUtil/UtilFileDescriptor.hpp | 52 - CPPUtil/UtilLog.cpp | 24 - CPPUtil/UtilLog.hpp | 14 - CPPUtil/UtilMakeUnique.hpp | 23 - CPPUtil/UtilMappedFile.cpp | 57 - CPPUtil/UtilMappedFile.hpp | 27 - CPPUtil/UtilMemoryBuffer.hpp | 63 - CPPUtil/UtilNanoInterval.hpp | 14 - CPPUtil/UtilNanoTime.cpp | 19 - CPPUtil/UtilNanoTime.hpp | 57 - CPPUtil/UtilPath.cpp | 92 - CPPUtil/UtilPath.hpp | 34 - CPPUtil/UtilPrettyPrinting.cpp | 26 - CPPUtil/UtilPrettyPrinting.hpp | 14 - CPPUtil/UtilString.cpp | 18 - CPPUtil/UtilString.hpp | 41 - CPPUtil/UtilTRange.hpp | 254 - CPPUtil/UtilTRangeValue.hpp | 26 - CPPUtil/UtilTerminalColor.cpp | 39 - CPPUtil/UtilTerminalColor.hpp | 28 - CPPUtil/UtilTime.hpp | 21 - CPPUtil/UtilTimer.cpp | 31 - CPPUtil/UtilTimer.hpp | 23 - KDBG/CPUActivity.hpp | 90 - KDBG/CPUSummary.hpp | 353 - KDBG/IOActivity.hpp | 34 - KDBG/KDBG.cpp | 181 - KDBG/KDBG.hpp | 190 - KDBG/KDCPUMapEntry.hpp | 36 - KDBG/KDEvent.hpp | 150 - KDBG/KDState.hpp | 79 - KDBG/KDThreadMapEntry.hpp | 43 - KDBG/KDebug.h | 69 - KDBG/Kernel.cpp | 52 - KDBG/Kernel.hpp | 20 - KDBG/Machine.hpp | 143 - KDBG/Machine.impl.hpp | 1085 --- KDBG/Machine.mutable-impl.hpp | 1128 --- KDBG/MachineCPU.hpp | 121 - KDBG/MachineCPU.impl.hpp | 36 - KDBG/MachineCPU.mutable-impl.hpp | 329 - KDBG/MachineMachMsg.hpp | 126 - KDBG/MachineProcess.hpp | 173 - KDBG/MachineProcess.impl.hpp | 57 - KDBG/MachineProcess.mutable-impl.hpp | 163 - KDBG/MachineThread.hpp | 124 - KDBG/MachineThread.impl.hpp | 99 - KDBG/MachineThread.mutable-impl.hpp | 215 - KDBG/MachineVoucher.hpp | 174 - KDBG/MetaTypes.hpp | 25 - KDBG/NurseryMachMsg.hpp | 89 - KDBG/ProcessSummary.hpp | 198 - KDBG/TaskEffectivePolicy.hpp | 47 - KDBG/TaskRequestedPolicy.hpp | 48 - KDBG/ThreadSummary.hpp | 149 - KDBG/TraceCodes.cpp | 73 - KDBG/TraceCodes.hpp | 20 - KDBG/TraceDataHeader.hpp | 81 - KDBG/TraceFile.cpp | 28 - KDBG/TraceFile.hpp | 257 - KDBG/VoucherInterval.hpp | 26 - ac.tproj/ac.c | 88 +- accton.tproj/accton.c | 2 +- arch.tproj/arch.c | 77 +- at.tproj/at.c | 79 +- at.tproj/at.h | 2 +- at.tproj/panic.c | 2 +- at.tproj/panic.h | 2 +- at.tproj/parsetime.c | 70 +- at.tproj/parsetime.h | 2 +- at.tproj/pathnames.h | 10 +- at.tproj/perm.c | 2 +- at.tproj/perm.h | 2 +- at.tproj/privs.h | 6 +- atrun.tproj/atrun.c | 30 +- atrun.tproj/gloadavg.c | 4 +- atrun.tproj/gloadavg.h | 2 +- chkpasswd.tproj/file_passwd.c | 30 +- chkpasswd.tproj/nis_passwd.c | 35 +- chkpasswd.tproj/od_passwd.c | 21 +- chkpasswd.tproj/pam_passwd.c | 17 +- chkpasswd.tproj/passwd.c | 24 +- chkpasswd.tproj/passwd.h | 5 + chkpasswd.tproj/stringops.c | 69 +- chkpasswd.tproj/stringops.h | 8 +- chpass.tproj/chpass.c | 26 +- chpass.tproj/chpass.h | 8 +- chpass.tproj/edit.c | 10 +- chpass.tproj/field.c | 13 +- chpass.tproj/open_directory.c | 24 +- chpass.tproj/pw_copy.c | 12 +- chpass.tproj/pw_copy.h | 8 +- chpass.tproj/table.c | 8 +- chpass.tproj/util.c | 57 +- dmesg.tproj/dmesg.c | 17 +- dynamic_pager.tproj/backing_store_alerts.defs | 23 - .../backing_store_triggers.defs | 25 - dynamic_pager.tproj/default_pager_alerts.defs | 1 - dynamic_pager.tproj/dynamic_pager.c | 12 +- fs_usage.tproj/fs_usage.1 | 14 +- fs_usage.tproj/fs_usage.c | 6857 ++++++----------- gcore.tproj/corefile.c | 634 ++ gcore.tproj/corefile.h | 64 + gcore.tproj/dyld.c | 249 + gcore.tproj/dyld.h | 33 + gcore.tproj/dyld_shared_cache.c | 106 + gcore.tproj/dyld_shared_cache.h | 36 + gcore.tproj/gcore.1 | 105 + gcore.tproj/loader_additions.h | 65 + gcore.tproj/main.c | 597 ++ gcore.tproj/options.h | 47 + gcore.tproj/region.h | 104 + gcore.tproj/sparse.c | 478 ++ gcore.tproj/sparse.h | 71 + gcore.tproj/threads.c | 78 + gcore.tproj/threads.h | 14 + gcore.tproj/utils.c | 91 + gcore.tproj/utils.h | 28 + gcore.tproj/vanilla.c | 708 ++ gcore.tproj/vanilla.h | 16 + gcore.tproj/vm.c | 556 ++ gcore.tproj/vm.h | 48 + getconf.tproj/getconf.c | 5 +- getty.tproj/chat.c | 14 +- getty.tproj/init.c | 10 +- getty.tproj/main.c | 23 +- getty.tproj/subr.c | 6 +- hostinfo.tproj/hostinfo.c | 21 +- iosim.tproj/iosim.c | 101 +- iostat.tproj/iostat.c | 62 +- kdprof/Action.hpp | 17 - kdprof/CollectAction.cpp | 89 - kdprof/CollectAction.hpp | 19 - kdprof/DisableAction.cpp | 15 - kdprof/DisableAction.hpp | 19 - kdprof/EnableAction.cpp | 15 - kdprof/EnableAction.hpp | 19 - kdprof/EventPrinting.cpp | 31 - kdprof/EventPrinting.hpp | 346 - kdprof/Globals.cpp | 120 - kdprof/Globals.hpp | 176 - kdprof/InitializeAction.cpp | 21 - kdprof/InitializeAction.hpp | 22 - kdprof/NoWrapAction.cpp | 13 - kdprof/NoWrapAction.hpp | 19 - kdprof/PrintStateAction.cpp | 15 - kdprof/PrintStateAction.hpp | 19 - kdprof/RemoveAction.cpp | 13 - kdprof/RemoveAction.hpp | 19 - kdprof/SaveTraceAction.cpp | 101 - kdprof/SaveTraceAction.hpp | 25 - kdprof/SleepAction.cpp | 17 - kdprof/SleepAction.hpp | 21 - kdprof/SummaryPrinting.cpp | 42 - kdprof/SummaryPrinting.hpp | 1504 ---- kdprof/TraceFileAction.cpp | 260 - kdprof/TraceFileAction.hpp | 24 - kdprof/global.h | 42 - kdprof/kdprof.1 | 17 - kdprof/kdprof.cpp | 444 -- kpgo.tproj/kpgo.c | 28 +- latency.tproj/latency.c | 320 +- login.tproj/klogin.c | 14 +- login.tproj/login.c | 32 +- login.tproj/login_audit.c | 13 +- lskq.tproj/common.h | 5 + lskq.tproj/lskq.1 | 45 +- lskq.tproj/lskq.c | 382 +- lsmp.tproj/common.h | 20 +- lsmp.tproj/lsmp.c | 48 +- lsmp.tproj/port_details.c | 114 +- lsmp.tproj/task_details.c | 115 +- ltop.tproj/ltop.c | 94 +- makekey.tproj/makekey.8 | 59 - makekey.tproj/makekey.c | 106 - mean.tproj/mean.c | 39 +- memory_pressure.tproj/memory_pressure.c | 120 +- mkfile.tproj/mkfile.c | 75 +- msa/Action.hpp | 17 - msa/EventProcessing.hpp | 425 - msa/EventRingBuffer.hpp | 154 - msa/Globals.cpp | 80 - msa/Globals.hpp | 123 - msa/LiveTraceAction.cpp | 184 - msa/LiveTraceAction.hpp | 19 - msa/PrintBuffer.hpp | 116 - msa/Printing.cpp | 254 - msa/Printing.hpp | 1318 ---- msa/ReadTraceFileAction.cpp | 77 - msa/ReadTraceFileAction.hpp | 24 - msa/VoucherContentSysctl.cpp | 27 - msa/VoucherContentSysctl.hpp | 24 - msa/WriteTraceFileAction.cpp | 74 - msa/WriteTraceFileAction.hpp | 26 - msa/global.h | 40 - msa/main.cpp | 208 - msa/msa.1 | 154 - newgrp.tproj/newgrp.c | 4 +- nvram.tproj/nvram.c | 200 +- passwd.tproj/file_passwd.c | 16 +- passwd.tproj/nis_passwd.c | 26 +- passwd.tproj/od_passwd.c | 26 +- passwd.tproj/pam_passwd.c | 14 +- passwd.tproj/passwd.c | 31 +- passwd.tproj/passwd.h | 8 +- proc_uuid_policy.tproj/proc_uuid_policy.1 | 54 + proc_uuid_policy.tproj/proc_uuid_policy.c | 470 ++ purge.tproj/purge.c | 5 +- pwd_mkdb.tproj/pw_scan.c | 1 + pwd_mkdb.tproj/pw_scan.h | 8 +- pwd_mkdb.tproj/pwd_mkdb.c | 43 +- reboot.tproj/reboot.c | 16 +- sa.tproj/main.c | 2 +- sa.tproj/pdb.c | 10 +- sa.tproj/usrdb.c | 8 +- sadc.tproj/sa1.8 | 85 - sadc.tproj/sa1.sh | 31 - sadc.tproj/sa2.8 | 100 - sadc.tproj/sa2.sh | 29 - sadc.tproj/sadc.8 | 110 - sadc.tproj/sadc.c | 909 --- sadc.tproj/sadc.h | 120 - sar.tproj/sar.1 | 223 - sar.tproj/sar.c | 2340 ------ sar.tproj/sar.h | 135 - sc_usage.tproj/sc_usage.c | 376 +- shutdown.tproj/pathnames.h | 8 +- shutdown.tproj/shutdown.c | 44 +- sysctl.tproj/sysctl.c | 8 +- system_cmds.xcodeproj/project.pbxproj | 2768 +++---- .../xcschemes/All_MacOSX.xcscheme | 28 +- .../xcshareddata/xcschemes/All_iOS.xcscheme | 26 +- taskpolicy.tproj/taskpolicy.8 | 4 +- taskpolicy.tproj/taskpolicy.c | 27 +- trace.tproj/trace.1 | 18 +- trace.tproj/trace.c | 560 +- vifs.tproj/vifs.c | 8 +- vipw.tproj/pw_util.c | 39 +- vipw.tproj/pw_util.h | 8 +- vipw.tproj/vipw.c | 24 +- vm_purgeable_stat.tproj/vm_purgeable_stat.c | 32 +- vm_stat.tproj/vm_stat.c | 14 +- wait4path/wait4path.1 | 37 + wait4path/wait4path.c | 64 + wait4path/wait4path.version | 5 + wordexp-helper.tproj/wordexp-helper.c | 8 +- xcconfigs/base.xcconfig | 88 + xcconfigs/development.xcconfig | 29 + xcconfigs/executable.xcconfig | 45 + xcconfigs/wait4path.xcconfig | 16 + xscripts/darwinversion.sh | 228 + zdump.tproj/zdump.c | 42 +- zic.tproj/generate_zone_file_list.sh | 4 +- zic.tproj/generate_zoneinfo.sh | 16 +- zic.tproj/ialloc.c | 39 +- zic.tproj/install_zoneinfo.sh | 12 +- zic.tproj/private.h | 6 +- zic.tproj/scheck.c | 23 +- zic.tproj/zic.c | 348 +- zprint.tproj/zprint.1 | 142 +- zprint.tproj/zprint.c | 119 +- 269 files changed, 11674 insertions(+), 26890 deletions(-) delete mode 100644 CPPUtil/CPPUtil.h delete mode 100644 CPPUtil/UtilAbsInterval.cpp delete mode 100644 CPPUtil/UtilAbsInterval.hpp delete mode 100644 CPPUtil/UtilAbsTime.cpp delete mode 100644 CPPUtil/UtilAbsTime.hpp delete mode 100644 CPPUtil/UtilAssert.hpp delete mode 100644 CPPUtil/UtilBase.hpp delete mode 100644 CPPUtil/UtilException.hpp delete mode 100644 CPPUtil/UtilFileDescriptor.hpp delete mode 100644 CPPUtil/UtilLog.cpp delete mode 100644 CPPUtil/UtilLog.hpp delete mode 100644 CPPUtil/UtilMakeUnique.hpp delete mode 100644 CPPUtil/UtilMappedFile.cpp delete mode 100644 CPPUtil/UtilMappedFile.hpp delete mode 100644 CPPUtil/UtilMemoryBuffer.hpp delete mode 100644 CPPUtil/UtilNanoInterval.hpp delete mode 100644 CPPUtil/UtilNanoTime.cpp delete mode 100644 CPPUtil/UtilNanoTime.hpp delete mode 100644 CPPUtil/UtilPath.cpp delete mode 100644 CPPUtil/UtilPath.hpp delete mode 100644 CPPUtil/UtilPrettyPrinting.cpp delete mode 100644 CPPUtil/UtilPrettyPrinting.hpp delete mode 100644 CPPUtil/UtilString.cpp delete mode 100644 CPPUtil/UtilString.hpp delete mode 100644 CPPUtil/UtilTRange.hpp delete mode 100644 CPPUtil/UtilTRangeValue.hpp delete mode 100644 CPPUtil/UtilTerminalColor.cpp delete mode 100644 CPPUtil/UtilTerminalColor.hpp delete mode 100644 CPPUtil/UtilTime.hpp delete mode 100644 CPPUtil/UtilTimer.cpp delete mode 100644 CPPUtil/UtilTimer.hpp delete mode 100644 KDBG/CPUActivity.hpp delete mode 100644 KDBG/CPUSummary.hpp delete mode 100644 KDBG/IOActivity.hpp delete mode 100644 KDBG/KDBG.cpp delete mode 100644 KDBG/KDBG.hpp delete mode 100644 KDBG/KDCPUMapEntry.hpp delete mode 100644 KDBG/KDEvent.hpp delete mode 100644 KDBG/KDState.hpp delete mode 100644 KDBG/KDThreadMapEntry.hpp delete mode 100644 KDBG/KDebug.h delete mode 100644 KDBG/Kernel.cpp delete mode 100644 KDBG/Kernel.hpp delete mode 100644 KDBG/Machine.hpp delete mode 100644 KDBG/Machine.impl.hpp delete mode 100644 KDBG/Machine.mutable-impl.hpp delete mode 100644 KDBG/MachineCPU.hpp delete mode 100644 KDBG/MachineCPU.impl.hpp delete mode 100644 KDBG/MachineCPU.mutable-impl.hpp delete mode 100644 KDBG/MachineMachMsg.hpp delete mode 100644 KDBG/MachineProcess.hpp delete mode 100644 KDBG/MachineProcess.impl.hpp delete mode 100644 KDBG/MachineProcess.mutable-impl.hpp delete mode 100644 KDBG/MachineThread.hpp delete mode 100644 KDBG/MachineThread.impl.hpp delete mode 100644 KDBG/MachineThread.mutable-impl.hpp delete mode 100644 KDBG/MachineVoucher.hpp delete mode 100644 KDBG/MetaTypes.hpp delete mode 100644 KDBG/NurseryMachMsg.hpp delete mode 100644 KDBG/ProcessSummary.hpp delete mode 100644 KDBG/TaskEffectivePolicy.hpp delete mode 100644 KDBG/TaskRequestedPolicy.hpp delete mode 100644 KDBG/ThreadSummary.hpp delete mode 100644 KDBG/TraceCodes.cpp delete mode 100644 KDBG/TraceCodes.hpp delete mode 100644 KDBG/TraceDataHeader.hpp delete mode 100644 KDBG/TraceFile.cpp delete mode 100644 KDBG/TraceFile.hpp delete mode 100644 KDBG/VoucherInterval.hpp create mode 100644 chkpasswd.tproj/passwd.h delete mode 100644 dynamic_pager.tproj/backing_store_alerts.defs delete mode 100644 dynamic_pager.tproj/backing_store_triggers.defs delete mode 100644 dynamic_pager.tproj/default_pager_alerts.defs create mode 100644 gcore.tproj/corefile.c create mode 100644 gcore.tproj/corefile.h create mode 100644 gcore.tproj/dyld.c create mode 100644 gcore.tproj/dyld.h create mode 100644 gcore.tproj/dyld_shared_cache.c create mode 100644 gcore.tproj/dyld_shared_cache.h create mode 100644 gcore.tproj/gcore.1 create mode 100644 gcore.tproj/loader_additions.h create mode 100644 gcore.tproj/main.c create mode 100644 gcore.tproj/options.h create mode 100644 gcore.tproj/region.h create mode 100644 gcore.tproj/sparse.c create mode 100644 gcore.tproj/sparse.h create mode 100644 gcore.tproj/threads.c create mode 100644 gcore.tproj/threads.h create mode 100644 gcore.tproj/utils.c create mode 100644 gcore.tproj/utils.h create mode 100644 gcore.tproj/vanilla.c create mode 100644 gcore.tproj/vanilla.h create mode 100644 gcore.tproj/vm.c create mode 100644 gcore.tproj/vm.h delete mode 100644 kdprof/Action.hpp delete mode 100644 kdprof/CollectAction.cpp delete mode 100644 kdprof/CollectAction.hpp delete mode 100644 kdprof/DisableAction.cpp delete mode 100644 kdprof/DisableAction.hpp delete mode 100644 kdprof/EnableAction.cpp delete mode 100644 kdprof/EnableAction.hpp delete mode 100644 kdprof/EventPrinting.cpp delete mode 100644 kdprof/EventPrinting.hpp delete mode 100644 kdprof/Globals.cpp delete mode 100644 kdprof/Globals.hpp delete mode 100644 kdprof/InitializeAction.cpp delete mode 100644 kdprof/InitializeAction.hpp delete mode 100644 kdprof/NoWrapAction.cpp delete mode 100644 kdprof/NoWrapAction.hpp delete mode 100644 kdprof/PrintStateAction.cpp delete mode 100644 kdprof/PrintStateAction.hpp delete mode 100644 kdprof/RemoveAction.cpp delete mode 100644 kdprof/RemoveAction.hpp delete mode 100644 kdprof/SaveTraceAction.cpp delete mode 100644 kdprof/SaveTraceAction.hpp delete mode 100644 kdprof/SleepAction.cpp delete mode 100644 kdprof/SleepAction.hpp delete mode 100644 kdprof/SummaryPrinting.cpp delete mode 100644 kdprof/SummaryPrinting.hpp delete mode 100644 kdprof/TraceFileAction.cpp delete mode 100644 kdprof/TraceFileAction.hpp delete mode 100644 kdprof/global.h delete mode 100644 kdprof/kdprof.1 delete mode 100644 kdprof/kdprof.cpp delete mode 100644 makekey.tproj/makekey.8 delete mode 100644 makekey.tproj/makekey.c delete mode 100644 msa/Action.hpp delete mode 100644 msa/EventProcessing.hpp delete mode 100644 msa/EventRingBuffer.hpp delete mode 100644 msa/Globals.cpp delete mode 100644 msa/Globals.hpp delete mode 100644 msa/LiveTraceAction.cpp delete mode 100644 msa/LiveTraceAction.hpp delete mode 100644 msa/PrintBuffer.hpp delete mode 100644 msa/Printing.cpp delete mode 100644 msa/Printing.hpp delete mode 100644 msa/ReadTraceFileAction.cpp delete mode 100644 msa/ReadTraceFileAction.hpp delete mode 100644 msa/VoucherContentSysctl.cpp delete mode 100644 msa/VoucherContentSysctl.hpp delete mode 100644 msa/WriteTraceFileAction.cpp delete mode 100644 msa/WriteTraceFileAction.hpp delete mode 100644 msa/global.h delete mode 100644 msa/main.cpp delete mode 100644 msa/msa.1 create mode 100644 proc_uuid_policy.tproj/proc_uuid_policy.1 create mode 100644 proc_uuid_policy.tproj/proc_uuid_policy.c delete mode 100644 sadc.tproj/sa1.8 delete mode 100644 sadc.tproj/sa1.sh delete mode 100644 sadc.tproj/sa2.8 delete mode 100644 sadc.tproj/sa2.sh delete mode 100644 sadc.tproj/sadc.8 delete mode 100644 sadc.tproj/sadc.c delete mode 100644 sadc.tproj/sadc.h delete mode 100644 sar.tproj/sar.1 delete mode 100644 sar.tproj/sar.c delete mode 100644 sar.tproj/sar.h create mode 100644 wait4path/wait4path.1 create mode 100644 wait4path/wait4path.c create mode 100644 wait4path/wait4path.version create mode 100644 xcconfigs/base.xcconfig create mode 100644 xcconfigs/development.xcconfig create mode 100644 xcconfigs/executable.xcconfig create mode 100644 xcconfigs/wait4path.xcconfig create mode 100644 xscripts/darwinversion.sh diff --git a/CPPUtil/CPPUtil.h b/CPPUtil/CPPUtil.h deleted file mode 100644 index 7ed10da..0000000 --- a/CPPUtil/CPPUtil.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// CPPUtil.h -// CPPUtil -// -// Created by James McIlree on 4/7/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_CPPUtil_h -#define CPPUtil_CPPUtil_h - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace util { - -#include "UtilBase.hpp" -#include "UtilAssert.hpp" -#include "UtilException.hpp" -#include "UtilMakeUnique.hpp" - -#include "UtilPath.hpp" - -#include "UtilTRange.hpp" -#include "UtilTRangeValue.hpp" - -#include "UtilPrettyPrinting.hpp" -#include "UtilTime.hpp" -#include "UtilAbsTime.hpp" -#include "UtilNanoTime.hpp" -#include "UtilAbsInterval.hpp" -#include "UtilNanoInterval.hpp" -#include "UtilTimer.hpp" - -#include "UtilLog.hpp" - -#include "UtilFileDescriptor.hpp" -#include "UtilString.hpp" - -#include "UtilMappedFile.hpp" -#include "UtilMemoryBuffer.hpp" - -#include "UtilTerminalColor.hpp" - -} - -#endif diff --git a/CPPUtil/UtilAbsInterval.cpp b/CPPUtil/UtilAbsInterval.cpp deleted file mode 100644 index 4cb4651..0000000 --- a/CPPUtil/UtilAbsInterval.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// UtilAbsInterval.cpp -// CPPUtil -// -// Created by James McIlree on 9/8/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -const AbsInterval* interval_beginning_timespan(const std::vector& intervals, AbsInterval timespan) { - auto it = std::upper_bound(intervals.begin(), intervals.end(), timespan.location(), AbsIntervalMaxVsAbsTimeComparator()); - - // - // For a beginning interval, there is no possible match if timespan.location() > intervals.back().max() - // - if (it != intervals.end()) { - // - // We found something. Does it contain the search point? - // - if (it->contains(timespan.location())) { - return &*it; - } - - // - // If the AbsInterval found intersects the timespan, its still the first valid vm_fault in - // the given timespan, so return it anyway. - // - if (it->intersects(timespan)) { - return &*it; - } - } - - return NULL; -} - -const AbsInterval* interval_ending_timespan(const std::vector& intervals, AbsInterval timespan) { - - // We could do this as timespan.max() and use lower_bound(...) to save the subtraction. - // But we need the max()-1 value later for the contains() test anyway, so might as well calculate - // it here. - AbsTime max = timespan.max() - AbsTime(1); - auto it = std::upper_bound(intervals.begin(), intervals.end(), max, AbsIntervalMaxVsAbsTimeComparator()); - - // Did we find something? - if (it != intervals.end()) { - - if (it->contains(max)) { - return &*it; - } - - // Okay, the matched interval is to the "right" of us on the - // timeline. Is there a previous interval that might work? - if (it != intervals.begin()) { - if ((--it)->intersects(timespan)) { - return &*it; - } - } - } else { - // Okay, we're off the end of the timeline. There still might - // be a previous interval that would match. - if (!intervals.empty()) { - if ((--it)->intersects(timespan)) { - return &*it; - } - } - } - - return NULL; -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilAbsInterval.hpp b/CPPUtil/UtilAbsInterval.hpp deleted file mode 100644 index 4fe9c31..0000000 --- a/CPPUtil/UtilAbsInterval.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// UtilAbsInterval.h -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilAbsInterval__ -#define __CPPUtil__UtilAbsInterval__ - -typedef TRange AbsInterval; - -struct AbsIntervalLocationVsAbsTimeComparator { - bool operator()(const AbsInterval& activity, const AbsTime& time) const { - return activity.location() < time; - } - - bool operator()(const AbsTime& time, const AbsInterval& activity) const { - return time < activity.location(); - } -}; - -struct AbsIntervalMaxVsAbsTimeComparator { - bool operator()(const AbsInterval& activity, const AbsTime& time) const { - return activity.max() < time; - } - - bool operator()(const AbsTime& time, const AbsInterval& activity) const { - return time < activity.max(); - } -}; - -// -// Takes a vector of sorted non overlapping AbsInterval(s), and a timespan. Returns a pointer to the -// youngest AbsInterval that intersects the timespan. Returns NULL if no interval intersects. -// -// vec: XXXXXXX XXXXXXXX XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXXXX -// -// ---------------------------------- -// -// vec: XXXXXXXX XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXXXXX -// -// ---------------------------------- -// -// vec: XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXX -// -// ---------------------------------- -// -// vec: XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: NULL -// - -const AbsInterval* interval_beginning_timespan(const std::vector& intervals, AbsInterval timespan); - -// -// Takes a vector of sorted non overlapping AbsInterval(s), and a timespan. Returns a pointer to the -// oldest AbsInterval that intersects the timespan. Returns NULL if no interval intersects. -// -// vec: XXXXXXX XXXXXXXX XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXXXX -// -// ---------------------------------- -// -// vec: XXXXXXXX XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXXXXX -// -// ---------------------------------- -// -// vec: XXXXX XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: XXXXX -// -// ---------------------------------- -// -// vec: XXXXXX -// ts: MMMMMMMMMMMMMMM -// ret: NULL -// - -const AbsInterval* interval_ending_timespan(const std::vector& intervals, AbsInterval timespan); - -#endif /* defined(__CPPUtil__UtilAbsInterval__) */ diff --git a/CPPUtil/UtilAbsTime.cpp b/CPPUtil/UtilAbsTime.cpp deleted file mode 100644 index 6c0c0c8..0000000 --- a/CPPUtil/UtilAbsTime.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// UtilAbsTime.cpp -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -const AbsTime AbsTime::BEGINNING_OF_TIME = AbsTime(0ULL); -const AbsTime AbsTime::END_OF_TIME = AbsTime(UINT64_MAX); - -AbsTime AbsTime::now() { - return AbsTime(mach_absolute_time()); -} - -NanoTime AbsTime::nano_time() const { - mach_timebase_info_data_t timebase_info; - mach_timebase_info(&timebase_info); - return NanoTime(_time * timebase_info.numer / timebase_info.denom); -} - -NanoTime AbsTime::nano_time(mach_timebase_info_data_t timebase_info) const { - return NanoTime(_time * timebase_info.numer / timebase_info.denom); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilAbsTime.hpp b/CPPUtil/UtilAbsTime.hpp deleted file mode 100644 index 8fe56b0..0000000 --- a/CPPUtil/UtilAbsTime.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// UtilAbsTime.hpp -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilAbsTime__ -#define __CPPUtil__UtilAbsTime__ - -class NanoTime; - -class AbsTime { - protected: - uint64_t _time; - - public: - // Minimum and Maximum possible values - static const AbsTime BEGINNING_OF_TIME; - static const AbsTime END_OF_TIME; - - static AbsTime now(); - - AbsTime() : _time(0ULL) {} - explicit AbsTime(uint64_t t) : _time(t) {} - - bool operator==(const AbsTime& rhs) const { return this->_time == rhs._time; } - bool operator!=(const AbsTime &rhs) const { return !(*this == rhs); } - - bool operator<(const AbsTime& rhs) const { return this->_time < rhs._time; } - bool operator<=(const AbsTime& rhs) const { return this->_time <= rhs._time; } - bool operator>(const AbsTime& rhs) const { return this->_time > rhs._time; } - bool operator>=(const AbsTime& rhs) const { return this->_time >= rhs._time; } - - // We do not want to be able to mutate AbsTime(s) - // without type enforcement, but it is useful to be able - // to say "if (time == 0) {}", so we have value based - // operators for comparison - bool operator==(uint64_t value) const { return this->_time == value; } - bool operator!=(uint64_t value) const { return !(*this == value); } - - bool operator<(uint64_t value) const { return this->_time < value; } - bool operator<=(uint64_t value) const { return this->_time <= value; } - bool operator>(uint64_t value) const { return this->_time > value; } - bool operator>=(uint64_t value) const { return this->_time >= value; } - - AbsTime operator+(const AbsTime& rhs) const { return AbsTime(_time + rhs._time); } - AbsTime operator-(const AbsTime& rhs) const { return AbsTime(_time - rhs._time); } - AbsTime operator*(const AbsTime& rhs) const { return AbsTime(_time * rhs._time); } - AbsTime operator/(const AbsTime& rhs) const { return AbsTime(_time / rhs._time); } - - AbsTime& operator+=(const AbsTime& rhs) { _time += rhs._time; return *this; } - - NanoTime nano_time() const; // NOTE! Uses system mach_timebase_info, potentially expensive conversion costs. - NanoTime nano_time(mach_timebase_info_data_t timebase_info) const; - - uint64_t value() const { return _time; } - double double_value() const { return (double)_time; } -}; - -#endif /* defined(__CPPUtil__UtilAbsTime__) */ diff --git a/CPPUtil/UtilAssert.hpp b/CPPUtil/UtilAssert.hpp deleted file mode 100644 index f7a0d57..0000000 --- a/CPPUtil/UtilAssert.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Assert.hpp -// CPPUtil -// -// Created by James McIlree on 4/7/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_Assert_hpp -#define CPPUtil_Assert_hpp - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) - - #define DEBUG_ONLY( statement ) statement - - #define ASSERT(e, d) \ - { \ - if (__builtin_expect(!(e), 0)) { \ - ::printf("ASSERT(%s) %s %d, %s\n", #e, util::Path::basename((char*)__FILE__).c_str(), __LINE__, d); \ - std::abort(); \ - } \ - } - - #define SHOULD_NOT_REACH_HERE(d) \ - { \ - ::printf("SHOULD_NOT_REACH_HERE %s %d, %s\n", util::Path::basename((char*)__FILE__).c_str(), __LINE__, d); \ - std::abort(); \ - } - - #define TrueInDebug true - -#else - - #define DEBUG_ONLY( statement ) - #define ASSERT(e, d) - #define SHOULD_NOT_REACH_HERE(d) - - #define TrueInDebug false - -#endif - -#define GUARANTEE(e) \ -{ \ - if (__builtin_expect(!(e), 0)) { \ - ::printf("ASSERT(%s) %s %d\n", #e, util::Path::basename((char*)__FILE__).c_str(), __LINE__); \ - std::abort(); \ - } \ -} - -#endif diff --git a/CPPUtil/UtilBase.hpp b/CPPUtil/UtilBase.hpp deleted file mode 100644 index af03bc9..0000000 --- a/CPPUtil/UtilBase.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// UtilBase.hpp -// CPPUtil -// -// Created by James McIlree on 4/7/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilBase_hpp -#define CPPUtil_UtilBase_hpp - -#define BEGIN_UTIL_NAMESPACE namespace util { -#define END_UTIL_NAMESPACE } - -#endif diff --git a/CPPUtil/UtilException.hpp b/CPPUtil/UtilException.hpp deleted file mode 100644 index 1452eb6..0000000 --- a/CPPUtil/UtilException.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// Exception.hpp -// CPPUtil -// -// Created by James McIlree on 4/7/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_Exception_hpp -#define CPPUtil_Exception_hpp - -class Exception : public std::exception { - protected: - std::string _what; - - public: - Exception(std::string& what) : _what(what) {} ; - virtual ~Exception() throw () {}; - - virtual char const* what() const throw() { return _what.c_str(); } -}; - -#define THROW(e) \ -{ \ - std::ostringstream s; \ - s << e; \ - std::string str = s.str(); \ - Exception exp(str); \ - throw exp; \ -} - -#define UNIMPLEMENTED() THROW("Unimplemented: " << Path((char*)__FILE__).basename() << ":" << __LINE__ ) - -#endif diff --git a/CPPUtil/UtilFileDescriptor.hpp b/CPPUtil/UtilFileDescriptor.hpp deleted file mode 100644 index be861b0..0000000 --- a/CPPUtil/UtilFileDescriptor.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// UtilFileDescriptor.hpp -// CPPUtil -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilFileDescriptor_hpp -#define CPPUtil_UtilFileDescriptor_hpp - -class FileDescriptor { - protected: - int _fd; - - // FD's aren't reference counted, we allow move semantics but - // not copy semantics. Disable the copy constructor and copy - // assignment. - FileDescriptor(const FileDescriptor& that) = delete; - FileDescriptor& operator=(const FileDescriptor& other) = delete; - - public: - - FileDescriptor() : _fd(-1) {} - FileDescriptor(int fd) : _fd(fd) {} - - template - FileDescriptor(Args&& ... args) : - _fd(open(static_cast(args)...)) - { - } - - FileDescriptor (FileDescriptor&& rhs) noexcept : - _fd(rhs._fd) - { - rhs._fd = -1; - } - - ~FileDescriptor() { close(); } - - FileDescriptor& operator=(int fd) { close(); _fd = fd; return *this; } - FileDescriptor& operator=(FileDescriptor&& rhs) { std::swap(_fd, rhs._fd); return *this; } - - bool is_open() const { return _fd > -1 ? true : false; } - void close() { if (is_open()) { ::close(_fd); _fd = -1; } } - - explicit operator bool() const { return is_open(); } - operator int() const { return _fd; } -}; - - -#endif diff --git a/CPPUtil/UtilLog.cpp b/CPPUtil/UtilLog.cpp deleted file mode 100644 index 3d91f67..0000000 --- a/CPPUtil/UtilLog.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// UtilLog.cpp -// CPPUtil -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -void log_msg(int level, const char* format, ...) { - va_list list; - va_start(list, format); - asl_vlog(NULL, NULL, level, format, list); - va_end(list); - - va_start(list, format); - vfprintf(stderr, format, list); - va_end(list); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilLog.hpp b/CPPUtil/UtilLog.hpp deleted file mode 100644 index 1cb2d40..0000000 --- a/CPPUtil/UtilLog.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// UtilLog.h -// CPPUtil -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilLog__ -#define __CPPUtil__UtilLog__ - -void log_msg(int level, const char* format, ...) __attribute__((format(printf, 2, 3))); - -#endif /* defined(__CPPUtil__UtilLog__) */ diff --git a/CPPUtil/UtilMakeUnique.hpp b/CPPUtil/UtilMakeUnique.hpp deleted file mode 100644 index 0be557c..0000000 --- a/CPPUtil/UtilMakeUnique.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// UtilMakeUnique.hpp -// CPPUtil -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilMakeUnique_hpp -#define CPPUtil_UtilMakeUnique_hpp - -/* Not needed in C++14 or later */ -#if __cplusplus <= 201103 - -template -std::unique_ptr make_unique( Args&& ...args ) -{ - return std::unique_ptr( new T( std::forward(args)... ) ); -} - -#endif - -#endif diff --git a/CPPUtil/UtilMappedFile.cpp b/CPPUtil/UtilMappedFile.cpp deleted file mode 100644 index acc71bd..0000000 --- a/CPPUtil/UtilMappedFile.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// UtilMappedFile.cpp -// CPPUtil -// -// Created by James McIlree on 4/19/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -#include - -BEGIN_UTIL_NAMESPACE - -static int open_fd(const char* path, size_t& file_size) -{ - int fd = open(path, O_RDONLY, 0); - if(fd >= 0) { - struct stat data; - if (fstat(fd, &data) == 0) { - if (S_ISREG(data.st_mode)) { - // Is it zero sized? - if (data.st_size > 0) { - file_size = (size_t)data.st_size; - return fd; - } - } - } - close(fd); - } - - return -1; -} - -MappedFile::MappedFile(const char* path) : - _address(NULL), - _size(0) -{ - ASSERT(path, "Sanity"); - int fd = open_fd(path, _size); - if (fd >= 0) { - _address = (unsigned char*)mmap(NULL, _size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); - if (_address == (void*)-1) { - _address = NULL; - } - close(fd); - } -} - -MappedFile::~MappedFile() -{ - if (_address != NULL) { - munmap(_address, _size); - } -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilMappedFile.hpp b/CPPUtil/UtilMappedFile.hpp deleted file mode 100644 index 1494752..0000000 --- a/CPPUtil/UtilMappedFile.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// UtilMappedFile.h -// CPPUtil -// -// Created by James McIlree on 4/19/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilMappedFile__ -#define __CPPUtil__UtilMappedFile__ - -class MappedFile { - protected: - unsigned char* _address; - size_t _size; - - public: - MappedFile(const char* path); - ~MappedFile(); - - uint8_t* address() { return _address; } - size_t size() { return _size; } - - bool mmap_failed() const { return _size > 0 && _address == nullptr; } -}; - -#endif /* defined(__CPPUtil__UtilMappedFile__) */ diff --git a/CPPUtil/UtilMemoryBuffer.hpp b/CPPUtil/UtilMemoryBuffer.hpp deleted file mode 100644 index 1bac915..0000000 --- a/CPPUtil/UtilMemoryBuffer.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// UtilMemoryBuffer.h -// CPPUtil -// -// Created by James McIlree on 4/20/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilMemoryBuffer__ -#define __CPPUtil__UtilMemoryBuffer__ - -template -class MemoryBuffer { - protected: - T* _data; - size_t _capacity; - - // No copying? - MemoryBuffer(const MemoryBuffer& that) = delete; - MemoryBuffer& operator=(const MemoryBuffer& other) = delete; - - public: - // Capacity is in units of T! - // - // MemoryBuffer(1); // 1 byte - // MemoryBuffer(1); // 4 bytes - MemoryBuffer() { _data = NULL; _capacity = 0; } - MemoryBuffer(size_t capacity); - MemoryBuffer(MemoryBuffer&& rhs) noexcept : - _data(rhs._data), - _capacity(rhs._capacity) - { - rhs._data = NULL; - rhs._capacity = 0; - } - - ~MemoryBuffer() { if (_data) { free(_data); } } - - MemoryBuffer& operator=(MemoryBuffer&& rhs) { std::swap(_data, rhs._data); std::swap(_capacity, rhs._capacity); return *this; } - - T* data() { return _data; } - size_t capacity() const { return _capacity; } - size_t capacity_in_bytes() const { return _capacity * sizeof(T); } - // This always results in an allocation and copy. - // If the new capacity is smaller, data is truncated. - void set_capacity(size_t capacity); -}; - -template -MemoryBuffer::MemoryBuffer(size_t capacity) : - _capacity(capacity) -{ - _data = capacity ? (T*)malloc(capacity * sizeof(T)) : (T*)NULL; -} - -template -void MemoryBuffer::set_capacity(size_t capacity) { - MemoryBuffer newbuf(capacity); - memcpy(newbuf.data(), _data, std::min(_capacity * sizeof(T), newbuf.capacity() * sizeof(T))); - *this = std::move(newbuf); -} - -#endif /* defined(__CPPUtil__UtilMemoryBuffer__) */ diff --git a/CPPUtil/UtilNanoInterval.hpp b/CPPUtil/UtilNanoInterval.hpp deleted file mode 100644 index 8a867ca..0000000 --- a/CPPUtil/UtilNanoInterval.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// UtilNanoInterval.h -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilNanoInterval__ -#define __CPPUtil__UtilNanoInterval__ - -typedef TRange NanoInterval; - -#endif /* defined(__CPPUtil__UtilNanoInterval__) */ diff --git a/CPPUtil/UtilNanoTime.cpp b/CPPUtil/UtilNanoTime.cpp deleted file mode 100644 index cae02ae..0000000 --- a/CPPUtil/UtilNanoTime.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// UtilNanoTime.cpp -// CPPUtil -// -// Created by James McIlree on 10/2/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -AbsTime NanoTime::abs_time() const { - mach_timebase_info_data_t timebase_info; - mach_timebase_info(&timebase_info); - return AbsTime(_time * timebase_info.denom / timebase_info.numer); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilNanoTime.hpp b/CPPUtil/UtilNanoTime.hpp deleted file mode 100644 index 990bdf9..0000000 --- a/CPPUtil/UtilNanoTime.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// UtilNanoTime.hpp -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilNanoTime__ -#define __CPPUtil__UtilNanoTime__ - -class NanoTime { - protected: - uint64_t _time; - - public: - NanoTime() : _time(0ULL) {} - NanoTime(uint64_t t) : _time(t) {} - - bool operator==(const NanoTime& rhs) const { return this->_time == rhs._time; } - bool operator!=(const NanoTime &rhs) const { return !(*this == rhs); } - - bool operator<(const NanoTime& rhs) const { return this->_time < rhs._time; } - bool operator<=(const NanoTime& rhs) const { return this->_time <= rhs._time; } - bool operator>(const NanoTime& rhs) const { return this->_time > rhs._time; } - bool operator>=(const NanoTime& rhs) const { return this->_time >= rhs._time; } - - // We do not want to be able to mutate NanoTime(s) - // without type enforcement, but it is useful to be able - // to say "if (time == 0) {}", so we have value based - // operators for comparison - bool operator==(uint64_t value) const { return this->_time == value; } - bool operator!=(uint64_t value) const { return !(*this == value); } - - bool operator<(uint64_t value) const { return this->_time < value; } - bool operator<=(uint64_t value) const { return this->_time <= value; } - bool operator>(uint64_t value) const { return this->_time > value; } - bool operator>=(uint64_t value) const { return this->_time >= value; } - - NanoTime operator+(const NanoTime& rhs) const { return NanoTime(_time + rhs._time); } - NanoTime operator-(const NanoTime& rhs) const { return NanoTime(_time - rhs._time); } - NanoTime operator*(const NanoTime& rhs) const { return NanoTime(_time * rhs._time); } - NanoTime operator/(const NanoTime& rhs) const { return NanoTime(_time / rhs._time); } - - NanoTime& operator+=(const NanoTime& rhs) { _time += rhs._time; return *this; } - - AbsTime abs_time() const; // NOTE! Uses system mach_timebase_info, potentially expensive conversion costs. - AbsTime abs_time(mach_timebase_info_data_t timebase_info) const { - return AbsTime(_time * timebase_info.denom / timebase_info.numer); - } - - uint64_t value() const { return _time; } - double double_value() const { return (double)_time; } -}; - - -#endif /* defined(__CPPUtil__UtilNanoTime__) */ diff --git a/CPPUtil/UtilPath.cpp b/CPPUtil/UtilPath.cpp deleted file mode 100644 index f08ff24..0000000 --- a/CPPUtil/UtilPath.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// UtilPath.inline.hpp -// CPPUtil -// -// Created by James McIlree on 4/8/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -#include - -BEGIN_UTIL_NAMESPACE - -std::string Path::basename(const char* path) { - size_t length = strlen(path); - - /* - * case: "" - * case: "/" - * case: [any-single-character-paths] - */ - if (length < 2) - return std::string(path); - - char temp[PATH_MAX]; - char* temp_cursor = &temp[PATH_MAX - 1]; - char* temp_end = temp_cursor; - *temp_end = 0; // NULL terminate - - const char* path_cursor = &path[length-1]; - - while (path_cursor >= path) { - if (*path_cursor == '/') { - // If we have copied one or more chars, we're done - if (temp_cursor != temp_end) - return std::string(temp_cursor); - } else { - *(--temp_cursor) = *path_cursor; - } - - // Is the temp buffer full? - if (temp_cursor == temp) - return std::string(temp); - - --path_cursor; - } - - if (path[0] == '/' && temp_cursor == temp_end) { - *(--temp_cursor) = '/'; - } - - return std::string(temp_cursor); -} - -std::string Path::basename(std::string& path) { - return basename(path.c_str()); -} - -bool Path::exists(const char *path) { - struct stat statinfo; - return lstat(path, &statinfo) == 0; -} - -bool Path::exists(std::string& path) { - return exists(path.c_str()); -} - -bool Path::is_file(const char* path, bool should_resolve_symlinks) { - struct stat statinfo; - if (should_resolve_symlinks) { - if (stat(path, &statinfo) == 0) { - if (S_ISREG(statinfo.st_mode)) { - return true; - } - } - } else { - if (lstat(path, &statinfo) == 0) { - if (S_ISREG(statinfo.st_mode)) { - return true; - } - } - } - - return false; -} - -bool Path::is_file(std::string& path, bool should_resolve_symlinks) { - return is_file(path.c_str(), should_resolve_symlinks); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilPath.hpp b/CPPUtil/UtilPath.hpp deleted file mode 100644 index 6eb2bb9..0000000 --- a/CPPUtil/UtilPath.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// UtilPath.hpp -// CPPUtil -// -// Created by James McIlree on 4/8/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilPath_hpp -#define CPPUtil_UtilPath_hpp - -class Path { - public: - /* - * INPUT OUTPUT - * - * /tmp/scratch.tiff scratch.tiff - * /tmp/scratch scratch - * /tmp/ tmp - * scratch scratch - * /mach_kernel mach_kernel - * / / - */ - static std::string basename(const char* path); - static std::string basename(std::string& path); - - static bool exists(const char* path); - static bool exists(std::string& path); - - static bool is_file(const char* path, bool should_resolve_symlinks); - static bool is_file(std::string& path, bool should_resolve_symlinks); -}; - -#endif diff --git a/CPPUtil/UtilPrettyPrinting.cpp b/CPPUtil/UtilPrettyPrinting.cpp deleted file mode 100644 index 00c1ea0..0000000 --- a/CPPUtil/UtilPrettyPrinting.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// UtilPrettyPrinting.cpp -// CPPUtil -// -// Created by James McIlree on 9/8/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -std::string formated_byte_size(uint64_t bytes) { - if (bytes) { - char tmp[128]; - const char *si_prefix[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; - const int base = 1024; - int c = std::min((int)(log((double)bytes)/log((double)base)), (int)sizeof(si_prefix) - 1); - snprintf(tmp, sizeof(tmp), "%1.2f %s", bytes / pow((double)base, c), si_prefix[c]); - return std::string(tmp); - } - - return std::string("0.00 B"); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilPrettyPrinting.hpp b/CPPUtil/UtilPrettyPrinting.hpp deleted file mode 100644 index c27fb96..0000000 --- a/CPPUtil/UtilPrettyPrinting.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// UtilPrettyPrinting.h -// CPPUtil -// -// Created by James McIlree on 9/8/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilPrettyPrinting__ -#define __CPPUtil__UtilPrettyPrinting__ - -std::string formated_byte_size(uint64_t bytes); - -#endif /* defined(__CPPUtil__UtilPrettyPrinting__) */ diff --git a/CPPUtil/UtilString.cpp b/CPPUtil/UtilString.cpp deleted file mode 100644 index 80d5cc3..0000000 --- a/CPPUtil/UtilString.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// -// UtilString.cpp -// CPPUtil -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -bool ends_with(std::string& str, std::string postfix) { - size_t pos = str.rfind(postfix); - return ((pos != std::string::npos) && (pos == (str.length() - postfix.length()))); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilString.hpp b/CPPUtil/UtilString.hpp deleted file mode 100644 index 8580163..0000000 --- a/CPPUtil/UtilString.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// UtilString.hpp -// CPPUtil -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilString_hpp -#define CPPUtil_UtilString_hpp - -struct ConstCharHash { - // - // Okay, by design std::hash hashes on the pointer, - // not the contents of that pointer. - // - // The C++11 std::hash hash works, but must - // construct a copy of the passed in string to hash. - // - // That's 3x slower than this, minimum. - // - // This is just the __gnu_cxx hash code inlined. - // - std::size_t operator()(const char* __s) const { - unsigned long __h = 0; - for ( ; *__s; ++__s) - __h = 5 * __h + *__s; - return size_t(__h); - }; - -}; - -struct ConstCharEqualTo { - bool operator() (const char* s1, const char* s2) const { - return strcmp(s1, s2) == 0; - } -}; - -bool ends_with(std::string& str, std::string postfix); - -#endif diff --git a/CPPUtil/UtilTRange.hpp b/CPPUtil/UtilTRange.hpp deleted file mode 100644 index 49daf4e..0000000 --- a/CPPUtil/UtilTRange.hpp +++ /dev/null @@ -1,254 +0,0 @@ -// -// UtilTRange.hpp -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilTRange_hpp -#define CPPUtil_UtilTRange_hpp - -template -class TRange { - protected: - T _location; - T _length; - - public: - TRange() : _location(0), _length(0) {} - TRange(T location, T length) : _location(location), _length(length) { - DEBUG_ONLY(validate()); - }; - - bool operator==(const TRange &rhs) const { return this->_location == rhs.location() && this->_length == rhs.length(); } - - bool operator!=(const TRange &rhs) const { return !(*this == rhs); } - - bool operator<(const TRange& rhs) const { return this->_location < rhs.location(); } - bool operator<(const TRange* rhs) const { return this->_location < rhs->location(); } - - const T location() const { return _location; } - const T length() const { return _length; } - const T max() const { return _location + _length; } - - void set_location(T location) { _location = location; DEBUG_ONLY(validate()); } - void set_length(T length) { _length = length; DEBUG_ONLY(validate()); } - void set_max(T max) { ASSERT(max >= _location, "Sanity"); _length = max - _location; } - - const bool contains(const TRange& other) const { return (other.location() >= location()) && (other.max() <= max()); } - const bool contains(const T loc) const { return loc - _location < _length; } // Assumes unsigned! - - const bool intersects(const TRange& o) const { return this->location() < o.max() && o.location() < this->max(); } - - // "union" is a keyword :-( - TRange union_range(const TRange& other) const { - T maxend = (this->max() > other.max()) ? this->max() : other.max(); - T minloc = this->location() < other.location() ? this->location() : other.location(); - return TRange(minloc, maxend - minloc); - } - - TRange intersection_range(const TRange& other) const { - if (this->intersects(other)) { - auto intersection_start = std::max(_location, other.location()); - auto intersection_end = std::min(max(), other.max()); - return TRange(intersection_start, intersection_end - intersection_start); - } - - return TRange(T(0),T(0)); - } - - void validate() const { ASSERT((_location + _length >= _location) /*|| (_location + 1 == 0)*/, "range must not wrap"); } -}; - -template -bool is_trange_vector_sorted_and_non_overlapping(const std::vector& vec) { - if (vec.size() > 1) { - auto last_it = vec.begin(); - auto it = last_it + 1; - - while (it < vec.end()) { - if (it < last_it) - return false; - - if (last_it->intersects(*it)) - return false; - - last_it = it; - it++; - } - } - return true; -} - -template -bool is_trange_vector_sorted(const std::vector& vec) { - if (vec.size() > 1) { - auto last_it = vec.begin(); - auto it = last_it + 1; - - while (it < vec.end()) { - if (it < last_it) - return false; - - last_it = it; - it++; - } - } - return true; -} - -// NOTE! -// -// This produces an output vector with the -// intervals "flattened". -// -// IOW, this: -// -// vec1: XXXXXXXX AAAAAAAAAA -// YYYYYYYYYYY ZZZZZZZZZ -// -// becomes: -// -// res: IIIIIIIIIIII IIIIIIIIIIII -// -// The input vector should be sorted. -// -template -std::vector trange_vector_union(std::vector& input) { - std::vector union_vec; - - ASSERT(is_trange_vector_sorted(input), "Sanity"); - - if (!input.empty()) { - auto input_it = input.begin(); - union_vec.push_back(*input_it); - while (++input_it < input.end()) { - TRANGE union_range = union_vec.back(); - - if (union_range.intersects(*input_it)) { - union_vec.pop_back(); - union_vec.push_back(union_range.union_range(*input_it)); - } else { - ASSERT(union_range < *input_it, "Out of order merging"); - union_vec.push_back(*input_it); - } - } - } - - ASSERT(is_trange_vector_sorted_and_non_overlapping(union_vec), "union'd vector fails invariant"); - - return union_vec; -} - -// NOTE! -// -// This will coalesce intervals that intersect. -// -// IOW, given two input vectors: -// -// vec1: XXXX XXXX -// vec2: XXX -// -// res: XXXX XXX XXXX -// -// -------------------------------- -// -// vec1: XXXX XX -// vec2: XXXXXXXXXXXXXXX -// -// res: XXXXXXXXXXXXXXXXX - -template -std::vector trange_vector_union(std::vector& vec1, std::vector& vec2) { - std::vector union_vec; - - ASSERT(is_trange_vector_sorted_and_non_overlapping(vec1), "input vector violates invariants"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(vec2), "input vector violates invariants"); - - // while (not done) - // select next interval (lowest location) - // if intersects with last union_vec entry, union, pop_back, push_back - // else push_back - - auto vec1_it = vec1.begin(); - auto vec2_it = vec2.begin(); - - while (uint32_t chose_vector = (((vec1_it != vec1.end()) ? 1 : 0) + ((vec2_it != vec2.end()) ? 2 : 0))) { - // - // This is a fancy "chose" algorithm - // - // vec1 == bit 1 - // vec2 == bit 2 - // - decltype(vec1_it) merge_it; - switch (chose_vector) { - case 1: - merge_it = vec1_it++; - break; - - case 2: - merge_it = vec2_it++; - break; - - case 3: - merge_it = (*vec1_it < * vec2_it) ? vec1_it++ : vec2_it++; - break; - - default: - ASSERT(false, "ShouldNotReachHere"); - return std::vector(); - } - - if (union_vec.empty()) { - union_vec.push_back(*merge_it); - } else { - TRANGE last_range = union_vec.back(); - - if (last_range.intersects(*merge_it)) { - union_vec.pop_back(); - union_vec.push_back(last_range.union_range(*merge_it)); - } else { - ASSERT(last_range < *merge_it, "Out of order merging"); - union_vec.push_back(*merge_it); - } - } - } - - ASSERT(is_trange_vector_sorted_and_non_overlapping(union_vec), "union'd vector fails invariant"); - - return union_vec; -} - -template -std::vector trange_vector_intersect(std::vector& vec1, std::vector& vec2) { - std::vector intersect_vec; - - ASSERT(is_trange_vector_sorted_and_non_overlapping(vec1), "input vector violates invariants"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(vec2), "input vector violates invariants"); - - auto vec1_it = vec1.begin(); - auto vec2_it = vec2.begin(); - - // As soon as one vector empties, there can be no more intersections - while (vec1_it != vec1.end() && vec2_it != vec2.end()) { - TRANGE temp = vec1_it->intersection_range(*vec2_it); - if (temp.length() > 0) { - intersect_vec.push_back(temp); - } - - // We keep the interval that ends last - - if (vec1_it->max() > vec2_it->max()) { - vec2_it++; - } else { - vec1_it++; - } - } - - ASSERT(is_trange_vector_sorted_and_non_overlapping(intersect_vec), "intersection vector fails invariant"); - - return intersect_vec; -} - -#endif diff --git a/CPPUtil/UtilTRangeValue.hpp b/CPPUtil/UtilTRangeValue.hpp deleted file mode 100644 index 7b50b73..0000000 --- a/CPPUtil/UtilTRangeValue.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// UtilTRangeValue.hpp -// CPPUtil -// -// Created by James McIlree on 12/10/07. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilTRangeValue_hpp -#define CPPUtil_UtilTRangeValue_hpp - -template -class TRangeValue : public TRange { - protected: - T2 _value; - - public: - TRangeValue(T1 location, T1 length, T2 value) : TRange(location, length), _value(value) { }; - - const T2 value() const { return _value; } - - // Sometimes we need to reference the value as a mutable reference (think std::vector types) - T2& mutable_value() { return _value; } -}; - -#endif diff --git a/CPPUtil/UtilTerminalColor.cpp b/CPPUtil/UtilTerminalColor.cpp deleted file mode 100644 index d7d42ca..0000000 --- a/CPPUtil/UtilTerminalColor.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// UtilTerminalColor.cpp -// CPPUtil -// -// Created by James McIlree on 4/26/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" - -#define ALLCOLORS(FGBG,BOLD) {\ - COLOR(FGBG, "0", BOLD),\ - COLOR(FGBG, "1", BOLD),\ - COLOR(FGBG, "2", BOLD),\ - COLOR(FGBG, "3", BOLD),\ - COLOR(FGBG, "4", BOLD),\ - COLOR(FGBG, "5", BOLD),\ - COLOR(FGBG, "6", BOLD),\ - COLOR(FGBG, "7", BOLD)\ -} - -static const char colorcodes[2][2][8][10] = { - { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, - { ALLCOLORS("4",""), ALLCOLORS("4","1;") } -}; - -const char* TerminalColorStringFor(kTerminalColor code, bool is_bold, bool is_background) { - return colorcodes[is_background ? 1 : 0][is_bold ? 1 : 0][(uint32_t)code & 7]; -} - -const char* TerminalColorResetString(void) { - return "\033[0m"; -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilTerminalColor.hpp b/CPPUtil/UtilTerminalColor.hpp deleted file mode 100644 index c5eee39..0000000 --- a/CPPUtil/UtilTerminalColor.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// UtilTerminalColor.hpp -// CPPUtil -// -// Created by James McIlree on 4/26/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilTerminalColor_hpp -#define CPPUtil_UtilTerminalColor_hpp - -// This is borrowed from clang - -enum class kTerminalColor : std::uint32_t { - BLACK=0, - RED, - GREEN, - YELLOW, - BLUE, - MAGENTA, - CYAN, - WHITE -}; - -const char* TerminalColorStringFor(kTerminalColor code, bool is_bold, bool is_background); -const char* TerminalColorResetString(void); - -#endif diff --git a/CPPUtil/UtilTime.hpp b/CPPUtil/UtilTime.hpp deleted file mode 100644 index 6662db3..0000000 --- a/CPPUtil/UtilTime.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// UtilTime.hpp -// CPPUtil -// -// Created by James McIlree on 4/14/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef CPPUtil_UtilTime_hpp -#define CPPUtil_UtilTime_hpp - -static const uint64_t NANOSECONDS_PER_MICROSECOND = 1000ULL; -static const uint64_t NANOSECONDS_PER_MILLISECOND = 1000000ULL; -static const uint64_t NANOSECONDS_PER_SECOND = 1000000000ULL; - -static const uint64_t MICROSECONDS_PER_MILLISECOND = 1000ULL; -static const uint64_t MICROSECONDS_PER_SECOND = 1000000ULL; - -static const uint64_t MILLISECONDS_PER_SECOND = 1000ULL; - -#endif diff --git a/CPPUtil/UtilTimer.cpp b/CPPUtil/UtilTimer.cpp deleted file mode 100644 index b285565..0000000 --- a/CPPUtil/UtilTimer.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// UtilTimer.cpp -// CPPUtil -// -// Created by James McIlree on 10/9/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "CPPUtil.h" - -BEGIN_UTIL_NAMESPACE - -static mach_timebase_info_data_t timebase_info; - -Timer::Timer(const char* message) : _message(message) { - // C++ guarantees that static variable initialization is thread safe. - // We don't actually care what the returned value is, we just want to init timebase_info - // The pragma prevents spurious warnings. - static kern_return_t blah = mach_timebase_info(&timebase_info); -#pragma unused(blah) - - _start = AbsTime::now(); // Do this after the initialization check. -} - -Timer::~Timer() -{ - _end = AbsTime::now(); - printf("%s: %5.5f seconds\n", _message.c_str(), (double)(_end - _start).nano_time().value() / (double)NANOSECONDS_PER_SECOND); -} - -END_UTIL_NAMESPACE diff --git a/CPPUtil/UtilTimer.hpp b/CPPUtil/UtilTimer.hpp deleted file mode 100644 index 4247eab..0000000 --- a/CPPUtil/UtilTimer.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// UtilTimer.h -// CPPUtil -// -// Created by James McIlree on 10/9/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __CPPUtil__UtilTimer__ -#define __CPPUtil__UtilTimer__ - -class Timer { - protected: - AbsTime _start; - AbsTime _end; - std::string _message; - - public: - Timer(const char* message); - ~Timer(); -}; - -#endif /* defined(__CPPUtil__UtilTimer__) */ diff --git a/KDBG/CPUActivity.hpp b/KDBG/CPUActivity.hpp deleted file mode 100644 index fb20c01..0000000 --- a/KDBG/CPUActivity.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// CPUActivity.hpp -// KDBG -// -// Created by James McIlree on 4/22/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_CPUActivity_hpp -#define kdprof_CPUActivity_hpp - -// NOTE! Counted, not bits! -enum class kCPUActivity : uint32_t { - Unknown = 0x00000001, - Idle = 0x00000002, - INTR = 0x00000003, - Run = 0x00000004 // *MUST* be the last definition. See "is_run()" -}; - -template -class CPUActivity : public AbsInterval { - - // Declaring this a union to make the behavior clearer. - // - // If _type > kCPUActivity::Run, the _thread portion of - // the union is valid, the _type is coonsider to be Run. - // - // However, if the _thread is valid, the low order bit of - // the thread indicates if this was a context switch. - // - // So: - // - // 0000000X == _type; - // XXXXXXX[0/1] == _thread; - - union { - MachineThread* thread; - uintptr_t type; - } _u; - - enum { - kCPUActivityRunIsContextSwitch = 0x1 - }; - - public: - CPUActivity(kCPUActivity type, AbsInterval interval) : - AbsInterval(interval) - { - ASSERT(type != kCPUActivity::Run, "Cannot be Run without a thread"); - _u.type = (uintptr_t)type; - } - - CPUActivity(MachineThread* thread, AbsInterval interval, bool is_cntx_swtch) : - AbsInterval(interval) - { - _u.thread = thread; - if (is_cntx_swtch) - _u.type |= kCPUActivityRunIsContextSwitch; - - ASSERT(is_run(), "Sanity"); - ASSERT(is_context_switch() == is_cntx_swtch, "Sanity"); - } - - // We can safely assume that the memory system will never allocate - // a thread in the first page of memory. - bool is_run() const { return _u.type > (uintptr_t)kCPUActivity::Run; } - bool is_idle() const { return _u.type == (uintptr_t)kCPUActivity::Idle; } - bool is_intr() const { return _u.type == (uintptr_t)kCPUActivity::INTR; } - bool is_unknown() const { return _u.type == (uintptr_t)kCPUActivity::Unknown; } - - bool is_context_switch() const { - if (is_run() && (_u.type & kCPUActivityRunIsContextSwitch)) - return true; - return false; - } - - kCPUActivity type() const { - if (_u.type > (uintptr_t)kCPUActivity::Run) - return kCPUActivity::Run; - - return (kCPUActivity)_u.type; - } - - const MachineThread* thread() const { - ASSERT(is_run(), "Sanity"); - return (MachineThread* )((uintptr_t)_u.thread & ~kCPUActivityRunIsContextSwitch); - } -}; - -#endif diff --git a/KDBG/CPUSummary.hpp b/KDBG/CPUSummary.hpp deleted file mode 100644 index eaafb65..0000000 --- a/KDBG/CPUSummary.hpp +++ /dev/null @@ -1,353 +0,0 @@ -// -// CPUSummary.hpp -// KDBG -// -// Created by James McIlree on 4/22/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_CPUSummary_hpp -#define kdprof_CPUSummary_hpp - -template -class MachineCPU; - -template -class CPUSummary { - private: - // Disallow copy constructor to make sure that the compiler - // is moving these, instead of copying them when we pass around - CPUSummary(const CPUSummary& that) = delete; - CPUSummary& operator=(const CPUSummary& other) = delete; - - friend class Machine; - - public: - typedef std::unordered_set, ProcessSummaryHash, ProcessSummaryEqualTo> ProcessSummarySet; - typedef std::unordered_set*> CPUSummaryMachineCPUSet; - - protected: - AbsTime _total_unknown_time; - AbsTime _total_run_time; - AbsTime _total_idle_time; - AbsTime _total_intr_time; - AbsTime _total_future_run_time; - AbsTime _total_wallclock_run_time; - AbsTime _total_all_cpus_idle_time; - AbsTime _total_vm_fault_time; - AbsTime _total_io_time; - AbsTime _total_jetsam_time; - - uint32_t _context_switch_count; - uint32_t _count_idle_events; - uint32_t _count_intr_events; - uint32_t _count_vm_fault_events; - uint32_t _count_io_events; - uint32_t _count_processes_jetsamed; - uint32_t _active_cpus; - - uint64_t _io_bytes_completed; - - CPUSummaryMachineCPUSet _cpus; - ProcessSummarySet _process_summaries; - - std::vector _wallclock_run_intervals; // This is the actual wallclock run interval data. - std::vector _per_cpu_wallclock_run_intervals; // We need to accumulate intervals during summary generation, this is a temp buffer. - - bool _should_merge_all_cpus_idle_intervals; - std::vector _all_cpus_idle_intervals; - std::vector _per_cpu_all_cpus_idle_intervals; - - void add_unknown_time(AbsTime time) { _total_unknown_time += time; } - void add_run_time(AbsTime time) { _total_run_time += time; } - void add_idle_time(AbsTime time) { _total_idle_time += time; _count_idle_events++; } - void add_intr_time(AbsTime time) { _total_intr_time += time; _count_intr_events++; } - void add_future_run_time(AbsTime time) { _total_future_run_time += time; } - void add_vm_fault_time(AbsTime time) { _total_vm_fault_time += time; _count_vm_fault_events++; } - void add_io_time(AbsTime time) { _total_io_time += time; _count_io_events++; } // We want to bump the event count on all IO activity, not just on completion - void add_jetsam_time(AbsTime time) { _total_jetsam_time += time; } - - void add_io_bytes_completed(typename SIZE::ptr_t bytes) { _io_bytes_completed += bytes; } - - void increment_processes_jetsamed() { _count_processes_jetsamed++; } - - // - // NOTE! Why are the various interval(s) accumulated one cpu at a time, - // instead of storing them all in a single vector, sorting it and processing - // once at the end? - // - // The single vector, sort and postprocess would work for wallclock time - // calculation, because wallclock times involve "union" operations where - // the number of cpu(s) don't matter. - // - // However, for the all-idle and idle-while-wating-on-IO calculations, we - // need "intersects" operations, I.E. all 16 cores need to be idle to count - // as "all-idle". In this mode, the number of cores matters, an intersection - // requires all 16 cores to simultaneously be the same state. This is difficult - // to calculate with more than 2 sources. By calculating one at a time, - // that is avoided, the state remains sanity-checkable throughout. - // - - - // - // Wallclock run intervals are added as each cpu timeline is walked. - // Between cpu(s), the results are accumulated to a single buffer - // After all cpus have been processed, the single buffer is summarized - // - // wallclock run time is the *union* of cpu run intervals. - // - void add_wallclock_run_interval(AbsInterval interval); - void accumulate_wallclock_run_intervals(); - void summarize_wallclock_run_intervals(); - - // - // all cpus idle intervals are added as each cpu timeline is walked. - // Between cpu(s), the results are accumulated to a single buffer - // After all cpus have been processed, the single buffer is summarized. - // - // all cpus idle time is the *intersection* of cpu idle intervals - // - void add_all_cpus_idle_interval(AbsInterval interval); - void accumulate_all_cpus_idle_intervals(); - void summarize_all_cpus_idle_intervals(); - - void incr_context_switches() { _context_switch_count++; } - void incr_active_cpus() { _active_cpus++; } - - // These bracket individual cpu timeline walks - void begin_cpu_timeline_walk(const MachineCPU* cpu); - void end_cpu_timeline_walk(const MachineCPU* cpu); - - // These bracket all cpu timeline walks - void begin_cpu_timeline_walks(void); - void end_cpu_timeline_walks(void); - - ProcessSummary* mutable_process_summary(const MachineProcess* process) { - auto it = _process_summaries.find(process); - if (it == _process_summaries.end()) { - // We create any process summary that is missing. - auto insert_result = _process_summaries.emplace(process); - ASSERT(insert_result.second, "Sanity"); - it = insert_result.first; - } - - // NOTE! Because we are using a Set instead of a Map, STL wants - // the objects to be immutable. "it" refers to a const Record, to - // prevent us from changing the hash or equality of the Set. We - // know that the allowed set of mutations will not change these, - // and so we evil hack(tm) and cast away the const'ness. - return const_cast*>(&*it); - } - - ProcessSummarySet& mutable_process_summaries() { return _process_summaries; } - - public: - CPUSummary() : - _context_switch_count(0), - _count_idle_events(0), - _count_intr_events(0), - _count_vm_fault_events(0), - _count_io_events(0), - _count_processes_jetsamed(0), - _active_cpus(0), - _io_bytes_completed(0), - _should_merge_all_cpus_idle_intervals(false) - { - } - - CPUSummary (CPUSummary&& rhs) noexcept : - _total_unknown_time(rhs._total_unknown_time), - _total_run_time(rhs._total_run_time), - _total_idle_time(rhs._total_idle_time), - _total_intr_time(rhs._total_intr_time), - _total_future_run_time(rhs._total_future_run_time), - _total_wallclock_run_time(rhs._total_wallclock_run_time), - _total_all_cpus_idle_time(rhs._total_all_cpus_idle_time), - _total_vm_fault_time(rhs._total_vm_fault_time), - _total_io_time(rhs._total_io_time), - _context_switch_count(rhs._context_switch_count), - _count_idle_events(rhs._count_idle_events), - _count_intr_events(rhs._count_intr_events), - _count_vm_fault_events(rhs._count_vm_fault_events), - _count_io_events(rhs._count_io_events), - _count_processes_jetsamed(rhs._count_processes_jetsamed), - _active_cpus(rhs._active_cpus), - _io_bytes_completed(rhs._io_bytes_completed), - _cpus(rhs._cpus), - _process_summaries(rhs._process_summaries), - // _wallclock_run_intervals - // _per_cpu_wallclock_run_intervals - _should_merge_all_cpus_idle_intervals(false) - // _all_cpus_idle_intervals - // _per_cpu_all_cpus_idle_intervals - // _wallclock_vm_fault_intervals - // _wallclock_pgin_intervals - // _wallclock_disk_read_intervals - { - ASSERT(rhs._all_cpus_idle_intervals.empty(), "Sanity"); - ASSERT(rhs._per_cpu_all_cpus_idle_intervals.empty(), "Sanity"); - ASSERT(rhs._wallclock_run_intervals.empty(), "Sanity"); - ASSERT(rhs._per_cpu_wallclock_run_intervals.empty(), "Sanity"); - ASSERT(rhs._should_merge_all_cpus_idle_intervals == false, "Sanity"); - } - - AbsTime total_time() const { return _total_unknown_time + _total_run_time + _total_idle_time + _total_intr_time; } - - AbsTime total_unknown_time() const { return _total_unknown_time; } - AbsTime total_run_time() const { return _total_run_time; } - AbsTime total_idle_time() const { return _total_idle_time; } - AbsTime total_intr_time() const { return _total_intr_time; } - AbsTime total_future_run_time() const { return _total_future_run_time; } - AbsTime total_wallclock_run_time() const { return _total_wallclock_run_time; } - AbsTime total_all_cpus_idle_time() const { return _total_all_cpus_idle_time; } - AbsTime total_vm_fault_time() const { return _total_vm_fault_time; } - AbsTime total_io_time() const { return _total_io_time; } - AbsTime total_jetsam_time() const { return _total_jetsam_time; } - - AbsTime avg_on_cpu_time() const { return _total_run_time / _context_switch_count; } - - uint32_t context_switches() const { return _context_switch_count; } - uint32_t num_idle_events() const { return _count_idle_events; } - uint32_t num_intr_events() const { return _count_intr_events; } - uint32_t num_vm_fault_events() const { return _count_vm_fault_events; } - uint32_t num_io_events() const { return _count_io_events; } - uint32_t num_processes_jetsammed() const { return _count_processes_jetsamed; } - - uint32_t active_cpus() const { return _active_cpus; } - - uint64_t io_bytes_completed() const { return _io_bytes_completed; } - - - // A CPUSummary may be a summary of one or more CPUs. - // The cpus set are the MachineCPU(s) that were used to - // construct this summary. - const CPUSummaryMachineCPUSet& cpus() const { return _cpus; } - - const ProcessSummarySet& process_summaries() const { return _process_summaries; } - const ProcessSummary* process_summary(const MachineProcess* process) const { - auto it = _process_summaries.find(process); - return (it == _process_summaries.end()) ? NULL : &*it; - } - - DEBUG_ONLY(void validate() const;) -}; - -template -void CPUSummary::begin_cpu_timeline_walks() { - _should_merge_all_cpus_idle_intervals = true; -} - -template -void CPUSummary::begin_cpu_timeline_walk(const MachineCPU* cpu) { - ASSERT(cpu, "Sanity"); - _cpus.emplace(cpu); -} - -template -void CPUSummary::end_cpu_timeline_walk(const MachineCPU* cpu) { - ASSERT(cpu, "Sanity"); - - accumulate_wallclock_run_intervals(); - accumulate_all_cpus_idle_intervals(); -} - -template -void CPUSummary::end_cpu_timeline_walks(void) { - summarize_wallclock_run_intervals(); - summarize_all_cpus_idle_intervals(); -} - -template -void CPUSummary::add_wallclock_run_interval(AbsInterval interval) { - ASSERT(_per_cpu_wallclock_run_intervals.empty() || (_per_cpu_wallclock_run_intervals.back() < interval && !interval.intersects(_per_cpu_wallclock_run_intervals.back())), "Invariant violated"); - _per_cpu_wallclock_run_intervals.emplace_back(interval); -} - -template -void CPUSummary::accumulate_wallclock_run_intervals() { - _wallclock_run_intervals = trange_vector_union(_wallclock_run_intervals, _per_cpu_wallclock_run_intervals); - _per_cpu_wallclock_run_intervals.clear(); - // We don't shrink_to_fit here as its expected another CPU's run intervals will be processed next. - - for (auto& process_summary : _process_summaries) { - // NOTE! Because we are using a Set instead of a Map, STL wants - // the objects to be immutable. We know that the operations being - // invoked will not change the hash, but we still must throw away - // the const'ness. Care must be taken to avoid the construction of - // temporary objects, thus the use of pointers... - const_cast*>(&process_summary)->accumulate_wallclock_run_intervals(); - } -} - -template -void CPUSummary::summarize_wallclock_run_intervals() { - ASSERT(_per_cpu_wallclock_run_intervals.empty(), "Sanity"); - _per_cpu_wallclock_run_intervals.shrink_to_fit(); - - ASSERT(_total_wallclock_run_time == 0, "Called more than once"); - - ASSERT(is_trange_vector_sorted_and_non_overlapping(_wallclock_run_intervals), "Sanity"); - - for (auto& interval : _wallclock_run_intervals) { - _total_wallclock_run_time += interval.length(); - } - - _wallclock_run_intervals.clear(); - _wallclock_run_intervals.shrink_to_fit(); - - for (auto& process_summary : _process_summaries) { - // NOTE! Because we are using a Set instead of a Map, STL wants - // the objects to be immutable. We know that the operations being - // invoked will not change the hash, but we still must throw away - // the const'ness. Care must be taken to avoid the construction of - // temporary objects, thus the use of pointers... - const_cast*>(&process_summary)->summarize_wallclock_run_intervals(); - } -} - -template -void CPUSummary::add_all_cpus_idle_interval(AbsInterval interval) { - ASSERT(_per_cpu_all_cpus_idle_intervals.empty() || (_per_cpu_all_cpus_idle_intervals.back() < interval && !interval.intersects(_per_cpu_all_cpus_idle_intervals.back())), "Invariant violated"); - _per_cpu_all_cpus_idle_intervals.emplace_back(interval); -} - -template -void CPUSummary::accumulate_all_cpus_idle_intervals() { - if (_should_merge_all_cpus_idle_intervals) { - _should_merge_all_cpus_idle_intervals = false; - _all_cpus_idle_intervals = _per_cpu_all_cpus_idle_intervals; - } else { - _all_cpus_idle_intervals = trange_vector_intersect(_all_cpus_idle_intervals, _per_cpu_all_cpus_idle_intervals); - } - _per_cpu_all_cpus_idle_intervals.clear(); -} - -template -void CPUSummary::summarize_all_cpus_idle_intervals() { - ASSERT(!_should_merge_all_cpus_idle_intervals, "Sanity"); - ASSERT(_per_cpu_all_cpus_idle_intervals.empty(), "Sanity"); - ASSERT(_total_all_cpus_idle_time == 0, "Called more than once"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(_all_cpus_idle_intervals), "Sanity"); - - _per_cpu_all_cpus_idle_intervals.shrink_to_fit(); - for (auto& interval : _all_cpus_idle_intervals) { - _total_all_cpus_idle_time += interval.length(); - } - - _all_cpus_idle_intervals.clear(); - _all_cpus_idle_intervals.shrink_to_fit(); -} - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void CPUSummary::validate() const { - ASSERT(_total_wallclock_run_time <= _total_run_time, "Sanity"); - ASSERT(_total_all_cpus_idle_time <= _total_idle_time, "Sanity"); - - for (const auto& process_summary : _process_summaries) { - process_summary.validate(); - } -} -#endif - -#endif diff --git a/KDBG/IOActivity.hpp b/KDBG/IOActivity.hpp deleted file mode 100644 index caa0264..0000000 --- a/KDBG/IOActivity.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// IOActivity.hpp -// KDBG -// -// Created by James McIlree on 9/2/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_IOActivity_hpp -#define kdprof_IOActivity_hpp - -template -class IOActivity : public TRange { - private: - MachineThread* _thread; - typename SIZE::ptr_t _size; - - public: - IOActivity(AbsTime start, AbsTime length, MachineThread* thread, typename SIZE::ptr_t size) : - TRange(start, length), - _thread(thread), - _size(size) - { - ASSERT(_thread, "Sanity"); - ASSERT(_size, "Zero length IO"); - } - - MachineThread* thread() const { return _thread; } - void set_thread(MachineThread* thread) { _thread = thread; } - - typename SIZE::ptr_t size() const { return _size; } -}; - -#endif diff --git a/KDBG/KDBG.cpp b/KDBG/KDBG.cpp deleted file mode 100644 index 8b006e6..0000000 --- a/KDBG/KDBG.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// Kernel.cpp -// KDBG -// -// Created by James McIlree on 10/24/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include - -using namespace util; - -#include "KDebug.h" - -KDState KDBG::state() -{ - static_assert(sizeof(KDState) == sizeof(kbufinfo_t), "Types must be the same size"); - - KDState state; - int mib[3]; - size_t len = sizeof(state); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDGETBUF; - - if (sysctl(mib, 3, &state, &len, 0, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_ERR, "trace facility failure, KERN_KDGETBUF: %s\n", strerror(errno))); - THROW("trace facility failure, KERN_KDGETBUF: %s\n" << strerror(errno)); - } - - return state; -} - -bool KDBG::reset() -{ - int mib[3]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREMOVE; - if (sysctl(mib, 3, NULL, NULL, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KERN_KDREMOVE: %s\n", strerror(errno))); - return false; - } - - return true; -} - -bool KDBG::set_buffer_capacity(uint32_t capacity) -{ - int mib[4]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETBUF; - mib[3] = (int)capacity; - - if (sysctl(mib, 4, NULL, NULL, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KERN_KDSETBUF: %s\n", strerror(errno))); - return false; - } - - return true; -} - -bool KDBG::set_nowrap(bool is_nowrap) -{ - int mib[4]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = is_nowrap ? KERN_KDEFLAGS : KERN_KDDFLAGS; - mib[3] = KDBG_NOWRAP; - - if (sysctl(mib, 4, NULL, NULL, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KDBG_NOWRAP: %s\n", strerror(errno))); - return false; - } - - return true; -} - -bool KDBG::initialize_buffers() -{ - int mib[3]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - - if (sysctl(mib, 3, NULL, NULL, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KERN_KDSETUP: %s\n", strerror(errno))); - return false; - } - return true; -} - - -// -// Legal values are: -// -// KDEBUG_TRACE (full set of tracepoints) -// KDEBUG_PPT (subset of tracepoints to minimize performance impact) -// 0 (Disable) -// -bool KDBG::set_enabled(uint32_t value) -{ - int mib[4]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDENABLE; - mib[3] = value; - - if (sysctl(mib, 4, NULL, NULL, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KERN_KDENABLE: %s\n", strerror(errno))); - return false; - } - return true; -} - -std::vector KDBG::cpumap() -{ - std::vector cpumap; - - /* - * To fit in the padding space of a VERSION1 file, the max possible - * cpumap size is one page. - */ - if (kd_cpumap_header* cpumap_header = (kd_cpumap_header*)malloc(PAGE_SIZE)) { - int mib[3]; - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDCPUMAP; - - size_t temp = PAGE_SIZE; - if (sysctl(mib, 3, cpumap_header, &temp, NULL, 0) == 0) { - if (PAGE_SIZE >= temp) { - if (cpumap_header->version_no == RAW_VERSION1) { - cpumap.resize(cpumap_header->cpu_count); - memcpy(cpumap.data(), &cpumap_header[1], cpumap_header->cpu_count * sizeof(KDCPUMapEntry)); - } - } - } - free(cpumap_header); - } - - return cpumap; -} - -bool KDBG::write_maps(int fd) -{ - int mib[4]; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDWRITEMAP; - mib[3] = fd; - - if (sysctl(mib, 4, NULL, NULL, NULL, 0) < 0) - return false; - - return true; -} - -int KDBG::write_events(int fd) -{ - int mib[4]; - size_t events_written = 0; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDWRITETR; - mib[3] = fd; - - if (sysctl(mib, 4, NULL, &events_written, NULL, 0) < 0) - return -1; - - return (int)events_written; -} diff --git a/KDBG/KDBG.hpp b/KDBG/KDBG.hpp deleted file mode 100644 index 325bf9a..0000000 --- a/KDBG/KDBG.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// KDBG -// KDBG -// -// Created by James McIlree on 10/24/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -class KDBG { - private: - - // KERN_KDGETBUF == fill out kd_bufinfo struct. Tolerates undersize input structs to fetch less. - // KERN_KDSETBUF == set nkdbufs (kernel variable) - // KERN_KDSETUP == dealloc old buffers, alloc new ones - // KERN_KDEFLAGS == "Enable Flags" (masked against KDBG_USERFLAGS) - // KERN_KDDFLAGS == "Disable Flags" (masked against KDBG_USERFLAGS) - // KERN_KDENABLE == Actually turn on/off tracing - // KERN_KDSETREG == Set some kind of filtering. - - - // KERN_KDREMOVE == Turn off tracing, delete all buffers, set bufsize to zero. - // Clears KDBG_CKTYPES, KDBG_NOWRAP, KDBG_RANGECHECK, KDBG_VALCHECK, - // KDBG_PIDCHECK, and KDBG_PIDEXCLUDE. - // Sets controlling_pid to -1. - // Disables and deallocates thread map. - - public: - - static KDState state(); - - // - // Does not appear that this call can fail. - // - // Clears/disables everything, resets to base state. (Calls KDREMOVE) - // - static bool reset(); - - // - // Does not actually allocate any buffer space, you must - // call initialize_buffers to do that. - // - static bool set_buffer_capacity(uint32_t capacity); - - // - // It appears this flag can be set or cleared at any time, even if a - // trace is currently active. - // - // If nowrap is true, the buffer state will not set is_wrapped, even - // if the buffer overflows. - // - static bool set_nowrap(bool is_nowrap); - - // - // If tracing is active, disable it. - // If buffers are allocated, free them. - // If a thread map is allocated, delete it. - // - // clears KDBG_WRAPPED - // - // Allocates new buffers of the size set in set_buffer_capacity() - // Sets KDBG_BUFINIT - // - static bool initialize_buffers(); - - // - // Legal values are: - // - // KDEBUG_ENABLE_TRACE (full set of tracepoints) - // KDEBUG_ENABLE_PPT (subset of tracepoints to minimize performance impact) - // 0 (Disable) - // - static bool set_enabled(uint32_t value); - - // - // Reads all available threadmap data - // - // Fails if KDBG_MAPINIT is not set. - // - template - static std::vector> threadmap(KDState& state); - - // - // Reads the *current* threadmap data - // - // NOTE that this differs from "threadmap", which reads the threadmap - // data that was snapshotted when the trace buffers were initialized. - // - template - static std::vector> current_threadmap(); - - // - // Reads the current cpumap. - // - // Fails if the buffers have not been initialized. - // - // The caller is responsible for the memory returned, which should be free()'d - // - static std::vector cpumap(); - - // - // Writes the current cpumap to the given fd - // - // Fails if the buffers have not been initialized, or if the provided fd cannot be written to. - // - // Writes a VERSION 1+ threadmap (containing an embedded cpumap) to the fd, and then - // enough zero bytes to pad to a file block alignment - // - static bool write_maps(int fd); - - // - // Blocks in the kernel until the trace buffers are 50% full. - // Then writes all events to the provided fd. - // - // Fails if the buffers are not initialized, tracing is not enabled, or the provided fd cannot be written to. - // - // Returns -1 on failure, otherwise the numbers of trace events written. - static int write_events(int fd); - - // - // Reads all available trace data. - // - // Returns -1 on failure, otherwise the number of elements read. - // - template - static int read(KDEvent* buf, size_t buf_size_in_bytes); -}; - -template -int KDBG::read(KDEvent* buf, size_t buf_size_in_bytes) -{ - ASSERT(buf, "Sanity"); - - int mib[3]; - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - - if (sysctl(mib, 3, buf, &buf_size_in_bytes, NULL, 0) < 0) { - DEBUG_ONLY(log_msg(ASL_LEVEL_WARNING, "trace facility failure, KERN_KDREADTR: %s\n", strerror(errno))); - return -1; - } - - return (int)buf_size_in_bytes; - } - -template -std::vector> KDBG::threadmap(KDState& state) -{ - std::vector> maps(state.thread_map_capacity()); - size_t size = state.thread_map_capacity() * sizeof(KDThreadMapEntry); - - int mib[3]; - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDTHRMAP; - - if (sysctl(mib, 3, maps.data(), &size, NULL, 0) < 0) { - maps.clear(); - } - - return maps; - } - -template -std::vector> KDBG::current_threadmap() -{ - std::vector> maps(2048); - -resize: - size_t size_in = maps.size() * sizeof(KDThreadMapEntry); - size_t size_out = size_in; - - int mib[3]; - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADCURTHRMAP; - - if (sysctl(mib, 3, maps.data(), &size_out, NULL, 0) < 0) { - // Grr, seems like this doesn't report a target size, we have to guess! - if (errno == EINVAL && size_out == size_in) { - maps.resize(maps.size() * 2); - goto resize; - } - maps.clear(); - } else { - maps.resize(size_out / sizeof(KDThreadMapEntry)); - } - - return maps; -} diff --git a/KDBG/KDCPUMapEntry.hpp b/KDBG/KDCPUMapEntry.hpp deleted file mode 100644 index 47ec0d2..0000000 --- a/KDBG/KDCPUMapEntry.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// KDCPUMapEntry.hpp -// KDBG -// -// Created by James McIlree on 4/18/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_KDCPUMapEntry_hpp -#define kdprof_KDCPUMapEntry_hpp - -class KDCPUMapEntry { - protected: - uint32_t _cpu_id; - uint32_t _flags; - char _name[8]; - - public: - KDCPUMapEntry() {} // Default constructor must do nothing, so vector resizes do no work! - KDCPUMapEntry(uint32_t cpu_id, uint32_t flags, const char* cpu_name) : - _cpu_id(cpu_id), - _flags(flags) - { - ASSERT(cpu_name, "Sanity"); - ASSERT(strlen(cpu_name) < sizeof(_name), "Name too long"); - strlcpy(_name, cpu_name, sizeof(_name)); - } - - uint32_t cpu_id() const { return _cpu_id; } - uint32_t flags() const { return _flags; } - const char* name() const { return _name; } - - bool is_iop() const { return _flags & KDBG_CPUMAP_IS_IOP; } -}; - -#endif diff --git a/KDBG/KDEvent.hpp b/KDBG/KDEvent.hpp deleted file mode 100644 index 5b2e6b9..0000000 --- a/KDBG/KDEvent.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// -// KDEvent.hpp -// KDBG -// -// Created by James McIlree on 10/25/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -template class KDEventFields {}; - -template <> -class KDEventFields { - private: - static const uint64_t K32_TIMESTAMP_MASK = 0x00ffffffffffffffULL; - static const uint64_t K32_CPU_MASK = 0xff00000000000000ULL; - static const uint32_t K32_CPU_SHIFT = 56; - - public: - uint64_t _timestamp; - uint32_t _arg1; - uint32_t _arg2; - uint32_t _arg3; - uint32_t _arg4; - uint32_t _thread; - uint32_t _debugid; - - int cpu() const { return (int) ((_timestamp & K32_CPU_MASK) >> K32_CPU_SHIFT); } - uint64_t timestamp() const { return _timestamp & K32_TIMESTAMP_MASK; } - - uint64_t unused() const { THROW("Calling method for field that does not exist"); } -}; - -template <> -class KDEventFields { - public: - uint64_t _timestamp; - uint64_t _arg1; - uint64_t _arg2; - uint64_t _arg3; - uint64_t _arg4; - uint64_t _thread; - uint32_t _debugid; - uint32_t _cpuid; - uint64_t _unused; // Defined as uintptr in orignal header - - int cpu() const { return (int)_cpuid; } - uint64_t timestamp() const { return _timestamp; } - - uint64_t unused() const { return _unused; } -}; - -/* The debug code consists of the following - * - * ---------------------------------------------------------------------- - *| | | |Func | - *| Class (8) | SubClass (8) | Code (14) |Qual(2)| - * ---------------------------------------------------------------------- - * The class specifies the higher level - */ - -template -class KDEvent { - private: - KDEventFields _fields; - - static const uint32_t DBG_CLASS_MASK = 0xFF000000; - static const uint32_t DBG_CLASS_MASK_SHIFT = 24; - static const uint32_t DBG_SUBCLASS_MASK = 0x00FF0000; - static const uint32_t DBG_SUBCLASS_MASK_SHIFT = 16; - static const uint32_t DBG_CODE_MASK = 0x0000FFFC; - static const uint32_t DBG_CODE_MASK_SHIFT = 2; - static const uint32_t DBG_FUNC_MASK = DBG_FUNC_START | DBG_FUNC_END; - - public: - // - // Provided only for lower_bounds/upper_bounds binary searches of event buffers - // - KDEvent() {} - KDEvent(AbsTime timestamp) { _fields._timestamp = timestamp.value(); } - - // Sort by time operator for lower_bounds/upper_bounds - bool operator<(const KDEvent& rhs) const { return this->timestamp() < rhs.timestamp(); } - - AbsTime timestamp() const { return AbsTime(_fields.timestamp()); } - typename SIZE::ptr_t tid() const { return _fields._thread; } - int cpu() const { return _fields.cpu(); } - - uint32_t dbg_class() const { return (_fields._debugid & DBG_CLASS_MASK) >> DBG_CLASS_MASK_SHIFT; } - uint32_t dbg_subclass() const { return (_fields._debugid & DBG_SUBCLASS_MASK) >> DBG_SUBCLASS_MASK_SHIFT; } - uint32_t dbg_code() const { return (_fields._debugid & DBG_CODE_MASK) >> DBG_CODE_MASK_SHIFT; } - uint32_t dbg_cooked() const { return _fields._debugid & ~DBG_FUNC_MASK; } - uint32_t dbg_raw() const { return _fields._debugid; } - - typename SIZE::ptr_t arg1() const { return _fields._arg1; } - typename SIZE::ptr_t arg2() const { return _fields._arg2; } - typename SIZE::ptr_t arg3() const { return _fields._arg3; } - typename SIZE::ptr_t arg4() const { return _fields._arg4; } - - uint8_t* arg1_as_pointer() const { return (uint8_t*)&_fields._arg1; } - std::string arg1_as_string() const; - std::string all_args_as_string() const; - - bool is_func_start() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_START; } - bool is_func_end() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_END; } - bool is_func_none() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_NONE; } - - uint64_t unused() const { return _fields.unused(); } - - bool is_valid() { - // Must have a code set to be valid, no codes are 0x00 - if (dbg_code() == 0) - return false; - - // Legal values are NONE, START, and END. - if ((_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_MASK) - return false; - - return true; - } - - std::string to_string() const; -}; - -template -std::string KDEvent::arg1_as_string() const { - // We can't count on the arg being NULL terminated, we have to copy. - // Using a uint32_t/uint64_t instead of a char[] guarantees alignment. - decltype(_fields._arg1) buf[2]; - - buf[0] = _fields._arg1; - buf[1] = 0; - - return std::string(reinterpret_cast(buf)); -} - -template -std::string KDEvent::all_args_as_string() const { - // We can't count on the arg being NULL terminated, we have to copy. - // Using a uint32_t/uint64_t instead of a char[] guarantees alignment. - decltype(_fields._arg1) buf[5]; - - buf[0] = _fields._arg1; - buf[1] = _fields._arg2; - buf[2] = _fields._arg3; - buf[3] = _fields._arg4; - buf[4] = 0; - - return std::string(reinterpret_cast(buf)); -} - diff --git a/KDBG/KDState.hpp b/KDBG/KDState.hpp deleted file mode 100644 index 13e7f06..0000000 --- a/KDBG/KDState.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// KDState.hpp -// KDBG -// -// Created by James McIlree on 8/10/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -class KDState { - protected: - kbufinfo_t _state; - - public: - uint32_t flags() { return _state.flags; } - int capacity() { return _state.nkdbufs; } - int thread_map_capacity() { return _state.nkdthreads; } - - bool is_enabled() { return !_state.nolog; } - bool is_initialized() { return flags() & KDBG_BUFINIT; } - bool is_thread_map_initialized() { return flags() & KDBG_MAPINIT; } - bool is_nowrap() { return flags() & KDBG_NOWRAP; } - bool is_freerun() { return flags() & KDBG_FREERUN; } - bool is_wrapped() { return flags() & KDBG_WRAPPED; } - - bool is_lp64() { return (flags() & KDBG_LP64) > 0; } - - bool is_range_collection_enabled() { return (flags() & KDBG_RANGECHECK) > 0; } - bool is_specific_value_collection_enabled() { return (flags() & KDBG_VALCHECK) > 0; } - bool is_filter_collection_enabled() { return (flags() & KDBG_TYPEFILTER_CHECK) > 0; } - bool is_inclusive_pid_collection_enabled() { return (flags() & KDBG_PIDCHECK) > 0; } - bool is_exclusive_pid_collection_enabled() { return (flags() & KDBG_PIDEXCLUDE) > 0; } - - pid_t controlling_pid() { return _state.bufid; } - - void print() { - printf("KDebug State\n"); - printf("\tBuffer is %s\n", this->is_initialized() ? "initialized" : "not initialized"); - printf("\tCapacity is %d\n", this->capacity()); - printf("\tRaw flags 0x%08x\n", this->flags()); - printf("\tLogging is %s\n", this->is_enabled() ? "enabled" : "disabled"); - printf("\tWrapping is %s\n", this->is_nowrap() ? "disabled" : "enabled"); - printf("\tBuffer %s wrapped\n", this->is_wrapped() ? "has" : "has not"); - - // Two bits, 4 possible states: - // - // INC EXC - // 1 0 ALL_MARKED_PIDS - // 0 1 ALL_UNMARKED_PIDS - // 0 0 ALL_PIDS - // 1 1 ERROR - - const char* style; - switch (flags() & (KDBG_PIDEXCLUDE | KDBG_PIDCHECK)) { - case 0: - style = "all-pids"; - break; - case KDBG_PIDCHECK: - style = "includes-marked-pids"; - break; - case KDBG_PIDEXCLUDE: - style = "excludes-marked-pids"; - break; - default: - style = "ERROR"; - break; - } - printf("\tCollection style is %s\n", style); - printf("\tCollection by range is %s\n", this->is_range_collection_enabled() ? "enabled" : "disabled"); - printf("\tCollection by value is %s\n", this->is_specific_value_collection_enabled() ? "enabled" : "disabled"); - printf("\tCollection by filter is %s\n", this->is_filter_collection_enabled() ? "enabled" : "disabled"); - printf("\tThread map is %s ", this->is_thread_map_initialized() ? "initialized\n" : "not initialized\n"); - printf("\tThread map entries %d\n", this->thread_map_capacity()); - if (this->controlling_pid() == -1) - printf("\tNo controlling pid\n"); - else - printf("\tControlled by pid %d\n", this->controlling_pid()); - } -}; - diff --git a/KDBG/KDThreadMapEntry.hpp b/KDBG/KDThreadMapEntry.hpp deleted file mode 100644 index 82dd3db..0000000 --- a/KDBG/KDThreadMapEntry.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// KDThreadMapEntry.hpp -// KDBG -// -// Created by James McIlree on 10/25/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_KDThreadMapEntry_hpp -#define kdprof_KDThreadMapEntry_hpp - -// -// This is the kd_threadmap from the kernel -// -// There is one interesting conflict I have noticed so far. -// -// The _pid field is set to 1 for kernel threads that have no user space -// representation. However, 1 is a valid pid, and in fact, used by launchd. -// -// A full disambiguation of entries *must* include the tid, pid, AND name: -// -// 000000000000011f 00000001 launchd -// 000000000000014f 00000001 launchd -// 0000000000000150 00000001 launchd -// -// 0000000000000110 00000001 kernel_task -// 0000000000000120 00000001 kernel_task -// 0000000000000133 00000001 kernel_task -// -template -class KDThreadMapEntry { - protected: - typename SIZE::ptr_t _tid; - int32_t _pid; - char _name[20]; // This is process name, not thread name! - - public: - typename SIZE::ptr_t tid() const { return _tid; } - int32_t pid() const { return _pid; } - const char* name() const { return _name; } -}; - -#endif diff --git a/KDBG/KDebug.h b/KDBG/KDebug.h deleted file mode 100644 index af2eb9d..0000000 --- a/KDBG/KDebug.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// KDebug.h -// KDBG -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef KDebug_KDebug_h -#define KDebug_KDebug_h - -#include -#include -#include - -#ifndef KERNEL_PRIVATE - #define KERNEL_PRIVATE - #include - #undef KERNEL_PRIVATE -#else - #error Something is really strage... -#endif /*KERNEL_PRIVATE*/ - -#include -#include -#include -#include - -#include - -#include - -using namespace util; - -#include "MetaTypes.hpp" -#include "TaskRequestedPolicy.hpp" -#include "TaskEffectivePolicy.hpp" -#include "KDState.hpp" -#include "KDThreadMapEntry.hpp" -#include "KDCPUMapEntry.hpp" -#include "KDEvent.hpp" -#include "KDBG.hpp" -#include "Kernel.hpp" -#include "TraceCodes.hpp" -#include "MachineVoucher.hpp" -#include "VoucherInterval.hpp" -#include "MachineThread.hpp" -#include "IOActivity.hpp" -#include "CPUActivity.hpp" -#include "ThreadSummary.hpp" -#include "ProcessSummary.hpp" -#include "MachineMachMsg.hpp" -#include "NurseryMachMsg.hpp" -#include "CPUSummary.hpp" -#include "MachineCPU.hpp" -#include "MachineProcess.hpp" -#include "TraceDataHeader.hpp" -#include "TraceFile.hpp" -#include "Machine.hpp" -#include "Machine.impl.hpp" -#include "Machine.mutable-impl.hpp" -#include "MachineProcess.impl.hpp" -#include "MachineProcess.mutable-impl.hpp" -#include "MachineThread.impl.hpp" -#include "MachineThread.mutable-impl.hpp" -#include "MachineCPU.impl.hpp" -#include "MachineCPU.mutable-impl.hpp" - -#endif diff --git a/KDBG/Kernel.cpp b/KDBG/Kernel.cpp deleted file mode 100644 index 8553f2e..0000000 --- a/KDBG/Kernel.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Kernel.cpp -// KDBG -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - -using namespace util; - -bool Kernel::is_64_bit() -{ - int mib[4]; - size_t len; - struct kinfo_proc kp; - - /* Now determine if the kernel is running in 64-bit mode */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = 0; /* kernproc, pid 0 */ - len = sizeof(kp); - if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &kp, &len, NULL, 0) == -1) { - THROW("sysctl to get kernel size failed"); - } - - if (kp.kp_proc.p_flag & P_LP64) - return true; - - return false; -} - -uint32_t Kernel::active_cpu_count() -{ - int mib[4]; - size_t len; - int num_cpus; - - /* - * grab the number of cpus and scale the buffer size - */ - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - mib[2] = 0; - len = sizeof(num_cpus); - - sysctl(mib, 2, &num_cpus, &len, NULL, 0); - - return num_cpus; -} diff --git a/KDBG/Kernel.hpp b/KDBG/Kernel.hpp deleted file mode 100644 index 16e46b4..0000000 --- a/KDBG/Kernel.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// Kernel.hpp -// KDBG -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __kdprof__Kernel__ -#define __kdprof__Kernel__ - -enum class KernelSize { k32, k64 }; - -class Kernel { - public: - static bool is_64_bit(); - static uint32_t active_cpu_count(); -}; - -#endif /* defined(__kdprof__Kernel__) */ diff --git a/KDBG/Machine.hpp b/KDBG/Machine.hpp deleted file mode 100644 index 48586f5..0000000 --- a/KDBG/Machine.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// Machine.hpp -// KDBG -// -// Created by James McIlree on 10/25/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -enum class kMachineFlag : std::uint32_t { - LostEvents = 0x00000001 -}; - -template -class Machine { - protected: - std::vector> _cpus; - - std::unordered_multimap> _processes_by_pid; - std::unordered_multimap*, ConstCharHash, ConstCharEqualTo> _processes_by_name; - std::vector*> _processes_by_time; - - std::unordered_multimap > _threads_by_tid; - std::vector*> _threads_by_time; - - std::vector> _mach_msgs; - std::unordered_map _mach_msgs_by_event_index; - std::unordered_map> _mach_msg_nursery; - - // - // Vouchers are a bit special. We install pointers to vouchers in - // MachineThreads and MachineMachMsg. This means that vouchers cannot - // be moved once allocated. We could do two passes to exactly size - // the data structures, this should be investigated in the future. - // - // On create or first observed use, a voucher goes into the nursery. - // It stays there until a destroy event, or the end of Machine events. - // Once flushed from the nursery, we have a map of addresses, which - // points to a vector sorted by time. This allows addr @ time lookups - // later. - // - std::unordered_map>> _voucher_nursery; - std::unordered_map>>> _vouchers_by_addr; - - std::unordered_map> _io_by_uid; // uid == unique id, not user id - std::vector> _all_io; - std::vector _all_io_active_intervals; - - MachineProcess* _kernel_task; - const KDEvent* _events; - uintptr_t _event_count; - uint32_t _flags; - int32_t _unknown_process_pid; // We need unique negative pid's for previously unknown TID's - - // - // Protected initialization code - // - void raw_initialize(const KDCPUMapEntry* cpumaps, - uint32_t cpumap_count, - const KDThreadMapEntry* threadmaps, - uint32_t threadmap_count, - const KDEvent* events, - uintptr_t event_count); - - void post_initialize(); - - // - // Mutable API, for use during construction - // - - pid_t next_unknown_pid() { return --_unknown_process_pid; } - - MachineProcess* create_process(pid_t pid, const char* name, AbsTime create_timestamp, kMachineProcessFlag flags); - MachineThread* create_thread(MachineProcess* process, typename SIZE::ptr_t tid, MachineVoucher* voucher, AbsTime create_timestamp, kMachineThreadFlag flags); - MachineVoucher* create_voucher(typename SIZE::ptr_t address, AbsTime create_timestamp, kMachineVoucherFlag flags, uint32_t content_bytes_capacity); - - void destroy_voucher(typename SIZE::ptr_t address, AbsTime timestamp); - - void set_flags(kMachineFlag flag) { _flags |= (uint32_t)flag; } - - void set_process_name(MachineProcess* process, const char* name); - - MachineProcess* mutable_process(pid_t pid, AbsTime time) { return const_cast*>(process(pid, time)); } - MachineThread* mutable_thread(typename SIZE::ptr_t tid, AbsTime time) { return const_cast*>(thread(tid, time)); } - - MachineProcess* youngest_mutable_process(pid_t pid); - MachineThread* youngest_mutable_thread(typename SIZE::ptr_t tid); - - MachineVoucher* process_event_voucher_lookup(typename SIZE::ptr_t address, uint32_t msgh_bits); - MachineThread* process_event_tid_lookup(typename SIZE::ptr_t tid, AbsTime now); - - MachineVoucher* thread_forwarding_voucher_lookup(const MachineVoucher* original_thread_voucher); - - void begin_io(MachineThread* thread, AbsTime time, typename SIZE::ptr_t uid, typename SIZE::ptr_t size); - void end_io(AbsTime time, typename SIZE::ptr_t uid); - - bool process_event(const KDEvent& event); - void process_trequested_task(pid_t pid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1); - void process_trequested_thread(typename SIZE::ptr_t tid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1); - - void initialize_cpu_idle_intr_states(); - - public: - static MachineVoucher UnsetVoucher; - static MachineVoucher NullVoucher; - - Machine(KDCPUMapEntry* cpumaps, uint32_t cpumap_count, KDThreadMapEntry* threadmaps, uint32_t threadmap_count, KDEvent* events, uintptr_t event_count); - // Destructive, mutates parent! - Machine(Machine& parent, KDEvent* events, uintptr_t event_count); - Machine(const TraceFile& file); - - bool lost_events() const { return (_flags & (uint32_t)kMachineFlag::LostEvents) > 0; } - - const MachineProcess* process(pid_t pid, AbsTime time) const; - const MachineThread* thread(typename SIZE::ptr_t tid, AbsTime time) const; - const MachineVoucher* voucher(typename SIZE::ptr_t address, AbsTime time) const; - const MachineMachMsg* mach_msg(uintptr_t event_index) const; - - const std::vector*>& processes() const; - const std::vector*>& threads() const; - const std::vector>& cpus() const; - - const KDEvent* events() const { return _events; } - uintptr_t event_count() const { return _event_count; } - - AbsInterval timespan() const; - - // Returns the number of cpus that have timeline data. - // (IOW, typically the number of AP(s) on a machine, but might be less if you've disabled some so they generate no trace data) - uint32_t active_cpus() const; - - // If summary_cpu == NULL , all cpus are matched. - CPUSummary summary_for_timespan(AbsInterval timespan, const MachineCPU* summary_cpu) const; - - // This attempts to analyze various pieces of data and guess - // if the Machine represents an ios device or not. - bool is_ios() const; - - DEBUG_ONLY(void validate() const;) -}; - -template MachineVoucher Machine::UnsetVoucher(SIZE::PTRMAX, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsUnsetVoucher, 0); -template MachineVoucher Machine::NullVoucher(0, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsNullVoucher, 0); - diff --git a/KDBG/Machine.impl.hpp b/KDBG/Machine.impl.hpp deleted file mode 100644 index 3aee10a..0000000 --- a/KDBG/Machine.impl.hpp +++ /dev/null @@ -1,1085 +0,0 @@ -// -// Machine.impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - -template -bool process_by_time_sort(const MachineProcess* left, const MachineProcess* right) { - return left->timespan().location() < right->timespan().location(); -} - -template -bool thread_by_time_sort(const MachineThread* left, const MachineThread* right) { - return left->timespan().location() < right->timespan().location(); -} - -template -void Machine::post_initialize() { - // - // Post initialization. Sort various by time vectors, etc. - // - - std::sort(_processes_by_time.begin(), _processes_by_time.end(), process_by_time_sort); - std::sort(_threads_by_time.begin(), _threads_by_time.end(), thread_by_time_sort); - - // naked auto okay here, process is a ptr. - AbsTime last_machine_timestamp = _events[_event_count-1].timestamp(); - for (auto process : _processes_by_time) { - process->post_initialize(last_machine_timestamp); - } - - // - // Collapse the idle/intr/run queues into a single timeline - // - for (auto& cpu : _cpus) { - cpu.post_initialize(timespan()); - } - - // - // Flush any outstanding blocked events - // - for (auto& thread : _threads_by_tid) { - thread.second.post_initialize(last_machine_timestamp); - } - - // - // Sort the IOActivity events, and build a flattened vector that can be used to find IO ranges for intersecting during interval searches - // - _io_by_uid.clear(); - std::sort(_all_io.begin(), _all_io.end()); - - // We cannot use trange_vector_union to flatten _all_io, as _all_io isn't a plain TRange type, and we want to yield that type. - // cut & paste to the rescue! :-) - if (!_all_io.empty()) { - auto input_it = _all_io.begin(); - _all_io_active_intervals.push_back(*input_it); - while (++input_it < _all_io.end()) { - TRange union_range = _all_io_active_intervals.back(); - - if (union_range.intersects(*input_it)) { - _all_io_active_intervals.pop_back(); - _all_io_active_intervals.push_back(union_range.union_range(*input_it)); - } else { - ASSERT(union_range < *input_it, "Out of order merging"); - _all_io_active_intervals.push_back(*input_it); - } - } - } - - // - // Flush any outstanding MachMsg(s) in the nursery (state SEND) - // - // NOTE! We do not clear _mach_msg_nursery because its state is - // forwarded to future Machine(s). - // - for (auto& nursery_it : _mach_msg_nursery) { - auto& nursery_msg = nursery_it.second; - if (nursery_msg.state() == kNurseryMachMsgState::Send) { - auto mach_msg_it = _mach_msgs.emplace(_mach_msgs.end(), - nursery_msg.id(), - nursery_msg.kmsg_addr(), - kMachineMachMsgFlag::HasSender, - nursery_msg.send_time(), - nursery_msg.send_tid(), - nursery_msg.send_msgh_bits(), - nursery_msg.send_voucher(), - AbsTime(0), - 0, - 0, - &Machine::UnsetVoucher); - _mach_msgs_by_event_index[nursery_msg.send_event_index()] = std::distance(_mach_msgs.begin(), mach_msg_it); - } - } - - // - // Flush any outstanding Voucher(s) in the nursery - // - for (auto& nursery_it : _voucher_nursery) { - - // - // First we need to "close" the open end of the live voucher's - // timespan. - // - auto voucher = nursery_it.second.get(); - voucher->set_timespan_to_end_of_time(); - - auto address = nursery_it.first; - - // First find the "row" for this address. - auto by_addr_it = _vouchers_by_addr.find(address); - if (by_addr_it == _vouchers_by_addr.end()) { - // No address entry case - std::vector>> row; - row.emplace_back(std::move(nursery_it.second)); - _vouchers_by_addr.emplace(address, std::move(row)); - } else { - auto& row = by_addr_it->second; - - // Make sure these are sorted and non-overlapping - ASSERT(row.back()->timespan() < voucher->timespan(), "Sanity"); - ASSERT(!row.back()->timespan().intersects(voucher->timespan()), "Sanity"); - - row.emplace_back(std::move(nursery_it.second)); - } - } - - _voucher_nursery.clear(); - - DEBUG_ONLY(validate()); -} - -template -void Machine::raw_initialize(const KDCPUMapEntry* cpumaps, - uint32_t cpumap_count, - const KDThreadMapEntry* threadmaps, - uint32_t threadmap_count, - const KDEvent* events, - uintptr_t event_count) -{ - ASSERT(cpumaps || cpumap_count == 0, "Sanity"); - ASSERT(threadmaps || threadmap_count == 0, "Sanity"); - ASSERT(events || event_count == 0, "Sanity"); - - for (uint32_t i = 0; i < cpumap_count; ++i) { - _cpus.emplace_back(i, cpumaps[i].is_iop(), cpumaps[i].name()); - } - - // We cannot create processes / threads unless we have at least one event to give us a timestamp. - if (event_count) { - AbsTime now = events[0].timestamp(); - - _kernel_task = create_process(0, "kernel_task", now, kMachineProcessFlag::IsKernelProcess); - - // Initial thread state, nothing in nusery - for (uint32_t index = 0; index < threadmap_count; ++index) { - auto& threadmap = threadmaps[index]; - - pid_t pid = threadmap.pid(); - - // The kernel threadmap often has empty entries. Skip them. - if (pid == 0) - break; - - if (pid == 1 && strncmp(threadmap.name(), "kernel_task", 12) == 0) { - pid = 0; - } - - MachineProcess* process = youngest_mutable_process(pid); - if (!process) { - process = create_process(pid, threadmap.name(), now, kMachineProcessFlag::CreatedByThreadMap); - ASSERT(process, "Sanity"); - } - process->add_thread(create_thread(process, threadmap.tid(), &UnsetVoucher, now, kMachineThreadFlag::CreatedByThreadMap)); - } - } - - // We need to know what the idle/INTR states of the CPU's are. - initialize_cpu_idle_intr_states(); - - for (uintptr_t index = 0; index < event_count; ++index) { - if (!process_event(events[index])) - break; - } - - post_initialize(); -} - -template -Machine::Machine(KDCPUMapEntry* cpumaps, uint32_t cpumap_count, KDThreadMapEntry* threadmaps, uint32_t threadmap_count, KDEvent* events, uintptr_t event_count) : - _kernel_task(nullptr), - _events(events), - _event_count(event_count), - _flags(0), - _unknown_process_pid(-1) -{ - raw_initialize(cpumaps, - cpumap_count, - threadmaps, - threadmap_count, - events, - event_count); -} - -template -Machine::Machine(const TraceFile& file) : - _kernel_task(nullptr), - _events(file.events()), - _event_count(file.event_count()), - _flags(0), - _unknown_process_pid(-1) -{ - raw_initialize(file.cpumap(), - file.cpumap_count(), - file.threadmap(), - file.threadmap_count(), - file.events(), - file.event_count()); -} - -template -Machine::Machine(Machine& parent, KDEvent* events, uintptr_t event_count) : - _kernel_task(nullptr), - _events(events), - _event_count(event_count), - _flags(0), - _unknown_process_pid(-1) -{ - ASSERT(events || event_count == 0, "Sanity"); - - const std::vector*>& parent_threads = parent.threads(); - const std::vector>& parent_cpus = parent.cpus(); - - for (const MachineCPU& parent_cpu : parent_cpus) { - _cpus.emplace_back(parent_cpu.id(), parent_cpu.is_iop(), parent_cpu.name()); - } - - // We cannot create processes / threads unless we have at least one event to give us a timestamp. - if (event_count) { - AbsTime now = events[0].timestamp(); - - // - // Forawd any live vouchers. This must done before forwarding threads - // or MachMsgs from their nurseries, as they have references to the - // vouchers. - // - for (auto& parent_vouchers_by_addr_it : parent._vouchers_by_addr) { - std::unique_ptr>& voucher = parent_vouchers_by_addr_it.second.back(); - if (voucher->is_live()) { - // When we flushed these vouchers in the previous machine state, - // we set their timespans to infinite. We need to reset them in - // case a close event arrives. - voucher->set_timespan_to_zero_length(); - _voucher_nursery.emplace(voucher->address(), std::move(voucher)); - } - } - - _kernel_task = create_process(0, "kernel_task", now, kMachineProcessFlag::IsKernelProcess); - - for (const MachineThread* parent_thread : parent_threads) { - if (!parent_thread->is_trace_terminated()) { - const MachineProcess& parent_process = parent_thread->process(); - MachineProcess* new_process = youngest_mutable_process(parent_process.pid()); - if (!new_process) { - kMachineProcessFlag new_process_flags = (kMachineProcessFlag)(parent_process.flags() | (uint32_t)kMachineProcessFlag::CreatedByPreviousMachineState); - new_process = create_process(parent_process.pid(), parent_process.name(), now, new_process_flags); - ASSERT(new_process, "Sanity"); - } - new_process->add_thread(create_thread(new_process, - parent_thread->tid(), - thread_forwarding_voucher_lookup(parent_thread->last_voucher()), - now, - (kMachineThreadFlag)(parent_thread->flags() | (uint32_t)kMachineThreadFlag::CreatedByPreviousMachineState))); - } - } - - // We need to know what the idle/INTR states of the CPU's are. - // - // Start by looking at the existing states. - uint32_t init_count = 0; - uint32_t ap_count = 0; - for (const MachineCPU& parent_cpu : parent_cpus) { - if (!parent_cpu.is_iop()) { - ap_count++; - const std::vector>& parent_cpu_timeline = parent_cpu.timeline(); - - bool intr_initialized = false; - bool idle_initialized = false; - bool runq_initialized = false; - - MachineCPU& cpu = _cpus[parent_cpu.id()]; - - for (auto reverse_it = parent_cpu_timeline.rbegin(); reverse_it < parent_cpu_timeline.rend(); ++reverse_it) { - - // We can sometimes split two simultaneous events across two buffer snaps. - // IOW, buffer snap 1: - // - // event[N].timestamp = 1234; - // - // buffer snap 2: - // - // event[0].timestamp = 1234; - ASSERT(!reverse_it->contains(now) || reverse_it->max()-AbsTime(1) == now, "Sanity"); - ASSERT(reverse_it->location() <= now, "Sanity"); - - switch (reverse_it->type()) { - // - // The states are separate, and heirarchical. - // The order (low -> high) is: - // Run, Idle, INTR - // Unknown is a special state; we give up on seeing it. - // A lower state precludes being in a higher state, but - // not vice-versa. You can not be IDLE if you are currently - // Run. You may be IDLE during Run. - // - - case kCPUActivity::Unknown: - // Don't actually initialize anything, just force a bailout - runq_initialized = idle_initialized = intr_initialized = true; - break; - - // NOTE NOTE NOTE! - // - // Overly clever here, note the lack of "break" in the Run - // and Idle clause, we fall through to initialize higher - // states. - case kCPUActivity::Run: - ASSERT(!runq_initialized, "This should always be the last level to initialize"); - if (MachineThread* on_cpu_thread = youngest_mutable_thread(reverse_it->thread()->tid())) { - cpu.initialize_thread_state(on_cpu_thread, now); - init_count++; - } else { - ASSERT(reverse_it->thread()->is_trace_terminated() , "We should find this thread unless its been removed"); - } - runq_initialized = true; - - case kCPUActivity::Idle: - if (!idle_initialized) { - cpu.initialize_idle_state(reverse_it->is_idle(), now); - init_count++; - idle_initialized = true; - } - - case kCPUActivity::INTR: - if (!intr_initialized) { - cpu.initialize_intr_state(reverse_it->is_intr(), now); - init_count++; - intr_initialized = true; - } - break; - } - - if (runq_initialized) { - ASSERT(idle_initialized && intr_initialized, "Sanity"); - break; - } - } - } - } - - if (init_count < (ap_count * 3)) { - initialize_cpu_idle_intr_states(); - } - - // - // Forward any messages from the nursery - // - - for (auto& parent_nursery_it : parent._mach_msg_nursery) { - auto& parent_nursery_msg = parent_nursery_it.second; - - switch (parent_nursery_msg.state()) { - // We forward send(s) because they can become receives. - // We forward the free's because they stop us from showing bogus kernel message receipts - case kNurseryMachMsgState::Send: - case kNurseryMachMsgState::Free: { - ASSERT(_mach_msg_nursery.find(parent_nursery_msg.kmsg_addr()) == _mach_msg_nursery.end(), "Duplicate kmsg address when forwarding mach_msg nursery from parent"); - - auto it = _mach_msg_nursery.emplace(parent_nursery_msg.kmsg_addr(), parent_nursery_msg); - - // Grr, emplace returns a std::pair, and the it is std::pair... - - // We have to clear this to prevent bogus data being shown during a receive, - // the send event index is no longer available. - it.first->second.set_send_event_index(-1); - break; - } - - default: - break; - } - } - } - - for (uintptr_t index = 0; index < event_count; ++index) { - if (!process_event(_events[index])) - break; - } - - post_initialize(); -} - -template -const MachineProcess* Machine::process(pid_t pid, AbsTime time) const { - auto by_pid_range = _processes_by_pid.equal_range(pid); - for (auto it = by_pid_range.first; it != by_pid_range.second; ++it) { - const MachineProcess& process = it->second; - if (process.timespan().contains(time)) { - return &process; - } - } - - return nullptr; -} - -template -const MachineThread* Machine::thread(typename SIZE::ptr_t tid, AbsTime time) const { - auto by_tid_range = _threads_by_tid.equal_range(tid); - for (auto it = by_tid_range.first; it != by_tid_range.second; ++it) { - const MachineThread& thread = it->second; - if (thread.timespan().contains(time)) { - return &thread; - } - } - - return nullptr; -} - -template -struct VoucherVsAbsTimeComparator { - bool operator()(const std::unique_ptr>& voucher, const AbsTime time) const { - return voucher->timespan().max() < time; - } - - bool operator()(const AbsTime time, const std::unique_ptr>& voucher) const { - return time < voucher->timespan().max(); - } -}; - -template -const MachineVoucher* Machine::voucher(typename SIZE::ptr_t address, AbsTime timestamp) const { - // First find the "row" for this address. - auto by_addr_it = _vouchers_by_addr.find(address); - if (by_addr_it != _vouchers_by_addr.end()) { - auto& row = by_addr_it->second; - - auto by_time_it = std::upper_bound(row.begin(), row.end(), timestamp, VoucherVsAbsTimeComparator()); - // The upper bound will report that 0 is lower than [ 10, 20 ), need to check contains! - if (by_time_it != row.end()) { - // The compiler is having troubles seeing through an iterator that reflects unique_ptr methods which reflects MachineVoucher methods. - auto v = by_time_it->get(); - if (v->timespan().contains(timestamp)) { - return v; - } - } - } - - return nullptr; -} - -template -const MachineMachMsg* Machine::mach_msg(uintptr_t event_index) const { - auto it = _mach_msgs_by_event_index.find(event_index); - if (it != _mach_msgs_by_event_index.end()) { - return &_mach_msgs.at(it->second); - } - - return nullptr; -} - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void Machine::validate() const { - ASSERT(_events, "Sanity"); - ASSERT(_event_count, "Sanity"); - - // - // Event timestamp ordering is already pre-checked, no point in retesting it here. - // - - ASSERT(_threads_by_tid.size() == _threads_by_time.size(), "Container views state not in sync"); - ASSERT(_processes_by_pid.size() == _processes_by_name.size(), "Container views state not in sync"); - ASSERT(_processes_by_pid.size() == _processes_by_time.size(), "Container views state not in sync"); - - for (auto& pair : _processes_by_pid) { - auto& process = pair.second; - process.validate(); - AbsInterval process_timespan = process.timespan(); - for (auto thread : process.threads()) { - ASSERT(process_timespan.contains(thread->timespan()), "thread outside process timespan"); - } - } - - for (auto thread_ptr : _threads_by_time) { - thread_ptr->validate(); - } - - // - // Make sure no process with the same pid overlaps in time - // - const MachineProcess* last_process = nullptr; - for (auto& pair : _processes_by_pid) { - auto& process = pair.second; - if (last_process && last_process->pid() == process.pid()) { - // The < operator only checks ordering, it is not strict - // about overlap. We must check both - ASSERT(last_process->timespan() < process.timespan(), "Sanity"); - ASSERT(!last_process->timespan().intersects(process.timespan()), "Sanity"); - } - last_process = &process; - } - - // - // Make sure no thread with the same tid overlaps in time - // - const MachineThread* last_thread = nullptr; - for (auto& pair : _threads_by_tid) { - auto& thread = pair.second; - if (last_thread && last_thread->tid() == thread.tid()) { - // The < operator only checks ordering, it is not strict - // about overlap. We must check both - ASSERT(last_thread->timespan() < thread.timespan(), "Sanity"); - ASSERT(!last_thread->timespan().intersects(thread.timespan()), "Sanity"); - } - last_thread = &thread; - } - - ASSERT(is_trange_vector_sorted_and_non_overlapping(_all_io_active_intervals), "all io search/mask vector fails invariant"); -} -#endif - -template -const std::vector*>& Machine::processes() const { - return *reinterpret_cast< const std::vector*>* >(&_processes_by_time); -} - -template -const std::vector*>& Machine::threads() const { - return *reinterpret_cast< const std::vector*>* >(&_threads_by_time); -} - -template -const std::vector>& Machine::cpus() const { - return *reinterpret_cast< const std::vector>* >(&_cpus); -} - -template -AbsInterval Machine::timespan() const { - if (_event_count) { - AbsTime begin(_events[0].timestamp()); - AbsTime end(_events[_event_count-1].timestamp()); - return AbsInterval(begin, end - begin + AbsTime(1)); - } - - return AbsInterval(AbsTime(0),AbsTime(0)); -} - -template -CPUSummary Machine::summary_for_timespan(AbsInterval summary_timespan, const MachineCPU* summary_cpu) const { - ASSERT(summary_timespan.intersects(timespan()), "Sanity"); - CPUSummary summary; - - uint32_t ap_cpu_count = 0; - for (auto& cpu: _cpus) { - // We don't know enough about iops to do anything with them. - // Also skip cpus with no activity - if (!cpu.is_iop() && cpu.is_active()) { - ap_cpu_count++; - } - } - - bool should_calculate_wallclock_run_time = (summary_cpu == NULL && ap_cpu_count > 1); - - summary.begin_cpu_timeline_walks(); - - // - // Lots of optimization possibilities here... - // - // We spend a LOT of time doing the set lookups to map from a thread/process to a ThreadSummary / ProcessSummary. - // If we could somehow map directly from thread/process to the summary, this would speed up considerably. - // - - for (auto& cpu: _cpus) { - // We don't know enough about iops to do anything with them. - // Also skip cpus with no activity - if (!cpu.is_iop() && cpu.is_active()) { - if (summary_cpu == NULL || summary_cpu == &cpu) { - - summary.begin_cpu_timeline_walk(&cpu); - - auto& timeline = cpu.timeline(); - if (!timeline.empty()) { - AbsInterval timeline_timespan = AbsInterval(timeline.front().location(), timeline.back().max() - timeline.front().location()); - AbsInterval trimmed_timespan = summary_timespan.intersection_range(timeline_timespan); - - summary.incr_active_cpus(); - - auto start = cpu.activity_for_timestamp(trimmed_timespan.location()); - auto end = cpu.activity_for_timestamp(trimmed_timespan.max()-AbsTime(1)); - - ASSERT(start && start->contains(trimmed_timespan.location()), "Sanity"); - ASSERT(end && end->contains(trimmed_timespan.max()-AbsTime(1)), "Sanity"); - - ProcessSummary* process_summary = NULL; - ThreadSummary* thread_summary = NULL; - - if (start->is_run() && !start->is_context_switch()) { - const MachineThread* thread_on_cpu = start->thread(); - const MachineProcess* process_on_cpu = &thread_on_cpu->process(); - - process_summary = summary.mutable_process_summary(process_on_cpu); - thread_summary = process_summary->mutable_thread_summary(thread_on_cpu); - } - - // NOTE! <=, not <, because end is inclusive of data we want to count! - while (start <= end) { - // NOTE! summary_timespan, NOT trimmed_timespan! - AbsInterval t = start->intersection_range(summary_timespan); - - switch (start->type()) { - case kCPUActivity::Unknown: - // Only cpu summaries track unknown time - summary.add_unknown_time(t.length()); - break; - - case kCPUActivity::Idle: - summary.add_idle_time(t.length()); - summary.add_all_cpus_idle_interval(t); - if (process_summary) process_summary->add_idle_time(t.length()); - if (thread_summary) thread_summary->add_idle_time(t.length()); - break; - - case kCPUActivity::INTR: - summary.add_intr_time(t.length()); - // It might seem like we should add INTR time to the wallclock run time - // for the top level summary, but the concurrency level is calculated as - // Actual / Wallclock, where Actual only counts RUN time. If we add INTR - // the results are skewed. - if (process_summary) process_summary->add_intr_time(t.length()); - if (thread_summary) thread_summary->add_intr_time(t.length()); - break; - - case kCPUActivity::Run: { - // We must reset these each time. Consider the case where we have the following: - // - // RRRRRRRRIIIIIIIIIIIIIIIIRRRRRRRRRR - // ^ ^ - // CSW Summary starts here - // - // The first run seen in the summary will not be a CSW, and yet process/thread summary - // are NULL... - - const MachineThread* thread_on_cpu = start->thread(); - const MachineProcess* process_on_cpu = &thread_on_cpu->process(); - - process_summary = summary.mutable_process_summary(process_on_cpu); - thread_summary = process_summary->mutable_thread_summary(thread_on_cpu); - - if (start->is_context_switch()) { - summary.incr_context_switches(); - process_summary->incr_context_switches(); - thread_summary->incr_context_switches(); - } - - summary.add_run_time(t.length()); - process_summary->add_run_time(t.length()); - thread_summary->add_run_time(t.length()); - - // We only calculate wallclock run time if there is a chance - // it might differ from run time. - if (should_calculate_wallclock_run_time) { - summary.add_wallclock_run_interval(t); - process_summary->add_wallclock_run_interval(t); - } - - break; - } - } - - start++; - } - } - - summary.end_cpu_timeline_walk(&cpu); - } - } - } - - summary.end_cpu_timeline_walks(); - - // We only attempt to calculate future summary data in limited circumstances - // There must be enough future data to consistently decide if threads would run in the future. - // If the summary_cpu is not "all" we do not attempt to calculate. - - if (summary_cpu == NULL) { - AbsInterval future_timespan(summary_timespan.max(), summary_timespan.length() * AbsTime(5)); - if (future_timespan.intersection_range(timespan()).length() == future_timespan.length()) { - for (auto& cpu: _cpus) { - // We don't know enough about iops to do anything with them - if (!cpu.is_iop()) { - auto& timeline = cpu.timeline(); - - if (!timeline.empty()) { - AbsInterval timeline_timespan = AbsInterval(timeline.front().location(), timeline.back().max() - timeline.front().location()); - AbsInterval trimmed_timespan = future_timespan.intersection_range(timeline_timespan); - - auto start = cpu.activity_for_timestamp(trimmed_timespan.location()); - auto end = cpu.activity_for_timestamp(trimmed_timespan.max()-AbsTime(1)); - - ASSERT(start && start->contains(trimmed_timespan.location()), "Sanity"); - ASSERT(end && end->contains(trimmed_timespan.max()-AbsTime(1)), "Sanity"); - - ProcessSummary* process_summary = NULL; - ThreadSummary* thread_summary = NULL; - - // NOTE! <=, not <, because end is inclusive of data we want to count! - while (start <= end) { - // NOTE! future_timespan, NOT trimmed_timespan! - AbsInterval t = start->intersection_range(future_timespan); - - switch (start->type()) { - case kCPUActivity::Unknown: - break; - - case kCPUActivity::Idle: - // On idle, we mark the current thread as blocked. - if (thread_summary) - thread_summary->set_is_blocked_in_future(); - break; - - case kCPUActivity::INTR: - break; - - case kCPUActivity::Run: { - // We must reset these each time. Consider the case where we have the following: - // - // RRRRRRRRIIIIIIIIIIIIIIIIRRRRRRRRRR - // ^ ^ - // CSW Summary starts here - // - // The first run seen in the summary will not be a CSW, and yet process/thread summary - // are NULL... - - const MachineThread* thread_on_cpu = start->thread(); - const MachineProcess* process_on_cpu = &thread_on_cpu->process(); - - process_summary = summary.mutable_process_summary(process_on_cpu); - thread_summary = process_summary->mutable_thread_summary(thread_on_cpu); - - if (!thread_summary->is_future_initialized()) { - thread_summary->set_future_initialized(); - thread_summary->set_total_blocked_in_summary(thread_on_cpu->blocked_in_timespan(summary_timespan)); - thread_summary->set_first_block_after_summary(thread_on_cpu->next_blocked_after(summary_timespan.max())); - ASSERT(thread_summary->total_blocked_in_summary() + thread_summary->total_run_time() <= summary_timespan.length(), "More time blocked + running than is possible in summary timespan"); - thread_summary->set_max_possible_future_run_time(summary_timespan.length() - (thread_summary->total_blocked_in_summary() + thread_summary->total_run_time())); - } - - if (!thread_summary->is_blocked_in_future()) { - // We ONLY block at context_switch locations. But, we can context - // switch on any cpu. So, need a strong check! - if (t.max() >= thread_summary->first_block_after_summary()) { - thread_summary->set_is_blocked_in_future(); - } else { - ASSERT(t.location() <= thread_summary->first_block_after_summary(), "Sanity"); - // Each thread controls how much time it can accumulate in a given window. - // It may be that only a fraction (or none) of the time can be added. - // Make sure to only add the thread approved amount to the process and total summary - AbsTime future_time = thread_summary->add_future_run_time(t.length()); - summary.add_future_run_time(future_time); - process_summary->add_future_run_time(future_time); - } - } - break; - } - } - start++; - } - } - } - } - - // - // When we're doing future run predictions, we can create summaries for - // threads that have no run time, and no future run time. - // - // The way this happens is you have 2 or more cpus. - // On cpu 1, there is a blocking event for Thread T at time x. - // - // While walking through cpu 2's activity, you see T - // scheduled at x + N. You cannot add to T's future run - // time, and T never ran in the original time window. - // Thus, T is added and does nothing. - // - - // Remove inactive threads/processes. - auto& process_summaries = summary.mutable_process_summaries(); - auto process_it = process_summaries.begin(); - while (process_it != process_summaries.end()) { - auto next_process_it = process_it; - ++next_process_it; - if (process_it->total_run_time() == 0 && process_it->total_future_run_time() == 0) { - DEBUG_ONLY({ - for (auto& thread_summary : process_it->thread_summaries()) { - ASSERT(thread_summary.total_run_time() == 0 && thread_summary.total_future_run_time() == 0, "Process with 0 run time && 0 future run time has thread with non zero values"); - } - }); - process_summaries.erase(process_it); - } else { - // Our evil friend unordered_set returns const iterators... - auto& thread_summaries = const_cast*>(&*process_it)->mutable_thread_summaries(); - auto thread_it = thread_summaries.begin(); - while (thread_it != thread_summaries.end()) { - auto next_thread_it = thread_it; - ++next_thread_it; - if (thread_it->total_run_time() == 0 && thread_it->total_future_run_time() == 0) { - thread_summaries.erase(thread_it); - } - thread_it = next_thread_it; - } - } - process_it = next_process_it; - } - } - } - - // - // Calculate vmfault data. - // - // We want to calculate this after the future CPU time, because it is possible a time slice might have vmfaults - // that span the entire timespan. This could result in a process/thread with no run time, and no future time, which - // would be removed as "inactive" during future CPU time calculation. - // - - if (summary_cpu == NULL) { - // vmfault intervals are stored in the MachineThread - for (MachineThread* machine_thread : _threads_by_time) { - const MachineProcess* process = &machine_thread->process(); - - ProcessSummary* process_summary = NULL; - ThreadSummary* thread_summary = NULL; - - const auto& vm_faults = machine_thread->vm_faults(); - if (!vm_faults.empty()) { - AbsInterval vm_faults_timespan = AbsInterval(vm_faults.front().location(), vm_faults.back().max() - vm_faults.front().location()); - AbsInterval trimmed_timespan = summary_timespan.intersection_range(vm_faults_timespan); - - if (trimmed_timespan.length() > 0) { - auto start = interval_beginning_timespan(vm_faults, trimmed_timespan); - auto end = interval_ending_timespan(vm_faults, trimmed_timespan); - - ASSERT(!start || start->intersects(trimmed_timespan), "Sanity"); - ASSERT(!end || end->intersects(trimmed_timespan), "Sanity"); - ASSERT((!start && !end) || ((start && end) && (start <= end)), "Sanity"); - - if (start && end) { - // NOTE! <=, not <, because end is inclusive of data we want to count! - while (start <= end) { - // - // NOTE! summary_timespan, NOT trimmed_timespan! - // - // 8/25/13 ... Okay, why do we care summary vs trimmed? - // It shouldn't be possible for start to lie outside trimmed... - // Leaving this for now rather than introducing some bizzare - // corner case, but wth... - // - AbsInterval t = start->intersection_range(summary_timespan); - - ASSERT(t.length() > 0, "Might be too strong, but expecting this to be non-zero"); - - summary.add_vm_fault_time(t.length()); - - // We must initialize these lazily. If we don't, every process and thread gets - // a summary entry. But we don't want to keep looking them up over and over... - if (!process_summary) { - process_summary = summary.mutable_process_summary(process); - } - process_summary->add_vm_fault_time(t.length()); - - if (!thread_summary) { - thread_summary = process_summary->mutable_thread_summary(machine_thread); - } - thread_summary->add_vm_fault_time(t.length()); - - start++; - } - } - } - } - } - } - - - // - // Calculate IO activity data. - // - if (summary_cpu == NULL) { - // - // IO activity may overlap on even individual threads. - // - // All IO activity is stored in a single sorted vector, but - // it may overlap even at the thread level. There isn't an - // easy way to locate a starting and stopping point that intersect - // a given range. - // - // The solution being used is to flatten the overlapping IO - // and keep a sorted non overlapping list of IO activity. For any - // given timespan, we find the overlapping intervals of flattened - // IO activity and then look up the actual matching IOActivity - // objects. - // - if (!_all_io_active_intervals.empty()) { - AbsInterval io_timespan = AbsInterval(_all_io_active_intervals.front().location(), _all_io_active_intervals.back().max() - _all_io_active_intervals.front().location()); - AbsInterval trimmed_timespan = summary_timespan.intersection_range(io_timespan); - if (trimmed_timespan.length() > 0) { - // - // First find the flattened start point - // - if (auto flattened_start = interval_beginning_timespan(_all_io_active_intervals, trimmed_timespan)) { - // - // Now find the actual start IOActivity - // - auto it = std::lower_bound(_all_io.begin(), _all_io.end(), flattened_start->location(), AbsIntervalLocationVsAbsTimeComparator()); - ASSERT(it != _all_io.end(), "If we reach here, we should ALWAYS find a match!"); - - // We need <= in case there are multiple IOActivities ending at the same time - while (it != _all_io.end() && it->location() < summary_timespan.max()) { - AbsInterval t = it->intersection_range(summary_timespan); - - // Some of the ranges will not intersect at all, for example - // - // IOActivity - // - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXXXXX - // XXXXXXXX - // - // Summary Range - // - // SSSSSSSSSSSSSSSSSS - // - // The flattened_start will point at the oldest IOActivity - // which overlaps the summary range, but many of the later - // IOActivities will not overlap. - - if (t.length() > 0) { - // - // Wait time. - // - summary.add_io_time(t.length()); - - ProcessSummary* process_summary = summary.mutable_process_summary(&it->thread()->process()); - process_summary->add_io_time(t.length()); - - ThreadSummary* thread_summary = process_summary->mutable_thread_summary(it->thread()); - thread_summary->add_io_time(t.length()); - - // - // Bytes completed - // - if (summary_timespan.contains(it->max() - AbsTime(1))) { - summary.add_io_bytes_completed(it->size()); - process_summary->add_io_bytes_completed(it->size()); - thread_summary->add_io_bytes_completed(it->size()); - } - } - it++; - } - } - } - } - } - - // - // Calculate Jetsam activity data. - // - if (summary_cpu == NULL) { - // jetsam activity is stored in the MachineThread - for (MachineThread* machine_thread : _threads_by_time) { - const MachineProcess* process = &machine_thread->process(); - - ProcessSummary* process_summary = NULL; - ThreadSummary* thread_summary = NULL; - - const auto& jetsam_activity = machine_thread->jetsam_activity(); - if (!jetsam_activity.empty()) { - AbsInterval jetsam_timespan = AbsInterval(jetsam_activity.front().location(), jetsam_activity.back().max() - jetsam_activity.front().location()); - AbsInterval trimmed_timespan = summary_timespan.intersection_range(jetsam_timespan); - - if (trimmed_timespan.length() > 0) { - auto start = interval_beginning_timespan(jetsam_activity, trimmed_timespan); - auto end = interval_ending_timespan(jetsam_activity, trimmed_timespan); - - ASSERT(!start || start->intersects(trimmed_timespan), "Sanity"); - ASSERT(!end || end->intersects(trimmed_timespan), "Sanity"); - ASSERT((!start && !end) || ((start && end) && (start <= end)), "Sanity"); - - if (start && end) { - // NOTE! <=, not <, because end is inclusive of data we want to count! - while (start <= end) { - // - // NOTE! summary_timespan, NOT trimmed_timespan! - // - // 8/25/13 ... Okay, why do we care summary vs trimmed? - // It shouldn't be possible for start to lie outside trimmed... - // Leaving this for now rather than introducing some bizzare - // corner case, but wth... - // - AbsInterval t = start->intersection_range(summary_timespan); - - ASSERT(t.length() > 0, "Might be too strong, but expecting this to be non-zero"); - - summary.add_jetsam_time(t.length()); - - // We must initialize these lazily. If we don't, every process and thread gets - // a summary entry. But we don't want to keep looking them up over and over... - if (!process_summary) { - process_summary = summary.mutable_process_summary(process); - } - process_summary->add_jetsam_time(t.length()); - - if (!thread_summary) { - thread_summary = process_summary->mutable_thread_summary(machine_thread); - } - thread_summary->add_jetsam_time(t.length()); - - start++; - } - } - } - } - } - - // Jetsam kill times are stored in the process. - for (MachineProcess* machine_process : _processes_by_time) { - if (machine_process->is_exit_by_jetsam()) { - if (summary_timespan.contains(machine_process->exit_timestamp())) { - summary.increment_processes_jetsamed(); - summary.mutable_process_summary(machine_process)->set_jetsam_killed(); - } - } - } - } - - DEBUG_ONLY(summary.validate()); - - return summary; -} - -template -uint32_t Machine::active_cpus() const { - uint32_t cpus = 0; - - for (auto& cpu : _cpus) { - if (!cpu.timeline().empty()) { - cpus++; - } - } - - return cpus; -} - -// This attempts to analyze various pieces of data and guess -// if the Machine represents an ios device or not. - -template -bool Machine::is_ios() const { - // I looked at avg intr time, and min intr time; they were too close for - // reliable detection of desktop vs device (desktop has intr(s) as short - // as 60ns). - - // For now, we're just going to do a really gross detection, in any trace - // from a device we'd expect to see SpringBoard or backboardd. - - for (auto process : _processes_by_time) { - if (strcmp(process->name(), "SpringBoard") == 0) - return true; - if (strcmp(process->name(), "backboardd") == 0) - return true; - } - - return false; -} diff --git a/KDBG/Machine.mutable-impl.hpp b/KDBG/Machine.mutable-impl.hpp deleted file mode 100644 index 314ecd0..0000000 --- a/KDBG/Machine.mutable-impl.hpp +++ /dev/null @@ -1,1128 +0,0 @@ -// -// Machine.mutable-impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - -template -MachineProcess* Machine::create_process(pid_t pid, const char* name, AbsTime create_timestamp, kMachineProcessFlag flags) { - ASSERT(name, "Sanity"); - - // Validate that we are not creating a process that already exists - DEBUG_ONLY({ - ASSERT(_processes_by_pid.size() == _processes_by_name.size(), "Sanity"); - ASSERT(_processes_by_pid.size() == _processes_by_time.size(), "Sanity"); - - auto by_pid_range = _processes_by_pid.equal_range(pid); - for (auto it = by_pid_range.first; it != by_pid_range.second; ++it) { - MachineProcess& process = it->second; - ASSERT(!process.timespan().contains(create_timestamp), "Creating a process that overlaps an existing process"); - } - - auto by_name_range = _processes_by_name.equal_range(name); - for (auto it = by_name_range.first; it != by_name_range.second; ++it) { - MachineProcess& process = *it->second; - ASSERT((process.pid() != pid) || (!process.timespan().contains(create_timestamp)), "Creating a process that overlaps an existing process"); - } - - // The "by time" vector is unsorted during construction, we have to look at everything. - for (MachineProcess* process : _processes_by_time) { - if (process->pid() == pid) { - ASSERT(!process->timespan().contains(create_timestamp), "Creating a process that overlaps an existing process"); - } - } - }) - - if (MachineProcess* about_to_be_reused_process = youngest_mutable_process(pid)) { - // If this process is still alive, we're going to be replacing it. - // The only legal way of doing that is an exec. Validate. - if (!about_to_be_reused_process->is_trace_terminated()) { - DEBUG_ONLY({ - ASSERT((uint32_t)flags & ((uint32_t)kMachineProcessFlag::CreatedByForkExecEvent | (uint32_t)kMachineProcessFlag::CreatedByExecEvent), - "Replacing existing process without exec or fork-exec"); - }) - // - // Exit by exec is unique in that we will have two processes/threads - // back to back in the timeline. We do not want them to overlap, and - // the new process timeline is half open , and will have this time as - // its creation. Pass a 1 mabs older time to exit to prevent overlap - about_to_be_reused_process->set_exit_by_exec(create_timestamp - AbsTime(1)); - } - ASSERT(about_to_be_reused_process->is_trace_terminated(), "Sanity"); - } - - MachineProcess* process = &_processes_by_pid.emplace(pid, MachineProcess(pid, name, create_timestamp, flags))->second; - _processes_by_name.emplace(process->name(), process); - _processes_by_time.push_back(process); - - return process; -} - -template -MachineThread* Machine::create_thread(MachineProcess* process, typename SIZE::ptr_t tid, MachineVoucher* voucher, AbsTime create_timestamp, kMachineThreadFlag flags) { - ASSERT(process, "Sanity"); - - // Validate that we are not creating a thread that already exists - DEBUG_ONLY({ - ASSERT(_threads_by_tid.size() == _threads_by_time.size(), "Sanity"); - - auto by_tid_range = _threads_by_tid.equal_range(tid); - for (auto it = by_tid_range.first; it != by_tid_range.second; ++it) { - MachineThread& thread = it->second; - ASSERT(!thread.timespan().contains(create_timestamp), "Creating a thread that overlaps an existing thread"); - } - - // The "by time" vector is unsorted during construction, we have to look at everything - for (MachineThread* thread : _threads_by_time) { - if (thread->tid() == tid) { - ASSERT(!thread->timespan().contains(create_timestamp), "Creating a thread that overlaps an existing thread"); - } - } - }) - - // Currently the only way we intentionally re-use live threads is via exec/fork-exec. - // The exec/fork-exec code calls create_process first, which should mark all existing - // threads as trace-terminated. So we should NEVER see a live thread at this point. - // validate. - DEBUG_ONLY({ - if (MachineThread* about_to_be_reused_thread = youngest_mutable_thread(tid)) { - ASSERT(about_to_be_reused_thread->is_trace_terminated(), "Expected this thread to be terminated"); - } - }); - - MachineThread* thread = &_threads_by_tid.emplace(tid, MachineThread(process, tid, voucher, create_timestamp, flags))->second; - _threads_by_time.push_back(thread); - - return thread; -} - -template -MachineVoucher* Machine::create_voucher(typename SIZE::ptr_t address, AbsTime create_timestamp, kMachineVoucherFlag flags, uint32_t content_bytes_capacity) { - ASSERT(address, "Should not be NULL"); - ASSERT(content_bytes_capacity < 4096, "Probably an error"); // This is a guesstimate, may need re-evaluation - - MachineVoucher* voucher; - - ASSERT(_voucher_nursery.find(address) == _voucher_nursery.end(), "Attempt to create an already live voucher ()"); - // - // There is no real workaround for this. Other tracepoints will use the address, bad things happen. You can't fix ordering bugs with cleverness outside the lock :-). - // - // voucher create / destroy tracepoints are outside the hashtable lock - - auto workaround_it = _voucher_nursery.find(address); - if (workaround_it != _voucher_nursery.end()) { - // We've hit a race condition, this voucher was used before the create event was posted. - // We want to update the content_bytes_capacity, but not the create_timestamp. - voucher = workaround_it->second.get(); - voucher->workaround_16898190(flags, content_bytes_capacity); - } else { - auto it = _voucher_nursery.emplace(address, std::make_unique>(address, AbsInterval(create_timestamp, AbsTime(0)), flags, content_bytes_capacity)); - ASSERT(it.second, "Voucher emplace in nursery failed"); - voucher = it.first->second.get(); - } - - ASSERT(voucher->is_live(), "Sanity"); - ASSERT(!voucher->is_null(), "Sanity"); - ASSERT(!voucher->is_unset(), "Sanity"); - - return voucher; -} - -template -void Machine::destroy_voucher(typename SIZE::ptr_t address, AbsTime timestamp) { - ASSERT(address, "Should not be NULL"); - - auto nursery_it = _voucher_nursery.find(address); - - // We need a voucher for every reference, so we are in the odd position - // of creating a voucher so we can destroy it. - if (nursery_it == _voucher_nursery.end()) { - create_voucher(address, AbsTime(0), kMachineVoucherFlag::CreatedByFirstUse, 0); - nursery_it = _voucher_nursery.find(address); - } - - MachineVoucher* voucher = nursery_it->second.get(); - - voucher->set_destroyed(timestamp); - - // First find the "row" for this address. - auto by_addr_it = _vouchers_by_addr.find(address); - if (by_addr_it == _vouchers_by_addr.end()) { - // No address entry case - //std::vector>> row(std::move(nursery_it->second)); - std::vector>> row; - row.emplace_back(std::move(nursery_it->second)); - _vouchers_by_addr.emplace(address, std::move(row)); - } else { - auto& row = by_addr_it->second; - - // Make sure these are sorted and non-overlapping - ASSERT(row.back()->timespan() < voucher->timespan(), "Sanity"); - ASSERT(!row.back()->timespan().intersects(voucher->timespan()), "Sanity"); - - row.emplace_back(std::move(nursery_it->second)); - } - - _voucher_nursery.erase(nursery_it); -} - -// -// This function handles looking up a voucher by address. If neccessary, it will create a new voucher. -// NOTE! Does not update voucher timestamps, that is only done at voucher destroy. -// - -template -MachineVoucher* Machine::process_event_voucher_lookup(typename SIZE::ptr_t address, uint32_t msgh_bits) { - // NOTE! There is a subtle race here, we *MUST* test msgh_bits before - // checking for a 0 address. An unset voucher may have address 0... - if (MACH_MSGH_BITS_VOUCHER(msgh_bits) == MACH_MSGH_BITS_ZERO) - return &UnsetVoucher; - - if (address == 0) - return &NullVoucher; - - auto nursery_it = _voucher_nursery.find(address); - if (nursery_it == _voucher_nursery.end()) { - // If no voucher exists, create a default (no-contents!) voucher. - return create_voucher(address, AbsTime(0), kMachineVoucherFlag::CreatedByFirstUse, 0); - } - - return nursery_it->second.get(); -} - -template -MachineVoucher* Machine::thread_forwarding_voucher_lookup(const MachineVoucher* previous_machine_state_voucher) { - ASSERT(previous_machine_state_voucher, "Sanity"); - - if (previous_machine_state_voucher == &UnsetVoucher) - return &UnsetVoucher; - - if (previous_machine_state_voucher == &NullVoucher) - return &NullVoucher; - - auto nursery_it = _voucher_nursery.find(previous_machine_state_voucher->address()); - if (nursery_it == _voucher_nursery.end()) { - ASSERT(false, "Should not ever have a thread forwarding a voucher not in the nursery"); - return &UnsetVoucher; - } - - return nursery_it->second.get(); -} - -// -// This is used by processes that are being fork-exec'd / exec'd. They must be -// created with some name, but it isn't their final name. For now, we are -// heavily ASSERTING state to only allow processes which are fork-exec'd / -// exec'd to set their name. -// -template -void Machine::set_process_name(MachineProcess* process, const char* name) { - ASSERT(process, "Sanity"); - ASSERT(process->is_created_by_fork_exec() || process->is_created_by_exec(), "Sanity"); - ASSERT(process->threads().size() == 1, "Sanity"); - ASSERT(process->is_fork_exec_in_progress() || process->is_exec_in_progress(), "Sanity"); - ASSERT(name, "Sanity"); - - auto by_name_range = _processes_by_name.equal_range(process->name()); - for (auto it = by_name_range.first; it != by_name_range.second; ++it) { - if (process == it->second) { - _processes_by_name.erase(it); - process->set_name(name); - _processes_by_name.emplace(process->name(), process); - return; - } - } - - ASSERT(false, "Attempt to rename did not find a matching process"); -} - -// -// The "youngest" process/thread lookups are used during event processing, -// where we often must look up a process/thread that hasn't been updated -// to reflect current timespans. A time based lookup would fail. -// -template -MachineProcess* Machine::youngest_mutable_process(pid_t pid) { - MachineProcess* youngest_process = nullptr; - auto by_pid_range = _processes_by_pid.equal_range(pid); - for (auto it = by_pid_range.first; it != by_pid_range.second; ++it) { - MachineProcess& process = it->second; - // Larger times are newer (younger) - if (!youngest_process || process.timespan().location() > youngest_process->timespan().location()) { - youngest_process = &process; - } - } - - return youngest_process; -} - -template -MachineThread* Machine::youngest_mutable_thread(typename SIZE::ptr_t tid) { - MachineThread* youngest_thread = nullptr; - auto by_tid_range = _threads_by_tid.equal_range(tid); - for (auto it = by_tid_range.first; it != by_tid_range.second; ++it) { - MachineThread& thread = it->second; - // Larger times are newer (younger) - if (!youngest_thread || thread.timespan().location() > youngest_thread->timespan().location()) { - youngest_thread = &thread; - } - } - - return youngest_thread; -} - -// -// This function handles looking up a thread by tid. If neccessary, it will create a new thread -// and process. Any thread / process that are looked up or created will have their timestamps updated. -// -template -MachineThread* Machine::process_event_tid_lookup(typename SIZE::ptr_t tid, AbsTime now) { - MachineThread* thread = youngest_mutable_thread(tid); - - if (!thread) { - // This is an "unknown" thread. We have no information about its name or parent process. - char unknown_process_name[20]; - snprintf(unknown_process_name, sizeof(unknown_process_name), "unknown-%llX", (uint64_t)tid); - - // - // Strongly considering just requiring this to be valid, and never allowing an unknown thread. - // - printf("UNKNOWN TID FAIL! unknonwn tid %llx\n", (int64_t)tid); - ASSERT(false, "unknown TID fail"); - - MachineProcess* unknown_process = create_process(next_unknown_pid(), unknown_process_name, now, kMachineProcessFlag::IsUnknownProcess); - thread = create_thread(unknown_process, tid, &UnsetVoucher, now, kMachineThreadFlag::CreatedByUnknownTidInTrace); - unknown_process->add_thread(thread); - } - - ASSERT(thread, "Sanity"); - ASSERT(!thread->is_trace_terminated(), "Event tid seen after trace termination"); - ASSERT(!thread->process().is_trace_terminated(), "Event pid seen after trace termination"); - - return thread; -} - -// -// See comments in task_policy.c for full explanation of trequested_0 & trequested_1. -// -// process_trequested_task means that the tracepoint either had a NULL thread, or specified that the tracepoint was targeted at task level. -// This only matters in 32 bit traces, where it takes both trequested_0 and trequested_1 to carry task or thread requested data. -// -// For now, there is nothing we want to see in thread_requested data. -// -template -void Machine::process_trequested_task(pid_t pid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1) { - TaskRequestedPolicy task_requested = (SIZE::is_64_bit) ? TaskRequestedPolicy(trequested_0) : TaskRequestedPolicy((Kernel32::ptr_t)trequested_0, (Kernel32::ptr_t)trequested_1); - - if (uint32_t apptype = (uint32_t)task_requested.as_struct().t_apptype) { - if (pid) { - if (MachineProcess* target = youngest_mutable_process(pid)) { - target->set_apptype_from_trequested(apptype); - } - } - } -} - -template -void Machine::process_trequested_thread(typename SIZE::ptr_t tid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1) { - TaskRequestedPolicy task_requested = (SIZE::is_64_bit) ? TaskRequestedPolicy(trequested_0) : TaskRequestedPolicy((Kernel32::ptr_t)trequested_0, (Kernel32::ptr_t)trequested_1); - - if (uint32_t apptype = (uint32_t)task_requested.as_struct().t_apptype) { - if (MachineThread* target_thread = youngest_mutable_thread(tid)) { - target_thread->mutable_process().set_apptype_from_trequested(apptype); - } - } -} - -#define AST_PREEMPT 0x01 -#define AST_QUANTUM 0x02 -#define AST_URGENT 0x04 -#define AST_HANDOFF 0x08 -#define AST_YIELD 0x10 - -#define TRACE_DATA_NEWTHREAD 0x07000004 -#define TRACE_STRING_NEWTHREAD 0x07010004 -#define TRACE_DATA_EXEC 0x07000008 -#define TRACE_STRING_EXEC 0x07010008 -#define TRACE_LOST_EVENTS 0x07020008 - -// From ./osfmk/i386/mp.c -#define TRACE_MP_CPU_DEACTIVATE MACHDBG_CODE(DBG_MACH_MP, 7) - -// From osfmk/kern/task.h -#define TASK_POLICY_TASK 0x4 -#define TASK_POLICY_THREAD 0x8 - -template -bool Machine::process_event(const KDEvent& event) -{ - ASSERT(!lost_events(), "Should not be processing events after TRACE_LOST_EVENTS"); - - AbsTime now = event.timestamp(); - ASSERT(event.cpu() > -1 && event.cpu() < _cpus.size(), "cpu_id out of range"); - MachineCPU& cpu = _cpus[event.cpu()]; - - if (!cpu.is_iop()) { - // - // If we have lost events, immediately bail. - // - // Pre-process events known to have bogus TID's: - // - // DBG_TRACE_INFO events may not have a valid TID. - // MACH_IPC_VOUCHER_CREATE_ATTR_DATA do not have a valid TID, - // - - switch (event.dbg_cooked()) { - case TRACEDBG_CODE(DBG_TRACE_INFO, 1): // kernel_debug_early_end() - case TRACEDBG_CODE(DBG_TRACE_INFO, 4): // kernel_debug_string() - return true; - - case TRACEDBG_CODE(DBG_TRACE_INFO, 2): // TRACE_LOST_EVENTS - set_flags(kMachineFlag::LostEvents); - return false; - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_CREATE_ATTR_DATA): - // trace event data is - // data, data, data, data - // - // event tid is voucher address! - if (auto voucher = process_event_voucher_lookup(event.tid(), UINT32_MAX)) { - voucher->add_content_bytes(event.arg1_as_pointer()); - } - return true; - - default: - break; - } - - MachineThread* event_thread = process_event_tid_lookup(event.tid(), now); - - switch (event.dbg_cooked()) { - case BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_EXIT): // the exit syscall never returns, use this instead - // arg1 == pid exiting - // arg2 == exit code - if (event.is_func_end()) { - // can BSD_PROC_EXIT can be called from another context? - ASSERT((pid_t)event.arg1() == event_thread->process().pid(), "proc_exit pid does not match context pid"); - event_thread->mutable_process().set_exit_by_syscall(now, (int32_t)event.arg2()); - } - break; - - case TRACE_DATA_NEWTHREAD: { - ASSERT(event.is_func_none(), "TRACE_DATA_NEWTHREAD event has start/end bit set. Should be func_none."); - // - // This is called by the thread creating the new thread. - // - // The thread id of the new thread is in arg1. - // The pid of the process creating the new thread is in arg2. - // - // NOTE! This event carries enough information to create a thread, which we do. - // However, the immediately following TRACE_STRING_NEWTHREAD does not have the - // newly_created thread's tid. We cannot assume that we will always be able to - // read these events as a pair, they may be split by a particularly unlucky - // buffer snapshot. - // - // We have a "thread nursery" which we use to associate the tid of the new - // thread with the creating thread. - // - // (During fork operations, the "parent" may appear different than the child, - // this is why we cannot reuse the parent's name and ignore the STRING event.) - // - auto new_thread_id = (typename SIZE::ptr_t)event.arg1(); - auto new_thread_pid = (int32_t)event.arg2(); - - MachineProcess* new_process = youngest_mutable_process(new_thread_pid); - kMachineThreadFlag new_thread_flags; - - // - // Okay, it looks like we cannot pay much attention to the source of thread - // creates, the system will create a thread for anyone at any time, in any - // place. The new model is to lookup the pid of the new thread, and if it - // exists and is live, use that. Otherwise, fork-exec a new process. - // - - if (new_process) { - new_thread_flags = kMachineThreadFlag::CreatedByTraceDataNewThread; - } else { - new_thread_flags = (kMachineThreadFlag)((uint32_t)kMachineThreadFlag::CreatedByForkExecEvent | - (uint32_t)kMachineThreadFlag::IsMain); - - auto new_process_flags = (kMachineProcessFlag)((uint32_t)kMachineProcessFlag::CreatedByForkExecEvent | - (uint32_t)kMachineProcessFlag::IsForkExecInProgress); - - // Create the new process - new_process = create_process(new_thread_pid, "###Fork#Exec###", now, new_process_flags); - } - ASSERT(new_process, "Sanity"); - ASSERT(!new_process->is_trace_terminated(), "Sanity"); - ASSERT(new_thread_pid != 0 || new_process == _kernel_task, "Sanity"); - new_process->add_thread(create_thread(new_process, new_thread_id, &UnsetVoucher, now, new_thread_flags)); - break; - } - - case TRACEDBG_CODE(DBG_TRACE_DATA, TRACE_DATA_THREAD_TERMINATE): { - ASSERT(event.is_func_none(), "Sanity"); - typename SIZE::ptr_t terminated_tid = event.arg1(); - // If tid == terminated_tid, we need to handle the lookup below differently - ASSERT(event.tid() != terminated_tid, "Should not be possible"); - MachineThread* terminated_thread = process_event_tid_lookup(terminated_tid, now); - terminated_thread->set_trace_terminated(now); - - // Was this the last thread for a given process? - bool all_threads_trace_terminated = true; - MachineProcess& process = terminated_thread->mutable_process(); - for (auto thread : process.threads()) { - if (!thread->is_trace_terminated()) { - all_threads_trace_terminated = false; - break; - } - } - - if (all_threads_trace_terminated) { - process.set_trace_terminated(now); - } - break; - } - - case TRACE_DATA_EXEC: { - ASSERT(event.is_func_none(), "TRACE_DATA_EXEC event has start/end bit set. Should be func_none."); - - ASSERT(!event_thread->is_trace_terminated(), "Thread that is trace terminated is exec'ing"); - ASSERT(!event_thread->process().is_kernel(), "Kernel process is exec'ing"); - ASSERT(!event_thread->is_idle_thread(), "IDLE thread is exec'ing"); - - // arg1 == pid - int32_t exec_pid = (int32_t)event.arg1(); - ASSERT(exec_pid != -1, "Kernel thread is exec'ing"); - ASSERT(exec_pid == event_thread->process().pid() || event_thread->process().is_unknown(), "Pids should match. If not, maybe vfork?"); - - if (event_thread->process().is_fork_exec_in_progress()) { - ASSERT(event_thread->process().threads().size() == 1, "Fork invariant violated"); - // event_thread->mutable_process().clear_fork_exec_in_progress(); - - // Hmmm.. Do we need to propagate an apptype here? - } else { - // - // Creating a new process will automagically clean up the - // existing one, setting the last known timestamp, and "PidReused" - // - auto exec_thread_flags = (kMachineThreadFlag)((uint32_t)kMachineThreadFlag::CreatedByExecEvent | - (uint32_t)kMachineThreadFlag::IsMain); - - auto exec_process_flags = (kMachineProcessFlag)((uint32_t)kMachineProcessFlag::CreatedByExecEvent | - (uint32_t)kMachineProcessFlag::IsExecInProgress); - - auto exec_process = create_process(exec_pid, "###Exec###", now, exec_process_flags); - MachineThread* exec_thread = create_thread(exec_process, event_thread->tid(), &UnsetVoucher, now, exec_thread_flags); - exec_process->add_thread(exec_thread); - - int32_t apptype = event_thread->process().apptype(); - if (apptype != -1) { - exec_process->set_apptype(apptype); - } - } - break; - } - - case TRACE_STRING_EXEC: { - ASSERT(event.is_func_none(), "TRACE_STRING_EXEC event has start/end bit set. Should be func_none."); - ASSERT(event_thread->mutable_process().is_exec_in_progress() || - event_thread->mutable_process().is_fork_exec_in_progress(), "Must be exec or fork-exec in progress to be here"); - - set_process_name(&event_thread->mutable_process(), event.all_args_as_string().c_str()); - - if (event_thread->process().is_exec_in_progress()) - event_thread->mutable_process().clear_exec_in_progress(); - else - event_thread->mutable_process().clear_fork_exec_in_progress(); - break; - } - - case MACHDBG_CODE(DBG_MACH_EXCP_INTR, 0): - if (event.is_func_start()) { - cpu.set_intr(now); - } else { - cpu.clear_intr(now); - } - break; - - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED): - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_HANDOFF): { - // The is deactivate switch to idle thread should have happened before we see an actual - // context switch for this cpu. - ASSERT(!cpu.is_deactivate_switch_to_idle_thread(), "State machine fail"); - - typename SIZE::ptr_t handoff_tid = event.arg2(); - // If the handoff tid and the event_tid are the same, the lookup will fail an assert due to timestamps going backwards. - MachineThread* handoff_thread = (handoff_tid == event.tid()) ? event_thread : process_event_tid_lookup(handoff_tid, now); - ASSERT(handoff_thread, "Sanity"); - - // If we marked a given thread as unrunnable in idle, or the MKRUNNABLE wasn't emitted, make sure we - // mark the thread as runnable now. - handoff_thread->make_runnable(now); - cpu.context_switch(handoff_thread, event_thread, now); - - if (!event_thread->is_idle_thread()) { - if (event_thread->tid() != event.arg2()) { - if ((event.arg1() & (AST_PREEMPT | AST_QUANTUM | AST_URGENT | AST_HANDOFF | AST_YIELD)) == 0) { - event_thread->make_unrunnable(now); - } - } - } - break; - } - - // - // There is a rare case of: - // - // event[795176] { timestamp=4b8074fa6bb5, arg1=0, arg2=0, arg3=0, arg4=0, tid=8ab77, end MP_CPU_DEACTIVATE, cpu=1 } - // event[795177] { timestamp=4b8074fa70bd, arg1=8ab77, arg2=ffffffffffffffff, arg3=0, arg4=4, tid=2d, --- MACH_SCHED_CHOOSE_PROCESSOR, cpu=1 } - // - // When a cpu shuts down via MP_CPU_DEACTIVATE, on reactivation, the cpu does a forced switch to its idle thread, - // without dropping a MACH_SCHED or MACH_STACK_HANDOFF. We want to catch this and update the cpu correctly, as - // well as marking the idle thread. - // - // This is a desktop only codepath, TRACE_MP_CPU_DEACTIVATE is defined in ./osfmk/i386/mp.c - // - case TRACE_MP_CPU_DEACTIVATE: - ASSERT(event_thread == cpu.thread() || !cpu.is_thread_state_initialized(), "Sanity"); - if (event.is_func_end()) { - cpu.set_deactivate_switch_to_idle_thread(); - } - break; - - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_CHOOSE_PROCESSOR): - // - // I have seen a sequence of events like this, where it appears that multiple threads get re-dispatched: - // - // event[254871] { timestamp=332dd22319b, arg1=0, arg2=0, arg3=0, arg4=0, tid=1b8ab, end MP_CPU_DEACTIVATE, cpu=7 } - // event[254876] { timestamp=332dd22387a, arg1=1b7d9, arg2=ffffffffffffffff, arg3=e, arg4=4, tid=1b8ab, --- MACH_SCHED_CHOOSE_PROCESSOR, cpu=7 } - // event[254877] { timestamp=332dd223c44, arg1=e, arg2=0, arg3=0, arg4=0, tid=1b8ab, --- MACH_SCHED_REMOTE_AST, cpu=7 } - // event[254887] { timestamp=332dd22441c, arg1=1b8ab, arg2=ffffffffffffffff, arg3=4, arg4=4, tid=53, --- MACH_SCHED_CHOOSE_PROCESSOR, cpu=7 } - // - // We will wait until we see a tid mismatch before clearing the deactivate_switch state - // - if (cpu.is_deactivate_switch_to_idle_thread()) { - if (cpu.thread() == NULL || event_thread->tid() != cpu.thread()->tid()) { - // The choose tracepoint has the tid of the thread on cpu when it deactivated. - ASSERT(cpu.thread() == NULL || cpu.thread()->tid() == event.arg1(), "Sanity"); - - cpu.clear_deactivate_switch_to_idle_thread(); - event_thread->set_is_idle_thread(); - event_thread->make_runnable(now); - cpu.context_switch(event_thread, cpu.thread(), now); - } - } - break; - - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_MAKE_RUNNABLE): - event_thread->make_runnable(now); - break; - - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_IDLE): - if (event.is_func_start()) { - cpu.set_idle(now); - } else { - cpu.clear_idle(now); - } - break; - - case MACHDBG_CODE(DBG_MACH_VM, 2 /* MACH_vmfault is hardcoded as 2 */): - if (event.is_func_start()) - event_thread->begin_vm_fault(now); - else - event_thread->end_vm_fault(now); - break; - - case BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_JETSAM): - case BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_JETSAM_HIWAT): - if (event.is_func_end()) { - if (pid_t pid = (pid_t)event.arg2()) { - // - // The time for this kill is already covered by the MEMSTAT_scan. - // We still want to mark the victim process as jetsam killed, though. - // We need to look up the victim, which is the pid in arg2. - // - if (MachineProcess* victim = youngest_mutable_process(pid)) { - ASSERT(!victim->is_exiting(), "Jetsam killing already dead process"); - // This isn't technically impossible, but as a practical matter it is more likely - // signalling a bug than we were able to wrap the pid counter and reuse this pid - ASSERT(!victim->is_kernel(), "Cannot jetsam kernel"); - victim->set_exit_by_jetsam(now); - } else { - ASSERT(false, "Unable to find jetsam victim pid"); - } - } - } - break; - - case BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_SCAN): - case BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_UPDATE): - case BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_FREEZE): - if (event.is_func_start()) - event_thread->begin_jetsam_activity(event.dbg_cooked(), now); - else - event_thread->end_jetsam_activity(event.dbg_cooked(), now); - break; - - // - // IMP_TASK_APPTYPE trace args are: - // - // start: - // target_pid, trequested_0, trequested_1, apptype - // end: - // target_pid, trequested_0, trequested_1, is_importance_receiver - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_NONE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_INTERACTIVE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_STANDARD): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_ADAPTIVE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_BACKGROUND): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_APP_DEFAULT): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_APP_TAL): - // - // We want to set the explicit apptype now, and trequested will not have the - // apptype data until the end event. - // - if (event.is_func_start()) { - if (pid_t pid = (pid_t)event.arg1()) { - if (MachineProcess* target = youngest_mutable_process(pid)) { - target->set_apptype((uint32_t)event.arg4()); - } - } - } - process_trequested_task((pid_t)event.arg1(), event.arg2(), event.arg3()); - break; - - // Trace data is - // self_pid, audit_token_pid_from_task(task), trequested_0(task, NULL), trequested_1(task, NULL) - case IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, 0): - case IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, 1): - case IMPORTANCE_CODE(IMP_BOOST, IMP_BOOSTED): - case IMPORTANCE_CODE(IMP_BOOST, IMP_UNBOOSTED): - process_trequested_task((pid_t)event.arg2(), event.arg3(), event.arg4()); - break; - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_THREAD_SET_VOUCHER): { - // - // This can be invoked against another thread; you must use arg1 as the tid. - // - // thread-tid, name, voucher, callsite-id - // - auto set_thread_tid = event.arg1(); - MachineThread* set_thread = (set_thread_tid == event.tid()) ? event_thread : process_event_tid_lookup(set_thread_tid, now); - set_thread->set_voucher(process_event_voucher_lookup(event.arg3(), UINT32_MAX), now); - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_CREATE): - // trace event data is - // voucher address, voucher table size, system voucher count, voucher content bytes - create_voucher(event.arg1(), now, kMachineVoucherFlag::CreatedByVoucherCreate, (uint32_t)event.arg4()); - break; - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_DESTROY): - destroy_voucher(event.arg1(), now); - break; - - // The MachMsg state chart... - // - // The "key" to the mach msg is the kmsg_addr. - // - // We can encounter a given kmsg_addr in any of - // four possible states: - // - // UNINITIALIZED - // SEND - // RECV - // FREE - // - // These are the legal state transitions: - // (transition to UNINITIALIZED is not possible) - // - // UNIN -> SEND ; Accept as FREE -> SEND - // UNIN -> RECV ; Accept as SEND -> RECV - // UNIN -> FREE ; Accept as FREE -> FREE - // - // SEND -> SEND ; ERROR! - // SEND -> RECV ; User to User IPC, send message to machine - // SEND -> FREE ; User to Kernel IPC, recycle. - // - // RECV -> SEND ; ERROR! - // RECV -> RECV ; ERROR! - // RECV -> FREE ; End User IPC - // - // FREE -> SEND ; Begin User IPC - // FREE -> RECV ; Kernel to User IPC - // FREE -> FREE ; Kernel to Kernel IPC - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_SEND): { - // trace event data is: - // kmsg_addr, msgh_bits, msgh_id, voucher_addr, - auto kmsg_addr = event.arg1(); - auto msgh_bits = (uint32_t)event.arg2(); - auto msgh_id = (uint32_t)event.arg3(); - auto voucher_addr = event.arg4(); - - auto nursery_it = _mach_msg_nursery.find(kmsg_addr); - if (nursery_it == _mach_msg_nursery.end()) { - nursery_it = _mach_msg_nursery.emplace(kmsg_addr, kmsg_addr).first; - } - - auto& nursery_msg = nursery_it->second; - - switch (nursery_msg.state()) { - // SEND -> SEND ; ERROR! - // RECV -> SEND ; ERROR! - case kNurseryMachMsgState::Send: - ASSERT(false, "illegal state transition (SEND -> SEND) in nursery mach msg"); - case kNurseryMachMsgState::Recv: - ASSERT(false, "illegal state transition (RECV -> SEND) in nursery mach msg"); - break; - - // UNIN -> SEND ; Accept as FREE -> SEND - // FREE -> SEND ; Begin User IPC - case kNurseryMachMsgState::Uninitialized: - case kNurseryMachMsgState::Free: { - uintptr_t event_index = &event - _events; - nursery_msg.send(event_index, event.timestamp(), event.tid(), kmsg_addr, msgh_bits, msgh_id, process_event_voucher_lookup(voucher_addr, msgh_bits)); - break; - } - } - // We do the state set here so that release builds - // sync to current state when errors are encountered - nursery_msg.set_state(kNurseryMachMsgState::Send); - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV): - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV_VOUCHER_REFUSED): - { - // trace event data is - // kmsg_addr, msgh_bits, msgh_id, voucher_addr - auto kmsg_addr = event.arg1(); - auto msgh_bits = (uint32_t)event.arg2(); - auto voucher_addr = event.arg4(); - - auto nursery_it = _mach_msg_nursery.find(kmsg_addr); - if (nursery_it == _mach_msg_nursery.end()) { - nursery_it = _mach_msg_nursery.emplace(kmsg_addr, kmsg_addr).first; - } - - auto& nursery_msg = nursery_it->second; - - uint32_t flags = (event.dbg_code() == MACH_IPC_MSG_RECV_VOUCHER_REFUSED) ? kMachineMachMsgFlag::IsVoucherRefused : 0; - uintptr_t event_index = &event - _events; - - switch (nursery_msg.state()) { - - // UNIN -> RECV ; Accept as SEND -> RECV - case kNurseryMachMsgState::Uninitialized: { - flags |= kMachineMachMsgFlag::HasReceiver; - - auto mach_msg_it = _mach_msgs.emplace(_mach_msgs.end(), - NurseryMachMsg::message_id(), - kmsg_addr, - flags, - AbsTime(0), - 0, - 0, - &Machine::UnsetVoucher, - now, - event.tid(), - msgh_bits, - process_event_voucher_lookup(voucher_addr, msgh_bits)); - - ASSERT(_mach_msgs_by_event_index.find(event_index) == _mach_msgs_by_event_index.end(), "Stomping mach msg"); - _mach_msgs_by_event_index[event_index] = std::distance(_mach_msgs.begin(), mach_msg_it); - break; - } - - // SEND -> RECV ; User to User IPC, send message to machine - case kNurseryMachMsgState::Send: { - ASSERT(kmsg_addr == nursery_msg.kmsg_addr(), "Sanity"); - ASSERT((uint32_t)event.arg3() == nursery_msg.send_msgh_id(), "Sanity"); - - flags |= (kMachineMachMsgFlag::HasSender | kMachineMachMsgFlag::HasReceiver); - - auto mach_msg_it = _mach_msgs.emplace(_mach_msgs.end(), - nursery_msg.id(), - kmsg_addr, - flags, - nursery_msg.send_time(), - nursery_msg.send_tid(), - nursery_msg.send_msgh_bits(), - nursery_msg.send_voucher(), - now, - event.tid(), - msgh_bits, - process_event_voucher_lookup(voucher_addr, msgh_bits)); - - intptr_t send_event_index = nursery_msg.send_event_index(); - if (send_event_index != -1) { - ASSERT(send_event_index < _event_count, "Sanity"); - ASSERT(_mach_msgs_by_event_index.find(event_index) == _mach_msgs_by_event_index.end(), "Stomping mach msg"); - _mach_msgs_by_event_index[send_event_index] = std::distance(_mach_msgs.begin(), mach_msg_it); - } - ASSERT(_mach_msgs_by_event_index.find(event_index) == _mach_msgs_by_event_index.end(), "Stomping mach msg"); - _mach_msgs_by_event_index[event_index] = std::distance(_mach_msgs.begin(), mach_msg_it); - break; - } - - // RECV -> RECV ; ERROR! - case kNurseryMachMsgState::Recv: - ASSERT(false, "illegal state transition (RECV -> RECV) in nursery mach msg"); - break; - - // FREE -> RECV ; Kernel to User IPC - case kNurseryMachMsgState::Free: - break; - } - - // We do the state set here so that release builds - // sync to current state when errors are encountered - nursery_msg.set_state(kNurseryMachMsgState::Recv); - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_KMSG_FREE): { - // trace event data is: - // kmsg_addr - - auto kmsg_addr = event.arg1(); - - auto nursery_it = _mach_msg_nursery.find(kmsg_addr); - if (nursery_it == _mach_msg_nursery.end()) { - nursery_it = _mach_msg_nursery.emplace(kmsg_addr, kmsg_addr).first; - } - - auto& nursery_msg = nursery_it->second; - - - // All transitions to FREE are legal. - nursery_msg.set_state(kNurseryMachMsgState::Free); - } - - default: - // IO Activity - // - // There isn't an easy way to handle these inside the switch, The - // code is used as a bitfield. - - - // - // Okay temp note on how to approach this. - // - // Even a single thread may have overlapping IO activity. - // None of the current scheme's handle overlapped activity well. - // - // We'd like to be able to show for any given interval, "X pages IO outstanding, Y pages completed, Z ms waiting" - // - // To do that, we've got to be able to intersect an arbitrary interval with a pile of overlapping intervals. - // - // The approach is to accumulate the IO activity into a single vector. - // Sort by interval.location(). - // Now flatten this interval (union flatten). - // This will produce a second vector of non-overlapping intervals. - // When we want to intersect the arbitrary interval, we do the standard search on the non overlapping interval vector. - // This will give us a starting and ending location that guarantee to cover every IO that might intersect. - // - // The assumption is that while IO's overlap, they don't stay active forever. Sooner or later there will be a break. - // - // The arch-nemesis of this scheme is the light overlap, like so: - // - // XXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX - // XXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXX - - - // - // It turns out that IO can overlap inside a single thread, for example: - // - // 437719 C73AD5945 --- P_RdDataAsync 209b9f07 1000002 6b647 5000 2A72 1 gamed 293 - // 437724 C73AD5DCA --- P_RdDataAsync 209b7e37 1000002 6b64c 6000 2A72 1 gamed 293 - // 437822 C73AD98B0 --- P_RdDataAsyncDone 209b7e37 4dfe3eef 0 0 191 1 kernel_task 0 - // 437829 C73AD9E55 --- P_RdDataAsyncDone 209b9f07 4dfe3eef 0 0 191 1 kernel_task 0 - // - - if (event.dbg_class() == DBG_FSYSTEM && event.dbg_subclass() == DBG_DKRW) { - uint32_t code = event.dbg_code(); - // - // Disk IO doesn't use func_start/func_end - // - // arg1 == uid - // arg4 == size - if (code & DKIO_DONE) { - this->end_io(now, event.arg1()); - } else { - - // IO is initiated by a given process/thread, but it always finishes on a kernel_thread. - // We need to stash enough data to credit the correct thread when the completion event arrives. - begin_io(event_thread, now, event.arg1(), event.arg4()); - } - } else if (event.dbg_class() == DBG_IMPORTANCE) { - // - // Every task policy set trace code carries "trequested" data, we would like to grab them all. - // - // This subclass spans the range of 0x20 through 0x3F - // - - uint32_t subclass = event.dbg_subclass(); - if (subclass >= 0x20 && subclass <= 0x3F) { - // Trace event data is - // targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), value - - bool is_task_event = (event.dbg_code() & TASK_POLICY_TASK) > 0; - - // Should not be both a task and thread event. - ASSERT(is_task_event != (event.dbg_code() & TASK_POLICY_THREAD), "BEWM!"); - - if (is_task_event) { - process_trequested_task((pid_t)event.arg1(), event.arg2(), event.arg3()); - } else { - process_trequested_thread(event.arg1(), event.arg2(), event.arg3()); - } - } - } - break; - } - } - - return true; -} - -template -void Machine::initialize_cpu_idle_intr_states() { - ASSERT(_event_count, "Sanity"); - ASSERT(_events, "Sanity"); - ASSERT(!_cpus.empty(), "Sanity"); - - // How much work do we need to do? - uint32_t inits_needed = 0; - uint32_t inits_done = 0; - for (auto& cpu : _cpus) { - if (!cpu.is_iop()) { - inits_needed += 3; - - if (cpu.is_intr_state_initialized()) { - inits_done++; - } - if (cpu.is_idle_state_initialized()) { - inits_done++; - } - if (cpu.is_thread_state_initialized()) { - inits_done++; - } - } - } - - uintptr_t index; - for (index = 0; index < _event_count; ++index) { - const KDEvent& event = _events[index]; - ASSERT(event.cpu() > -1 && event.cpu() < _cpus.size(), "cpu_id out of range"); - MachineCPU& cpu = _cpus[event.cpu()]; - - if (!cpu.is_iop()) { - switch (event.dbg_cooked()) { - case TRACE_LOST_EVENTS: - // We're done, give up. - return; - - case MACHDBG_CODE(DBG_MACH_EXCP_INTR, 0): - if (!cpu.is_intr_state_initialized()) { - inits_done++; - - if (event.is_func_start()) { - // If we are starting an INTR now, the cpu was not in INTR prior to now. - cpu.initialize_intr_state(false, _events[0].timestamp()); - } else { - // If we are ending an INTR now, the cpu was in INTR prior to now. - cpu.initialize_intr_state(true, _events[0].timestamp()); - } - } - break; - - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_IDLE): - if (!cpu.is_idle_state_initialized()) { - inits_done++; - - if (event.is_func_start()) { - // If we are starting Idle now, the cpu was not Idle prior to now. - cpu.initialize_idle_state(false, _events[0].timestamp()); - } else { - // If we are ending Idle now, the cpu was Idle prior to now. - cpu.initialize_idle_state(true, _events[0].timestamp()); - } - } - break; - - // I spent a day tracking this down.... - // - // When you are actively sampling (say, every 100ms) on a machine - // that is mostly idle, there will be long periods of VERY idle - // cpus. So you might get a sample with no begin/end idle at all, - // but the cpu is actually idle the entire time. Now suppose in - // the next sample, you get a simple idle timeout in the middle, - // and immdiately go back to idle. If we treat any TID found on - // cpu as "running", we blow up because this segment appears to - // have the idle thread "running". - // - // So, to do a proper thread init, we require actual scheduler - // activity to tell us who the thread was. - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED): - case MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_HANDOFF): - if (!cpu.is_thread_state_initialized()) { - inits_done++; - - // We want to use the thread that *was* on cpu, not the thread being - // handed off too. - MachineThread* init_thread = youngest_mutable_thread(event.tid()); - // Legal for this to be NULL! - cpu.initialize_thread_state(init_thread, _events[0].timestamp()); - - } - break; - } - } - - if (inits_done == inits_needed) { - break; - } - } -} - -template -void Machine::begin_io(MachineThread* thread, AbsTime begin_time, typename SIZE::ptr_t uid, typename SIZE::ptr_t size) { - auto it = _io_by_uid.find(uid); - if (it == _io_by_uid.end()) { - _io_by_uid.emplace(uid, IOActivity(begin_time, AbsTime(0), thread, size)); - } else { - // We shouldn't find a valid IO entry at the uid we're installing. - ASSERT(it->second.thread() == NULL, "Overwriting existing io entry"); - ASSERT(it->second.location() == 0, "Overwriting existing io entry"); - - it->second = IOActivity(begin_time, AbsTime(0), thread, size); - } -} - -template -void Machine::end_io(AbsTime end_time, typename SIZE::ptr_t uid) { - auto it = _io_by_uid.find(uid); - - // Its okay to not find a match, if a trace begins with a Done event, for example. - if (it != _io_by_uid.end()) { - MachineThread* io_thread = it->second.thread(); - AbsTime begin_time = it->second.location(); - ASSERT(end_time > it->second.location(), "Sanity"); - - _all_io.emplace_back(begin_time, end_time - begin_time, io_thread, it->second.size()); - - DEBUG_ONLY({ - it->second.set_thread(NULL); - it->second.set_location(AbsTime(0)); - it->second.set_length(AbsTime(0)); - }) - } -} diff --git a/KDBG/MachineCPU.hpp b/KDBG/MachineCPU.hpp deleted file mode 100644 index d385c5b..0000000 --- a/KDBG/MachineCPU.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// MachineCPU.hpp -// KDBG -// -// Created by James McIlree on 10/26/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -// -// Much simplified cpu/thread state model. -// -// 1) A thread is *always* on cpu. Always. The only excpetion is during -// initialization, when the thread on cpu is unknown. -// -// 2) There are three states possible: Running, IDLE, INTR. -// A thread may move from any state to any other state. -// A thread may not take an INTR while in INTR. -// It is illegal to context_switch in IDLE or INTR. -// - -enum class kMachineCPUFlag : std::uint32_t { - IsStateIdleInitialized = 0x00000001, // Set when the idle state at event[0] has been identified. - IsStateINTRInitialized = 0x00000002, // Set when the INTR state at event[0] has been identified. - IsStateThreadInitialized = 0x00000004, // Set when the on-cpu thread at event[0] has been identified (may be NULL, for threads not known at the time of event[0]) - IsStateIdle = 0x00000008, // Set if the cpu is Idle - IsStateINTR = 0x00000010, // Set if the cpu is servicing an interrupt - IsStateDeactivatedForcedSwitchToIdleThread = 0x00000020, // OSX only; set when the cpu is deactivated and on wake forces a switch to its idle thread without a context switch tracepoint - IsIOP = 0x10000000 // Set if the cpu is an IOP -}; - -template -class MachineCPU { - protected: - - class ThreadOnCPU { - protected: - MachineThread* _thread; - AbsTime _timestamp; - public: - ThreadOnCPU(MachineThread* thread, bool is_event_zero_init_thread, AbsTime timestamp) : - _thread(thread), - _timestamp(timestamp) - { - if (is_event_zero_init_thread) - _thread = (MachineThread*)((uintptr_t)_thread | 1); - } - - MachineThread* thread() { return (MachineThread*)((uintptr_t)_thread & ~0x1); } - AbsTime timestamp() { return _timestamp; } - bool is_event_zero_init_thread() { return (uintptr_t)_thread & 0x1; } - }; - - int32_t _id; - uint32_t _flags; - std::string _name; // IOP's have names, AP's will be "AP" - std::vector> _timeline; - - // State used only during initialization - MachineThread* _thread; - AbsTime _begin_idle; - AbsTime _begin_intr; - std::vector _cpu_runq; - std::vector _cpu_intr; - std::vector _cpu_idle; - - friend class Machine; - - bool is_running() const { return (_flags & ((uint32_t)kMachineCPUFlag::IsStateIdle | (uint32_t)kMachineCPUFlag::IsStateINTR)) == 0; } - - bool is_idle() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateIdle) > 0; } - void set_idle(AbsTime timestamp); - void clear_idle(AbsTime timestamp); - - bool is_deactivate_switch_to_idle_thread() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateDeactivatedForcedSwitchToIdleThread) > 0; } - void set_deactivate_switch_to_idle_thread(); - void clear_deactivate_switch_to_idle_thread(); - - bool is_idle_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateIdleInitialized) > 0; } - void initialize_idle_state(bool value, AbsTime timestamp); - - bool is_intr() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateINTR) > 0; } - void set_intr(AbsTime timestamp); - void clear_intr(AbsTime timestamp); - - bool is_intr_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateINTRInitialized) > 0; } - void initialize_intr_state(bool state, AbsTime timestamp); - - void context_switch(MachineThread* to_thread, MachineThread* from_thread, AbsTime timestamp); - - bool is_thread_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateThreadInitialized) > 0; } - void initialize_thread_state(MachineThread* thread, AbsTime timestamp); - - MachineThread* thread() { return _thread; } - - // This is called after all events have been processed, to allow the - // cpu timelines to be collapsed and post processed. - void post_initialize(AbsInterval events_interval); - - public: - MachineCPU(int32_t id, bool is_iop, std::string name) : - _id(id), - _flags(is_iop ? (uint32_t)kMachineCPUFlag::IsIOP : 0), - _name(name), - _thread(nullptr), - _begin_idle(AbsTime(0)), - _begin_intr(AbsTime(0)) - { - } - - int32_t id() const { return _id; } - void set_id(int32_t id) { ASSERT(_id = -1, "Attempt to set id twice"); _id = id; } - - bool is_iop() const { return (_flags & (uint32_t)kMachineCPUFlag::IsIOP) > 0; } - - bool is_active() const { return !_timeline.empty(); } - - const char* name() const { return _name.c_str(); } - - const std::vector>& timeline() const { return _timeline; } - const CPUActivity* activity_for_timestamp(AbsTime timestamp) const; -}; diff --git a/KDBG/MachineCPU.impl.hpp b/KDBG/MachineCPU.impl.hpp deleted file mode 100644 index 0c048ac..0000000 --- a/KDBG/MachineCPU.impl.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// MachineCPU.impl.hpp -// KDBG -// -// Created by James McIlree on 11/7/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -// -// NOTE! activity match behavior explanation... -// -// CPUActivity entries are contiguous, there are no holes in the timeline. -// -// Note the operator< definitions above, std::lower_bounds is not using the -// default AbsInterval <. The comparsions are against the interval(s) max() - 1. -// -// std::lower_bound returns a match doing <=, std::upper_bound returns a match doing < -// -// 8/26/13... -// -// Okay, based on a better understanding of the behavior of xxx_bounds, this -// should be switchable to std::upper_bounds using a comparator without the -// subtraction, and so slightly more efficient. -// - -template -const CPUActivity* MachineCPU::activity_for_timestamp(AbsTime timestamp) const { - auto it = std::upper_bound(_timeline.begin(), _timeline.end(), timestamp, AbsIntervalMaxVsAbsTimeComparator()); - - // The upper bound will report that 0 is lower than [ 10, 20 ), need to check contains! - if (it != _timeline.end() && it->contains(timestamp)) { - return &*it; - } - - return NULL; -} diff --git a/KDBG/MachineCPU.mutable-impl.hpp b/KDBG/MachineCPU.mutable-impl.hpp deleted file mode 100644 index ceb25e1..0000000 --- a/KDBG/MachineCPU.mutable-impl.hpp +++ /dev/null @@ -1,329 +0,0 @@ -// -// MachineCPU.mutable-impl.hpp -// KDBG -// -// Created by James McIlree on 11/7/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -template -void MachineCPU::set_idle(AbsTime timestamp) { - ASSERT(is_idle_state_initialized(), "Setting idle before state was initialized"); - ASSERT(!is_intr(), "Setting idle while in interrupt"); - ASSERT(!is_idle(), "Setting idle while already idle"); - ASSERT(_begin_idle == 0, "Sanity"); - - _begin_idle = timestamp; - _flags |= (uint32_t)kMachineCPUFlag::IsStateIdle; -} - -template -void MachineCPU::clear_idle(AbsTime timestamp) { - ASSERT(is_idle_state_initialized(), "Clearing idle before state was initialized"); - ASSERT(!is_intr(), "Clearing idle while in interrupt"); - ASSERT(is_idle(), "Clearing idle while not idle"); - - _cpu_idle.emplace_back(_begin_idle, timestamp - _begin_idle); - DEBUG_ONLY(_begin_idle = AbsTime(0);) - _flags &= ~(uint32_t)kMachineCPUFlag::IsStateIdle; -} - -template -void MachineCPU::set_deactivate_switch_to_idle_thread() { - ASSERT(!is_deactivate_switch_to_idle_thread(), "State already set"); - ASSERT(!is_intr(), "This state should not occur during INTR"); - - _flags |= (uint32_t)kMachineCPUFlag::IsStateDeactivatedForcedSwitchToIdleThread; -} - -template -void MachineCPU::clear_deactivate_switch_to_idle_thread() { - ASSERT(is_deactivate_switch_to_idle_thread(), "Clearing state when not set"); - ASSERT(!is_intr(), "This state transition should not occur during INTR"); - - _flags &= ~(uint32_t)kMachineCPUFlag::IsStateDeactivatedForcedSwitchToIdleThread; -} - -template -void MachineCPU::initialize_idle_state(bool is_idle, AbsTime timestamp) { - ASSERT(!is_idle_state_initialized(), "Attempt to initialize Idle state more than once"); - ASSERT(!this->is_idle(), "Attempt to initialize Idle state while already idle"); - - if (is_idle) { - _begin_idle = timestamp; - _flags |= (uint32_t)kMachineCPUFlag::IsStateIdle; - } - - _flags |= (uint32_t)kMachineCPUFlag::IsStateIdleInitialized; -} - -template -void MachineCPU::set_intr(AbsTime timestamp) { - // We can take an INTR in state Unknown, IDLE, and RUNNING. - ASSERT(is_intr_state_initialized(), "Setting INTR before state was initialized"); - ASSERT(!is_intr(), "Setting INTR when already in state INTR"); - ASSERT(_begin_intr == 0, "Sanity"); - - _begin_intr = timestamp; - _flags |= (uint32_t)kMachineCPUFlag::IsStateINTR; -} - -template -void MachineCPU::clear_intr(AbsTime timestamp) { - ASSERT(is_intr_state_initialized(), "Clearing INTR before state was initialized"); - ASSERT(is_intr(), "Clearing INTR when not in INTR"); - - _cpu_intr.emplace_back(_begin_intr, timestamp - _begin_intr); - DEBUG_ONLY(_begin_intr = AbsTime(0);) - _flags &= ~(uint32_t)kMachineCPUFlag::IsStateINTR; -} - -template -void MachineCPU::initialize_intr_state(bool is_intr, AbsTime timestamp) { - ASSERT(!is_intr_state_initialized(), "Attempt to initialize INTR state more than once"); - ASSERT(!this->is_intr(), "Attempt to initialize INTR state while already INTR"); - - if (is_intr) { - _begin_intr = timestamp; - _flags |= (uint32_t)kMachineCPUFlag::IsStateINTR; - } - - _flags |= (uint32_t)kMachineCPUFlag::IsStateINTRInitialized; -} - -template -void MachineCPU::initialize_thread_state(MachineThread* init_thread, AbsTime timestamp) { - ASSERT(!is_thread_state_initialized(), "Attempt to initialize thread state more than once"); - ASSERT(!_thread, "Sanity"); - - // When initializing the thread state, the TID lookup may fail. This - // can happen if there wasn't a threadmap, or if the thread was created - // later in the trace. We explicitly allow NULL as a valid value here. - // NULL means "Go ahead and set the init flag, but we will not emit a - // runq event later when a real context switch happens - - _flags |= (uint32_t)kMachineCPUFlag::IsStateThreadInitialized; - if (init_thread) { - _cpu_runq.emplace_back(init_thread, true, timestamp); - _thread = init_thread; - } -} - -template -void MachineCPU::context_switch(MachineThread* to_thread, MachineThread* from_thread, AbsTime timestamp) { - // - // We cannot context switch in INTR or Idle - // - // The one exception is if we were thread_initialized with NULL, - // then the first context switch will happen at idle. - ASSERT(!is_intr(), "May not context switch while in interrupt"); - ASSERT(!is_idle() || _thread == NULL && is_thread_state_initialized(), "May not context switch while idle"); - ASSERT(to_thread, "May not context switch to NULL"); - - // The threads should match, unless... - // 1) We're uninitialized; we don't know who was on cpu - // 2) VERY RARE: A process EXEC'd, and we made a new thread for the new process. The tid's will still match, and the old thread should be marked as trace terminated. - ASSERT(from_thread == _thread || _thread == NULL || (_thread->is_trace_terminated() && _thread->tid() == from_thread->tid()), "From thread does not match thread on cpu"); - - // Very rarely, we init a cpu to a thread, and then event[0] is a mach_sched - // or other context switch event. If that has happened, just discard the init - // thread entry. - if (_cpu_runq.size() == 1) { - if (_cpu_runq.back().is_event_zero_init_thread()) { - if (timestamp == _cpu_runq.back().timestamp()) { - _cpu_runq.pop_back(); - } - } - } - - ASSERT(_cpu_runq.empty() || timestamp > _cpu_runq.back().timestamp(), "Out of order timestamps"); - ASSERT(_cpu_runq.size() < 2 || !_cpu_runq.back().is_event_zero_init_thread(), "Sanity"); - - _cpu_runq.emplace_back(to_thread, false, timestamp); - _thread = to_thread; -} - -template -void MachineCPU::post_initialize(AbsInterval events_timespan) { -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) - // Make sure everything is sorted - if (_cpu_runq.size() > 1) { - for (uint32_t i=1; i<_cpu_runq.size(); ++i) { - ASSERT(_cpu_runq[i-1].timestamp() < _cpu_runq[i].timestamp(), "Out of order run events"); - } - } - if (_cpu_idle.size() > 1) { - for (uint32_t i=1; i<_cpu_idle.size(); ++i) { - ASSERT(_cpu_idle[i-1].max() < _cpu_idle[i].location(), "Out of order idle events"); - } - } - if (_cpu_intr.size() > 1) { - for (uint32_t i=1; i<_cpu_intr.size(); ++i) { - ASSERT(_cpu_intr[i-1].max() < _cpu_intr[i].location(), "Out of order intr events"); - } - } -#endif - - // We do not need to flush the current thread on cpu, as the cpu - // runq only records "on" events, and assumes a duration of "until - // the next thread arrives or end of time" - - - // if we have a pending intr state, flush it. - // We want to flush the intr first, so an idle - // flush doesn't assert. - if (is_intr()) - clear_intr(events_timespan.max()); - - // If we have a pending idle state, flush it. - if (is_idle()) - clear_idle(events_timespan.max()); - - if (!_cpu_runq.empty() || !_cpu_idle.empty() || !_cpu_intr.empty()) { - // - // Collapse all the events into a single timeline - // - - // Check this math once we're done building the timeline. - size_t guessed_capacity = _cpu_runq.size() + _cpu_idle.size() * 2 + _cpu_intr.size() * 2; - _timeline.reserve(guessed_capacity); - - auto runq_it = _cpu_runq.begin(); - auto idle_it = _cpu_idle.begin(); - auto intr_it = _cpu_intr.begin(); - - // Starting these at 0 will for an update to valid values in - // the first pass of the workloop. - - AbsInterval current_runq(AbsTime(0), AbsTime(0)); - AbsInterval current_idle(AbsTime(0), AbsTime(0)); - AbsInterval current_intr(AbsTime(0), AbsTime(0)); - - MachineThread* current_thread = NULL; - - AbsTime cursor(events_timespan.location()); - while (events_timespan.contains(cursor)) { - // - // First we see if anyone needs updating with the next component. - // - if (cursor >= current_runq.max()) { - if (runq_it != _cpu_runq.end()) { - AbsTime end, begin = runq_it->timestamp(); - if (runq_it+1 != _cpu_runq.end()) - end = (runq_it+1)->timestamp(); - else - end = events_timespan.max(); - - current_runq = AbsInterval(begin, end - begin); - current_thread = runq_it->thread(); - ++runq_it; - } else { - // This will force future update checks to always fail. - current_runq = AbsInterval(events_timespan.max() + AbsTime(1), AbsTime(1)); - current_thread = NULL; - } - } - - if (cursor >= current_idle.max()) { - if (idle_it != _cpu_idle.end()) { - current_idle = *idle_it; - ++idle_it; - } else { - // This will force future update checks to always fail. - current_idle = AbsInterval(events_timespan.max() + AbsTime(1), AbsTime(1)); - } - } - - if (cursor >= current_intr.max()) { - if (intr_it != _cpu_intr.end()) { - current_intr = *intr_it; - ++intr_it; - } else { - // This will force future update checks to always fail. - current_intr = AbsInterval(events_timespan.max() + AbsTime(1), AbsTime(1)); - } - } - - // - // Now we see what type of activity we will be recording. - // - // This is heirarchical, intr > idle > run > unknown. - // - - kCPUActivity type = kCPUActivity::Unknown; - - if (current_runq.contains(cursor)) - type = kCPUActivity::Run; - - if (current_idle.contains(cursor)) - type = kCPUActivity::Idle; - - if (current_intr.contains(cursor)) - type = kCPUActivity::INTR; - - // - // Now we know the type, and the starting location. - // We must find the end. - // - // Since this is heirarchical, each type may end on - // its own "end", or the "begin" of a type higher than - // itself. An idle can end at its end, or at an intr begin. - // - - AbsTime end; - switch (type) { - case kCPUActivity::Unknown: - end = std::min({ events_timespan.max(), current_runq.location(), current_idle.location(), current_intr.location() }); - break; - - case kCPUActivity::Run: - end = std::min({ current_runq.max(), current_idle.location(), current_intr.location() }); - break; - - case kCPUActivity::Idle: - end = std::min(current_idle.max(), current_intr.location()); - break; - - case kCPUActivity::INTR: - end = current_intr.max(); - break; - } - - // - // Now we drop in the new activity - // - if (type == kCPUActivity::Run) { - ASSERT(current_thread, "Current thread is NULL"); - // Its a context switch if we are at the beginning of the runq interval - _timeline.emplace_back(current_thread, AbsInterval(cursor, end - cursor), current_runq.location() == cursor); - } else - _timeline.emplace_back(type, AbsInterval(cursor, end - cursor)); - - // - // And bump the cursor to the end... - // - cursor = end; - } - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) - for (auto it = _timeline.begin(); it != _timeline.end(); ++it) { - auto next_it = it + 1; - ASSERT(events_timespan.contains(*it), "activity not contained in events_timespan"); - if (next_it != _timeline.end()) { - ASSERT(it->max() == next_it->location(), "activity not end to end"); - bool initial_idle_state = ((it == _timeline.begin()) && it->is_idle()); - ASSERT(!next_it->is_context_switch() || (it->is_run() || it->is_unknown() || initial_idle_state) , "Context switch activity preceeded by !run activity"); - } - } -#endif - } - - _cpu_runq.clear(); - _cpu_runq.shrink_to_fit(); - - _cpu_idle.clear(); - _cpu_idle.shrink_to_fit(); - - _cpu_intr.clear(); - _cpu_intr.shrink_to_fit(); -} diff --git a/KDBG/MachineMachMsg.hpp b/KDBG/MachineMachMsg.hpp deleted file mode 100644 index 43f4f1d..0000000 --- a/KDBG/MachineMachMsg.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// MachineMachMsg.hpp -// KDBG -// -// Created by James McIlree on 2/20/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kernel_perf_cmds_MachineMachMsg_hpp -#define kernel_perf_cmds_MachineMachMsg_hpp - -enum kMachineMachMsgFlag { - HasSender = 0x00000001, - HasReceiver = 0x00000002, - IsVoucherRefused = 0x00000004 -}; - -template -class MachineMachMsg { - protected: - - // POTENTIAL ISSUE: - // - // We could have a case where a sender queue's a message, then dies before the receiver picks it up. - // With a dead thread, the next MachineState will not include the tid, and then we'll be unable to look it up. - - // NOTE NOTE NOTE! - // - // The instance vars are sorted by size to avoid wasting space. - // Don't change without good reason, and add new vars to the - // correct location! - - /* - * ALWAYS 64b - */ - - AbsTime _send_time; - AbsTime _recv_time; - - /* - * LP64 - HOST - * - * I'm going to assume the most common asymetric pattern is a 64 bit desktop - * looking at a 32 bit device... - */ - - MachineVoucher* _send_voucher; - MachineVoucher* _recv_voucher; - - /* - * LP64 - SIZE - */ - - typename SIZE::ptr_t _send_tid; - typename SIZE::ptr_t _recv_tid; - typename SIZE::ptr_t _kmsg_addr; - - - /* - * ALWAYS 32b - */ - - uint32_t _id; // This is globally unique for EACH message. - uint32_t _send_msgh_bits; // msgh_bits is modified between send/recv - uint32_t _recv_msgh_bits; - uint32_t _flags; - - public: - MachineMachMsg(uint32_t id, - typename SIZE::ptr_t kmsg_addr, - uint32_t flags, - AbsTime send_time, - typename SIZE::ptr_t send_tid, - uint32_t send_msgh_bits, - MachineVoucher* send_voucher, - AbsTime recv_time, - typename SIZE::ptr_t recv_tid, - uint32_t recv_msgh_bits, - MachineVoucher* recv_voucher) : - _send_time(send_time), - _recv_time(recv_time), - _send_voucher(send_voucher), - _recv_voucher(recv_voucher), - _send_tid(send_tid), - _recv_tid(recv_tid), - _kmsg_addr(kmsg_addr), - _id(id), - _send_msgh_bits(send_msgh_bits), - _recv_msgh_bits(recv_msgh_bits), - _flags(flags) - { - // Should always have a valid pointer, but may be Machine::NullVoucher - ASSERT(send_voucher, "Sanity"); - ASSERT(recv_voucher, "Sanity"); - - ASSERT(send_voucher->is_unset() == (MACH_MSGH_BITS_VOUCHER(_send_msgh_bits) == MACH_MSGH_BITS_ZERO), "voucher state disagrees with msgh_bits"); - ASSERT(recv_voucher->is_unset() == (MACH_MSGH_BITS_VOUCHER(_recv_msgh_bits) == MACH_MSGH_BITS_ZERO), "voucher state disagrees with msgh_bits"); - } - - bool has_sender() const { return (_flags & kMachineMachMsgFlag::HasSender) > 0; } - bool has_receiver() const { return (_flags & kMachineMachMsgFlag::HasReceiver) > 0; } - - uint32_t id() const { return _id; } - - typename SIZE::ptr_t send_tid() const { ASSERT(has_sender(), "No Sender"); return _send_tid; } - typename SIZE::ptr_t recv_tid() const { ASSERT(has_receiver(), "No Receiver"); return _recv_tid; } - - AbsTime send_time() const { ASSERT(has_sender(), "No Sender"); return _send_time; } - AbsTime recv_time() const { ASSERT(has_receiver(), "No Receiver"); return _recv_time; } - - MachineVoucher* send_voucher() const { ASSERT(has_sender(), "No Sender"); return _send_voucher; } - MachineVoucher* recv_voucher() const { ASSERT(has_receiver(), "No Receiver"); return _recv_voucher; } - - uint32_t send_msgh_bits() const { ASSERT(has_sender(), "No Sender"); return _send_msgh_bits; } - uint32_t recv_msgh_bits() const { ASSERT(has_receiver(), "No Receiver"); return _recv_msgh_bits; } - - bool is_voucher_refused() const { ASSERT(has_receiver(), "No Receiver"); return (_flags & kMachineMachMsgFlag::IsVoucherRefused) > 0; } - - bool has_send_voucher() const { return has_sender() && MACH_MSGH_BITS_VOUCHER(_send_msgh_bits) != MACH_MSGH_BITS_ZERO; } - bool has_recv_voucher() const { return has_receiver() && MACH_MSGH_BITS_VOUCHER(_recv_msgh_bits) != MACH_MSGH_BITS_ZERO; } - - bool has_non_null_send_voucher() const { return has_sender() && MACH_MSGH_BITS_VOUCHER(_send_msgh_bits) != MACH_MSGH_BITS_ZERO && !_send_voucher->is_null(); } - bool has_non_null_recv_voucher() const { return has_receiver() && MACH_MSGH_BITS_VOUCHER(_recv_msgh_bits) != MACH_MSGH_BITS_ZERO && !_recv_voucher->is_null(); } -}; - -#endif diff --git a/KDBG/MachineProcess.hpp b/KDBG/MachineProcess.hpp deleted file mode 100644 index 4b52051..0000000 --- a/KDBG/MachineProcess.hpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// MachineProcess.hpp -// KDBG -// -// Created by James McIlree on 10/26/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -// -// Process life cycle -// -// There are four ways a process can be created: -// -// 1) CreatedByPreviousMachineState -// -// It is a carryover from a previous Machine state. This happens when a -// live trace creates a machine state that is a union of a previous state -// and new event data. -// -// 2) CreatedByThreadMap -// -// It is a process that was running at the time the trace events were -// taken. The kernel provides this data. -// -// 3) CreatedByExecEvent -// -// It is a process that "reused" an existing pid, and exec'd a new process -// in place. The Machine State will completely close down the old process -// and create a new one to track data for the newly exec'd process. -// -// 4) CreatedByForkExecEvent -// -// An existing process "forked", creating a new pid, and then "exec'd". -// This is seen in trace events as a TRACE_DATA_NEWTHREAD with a pid that -// does not match the callers pid. -// -// There are also two catch-all processes, "Unknown", and "Kernel". The kernel -// process contains all kernel only threads, and unknown contains threads that -// are encountered without any previous identifying information. -// - -enum class kMachineProcessFlag : std::uint32_t { - CreatedByPreviousMachineState = 0x00000001, - CreatedByThreadMap = 0x00000002, - CreatedByForkExecEvent = 0x00000004, - CreatedByExecEvent = 0x00000008, - IsForkExecInProgress = 0x00000010, - IsExecInProgress = 0x00000020, - IsUnknownProcess = 0x00000040, - IsKernelProcess = 0x00000080, - IsExitBySyscall = 0x00000100, - IsExitByJetsam = 0x00000400, - IsExitByExec = 0x00000800, - IsTraceTerminated = 0x00001000 -}; - -template class Machine; - -template -class MachineProcess { - protected: - pid_t _pid; - char _name[20]; // Actual limit is 16, we round up for NULL terminator - AbsInterval _timespan; // This is set at trace termination, or in post_initialize if still live. - AbsTime _exit_initiated_timestamp; - std::vector*> _threads_by_time; - uint32_t _flags; - int32_t _exit_status; - int32_t _apptype; // Unset == -1 - - // - // Mutable API - // - - friend class Machine; - - void set_flags(kMachineProcessFlag flags) { _flags |= (uint32_t)flags; } - void clear_flags(kMachineProcessFlag flags) { _flags &= ~(uint32_t)flags; } - bool is_flag_set(kMachineProcessFlag flag) const { return (_flags & (uint32_t)flag) > 0; } - - // - // Process exit lifecycle - // - // Processes start to exit / terminate when one of the following happens: - // - // syscall to proc exit - // jetsam causes a SIGKILL - // syscall to exec - // - // It may be that more than one of these events happen. For example, jetsam - // may cause a process to die via a SIGKILL. - // - // For the purposes of this API, only the first method of initiating exit - // is recorded. This includes the timestamp; if you ask for the exit timestamp - // you will get the timestamp for the first invocation of any of the exit - // paths. - // - // Once a process starts terminating, it will eventually reach the point - // where no futher events will ever be seen for that process. When the - // last thread in the process is marked as trace terminated, the process - // is marked as trace terminated. - // - // The definitive test for a process being entirely done is trace termination. - // - - // - // The exit code and conditions are a bit of a mess. - // All processes exit. This is triggered by the BSD_PROC_EXIT - // tracepoint. Some processes chose to exit, some are forced to - // exit by signals (SIGKILL, for example). Some processes are - // forced to exit by a mechanism that appears to be a signal but - // we want to track them separately (jetsam). - // - // The upshot of this is the exit code is stored in waitpid - // style. See waitpid(2) for the macros used to decode this. - // - void set_exit_by_syscall(AbsTime timestamp, int exit_status); - void set_exit_by_jetsam(AbsTime timestamp); - void set_exit_by_exec(AbsTime timestamp); - void set_trace_terminated(AbsTime timestamp); // Also sets last timestamp - - void set_apptype(uint32_t apptype); - void set_apptype_from_trequested(uint32_t apptype); - void set_name(const char* name); - - void add_thread(MachineThread* thread); - - bool is_exec_in_progress() const { return (_flags & (uint32_t)kMachineProcessFlag::IsExecInProgress) > 0; } - bool is_fork_exec_in_progress() const { return (_flags & (uint32_t)kMachineProcessFlag::IsForkExecInProgress) > 0; } - - void clear_fork_exec_in_progress(); - void clear_exec_in_progress(); - - // This is called after all events have been processed, to allow the - // threads to be sorted. - void post_initialize(AbsTime last_machine_timestamp); - - public: - MachineProcess(pid_t pid, - const char* name, - AbsTime create_timestamp, - kMachineProcessFlag flags); - - pid_t pid() const { return _pid; } - const char* name() const { return _name; } - AbsInterval timespan() const { return _timespan; } - AbsTime exit_timestamp() const { return _exit_initiated_timestamp; } - int32_t exit_status() const { return _exit_status; } - int32_t apptype() const { return _apptype; } - - uint32_t flags() const { return _flags; } - - const std::vector*>& threads() const { return *reinterpret_cast*>*>(&_threads_by_time); } - - bool is_exit_by_syscall() const { return is_flag_set(kMachineProcessFlag::IsExitBySyscall); } - bool is_exit_by_jetsam() const { return is_flag_set(kMachineProcessFlag::IsExitByJetsam); } - bool is_exit_by_exec() const { return is_flag_set(kMachineProcessFlag::IsExitByExec); } - - // The invariant is that trace_terminated may not be set without is_exiting() set - bool is_exiting() const { return is_exit_by_syscall() || is_exit_by_jetsam() || is_exit_by_exec(); } - bool is_trace_terminated() const { return is_flag_set(kMachineProcessFlag::IsTraceTerminated); } - - bool is_unknown() const { return is_flag_set(kMachineProcessFlag::IsUnknownProcess); } - bool is_kernel() const { return is_flag_set(kMachineProcessFlag::IsKernelProcess); } - - bool is_created_by_previous_machine_state() const { return is_flag_set(kMachineProcessFlag::CreatedByPreviousMachineState); } - bool is_created_by_thread_map() const { return is_flag_set(kMachineProcessFlag::CreatedByThreadMap); } - bool is_created_by_fork_exec() const { return is_flag_set(kMachineProcessFlag::CreatedByForkExecEvent); } - bool is_created_by_exec() const { return is_flag_set(kMachineProcessFlag::CreatedByExecEvent); } - - DEBUG_ONLY(void validate() const;) -}; - diff --git a/KDBG/MachineProcess.impl.hpp b/KDBG/MachineProcess.impl.hpp deleted file mode 100644 index 7aab877..0000000 --- a/KDBG/MachineProcess.impl.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// MachineProcess.impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -template -MachineProcess::MachineProcess(pid_t pid, const char* name, AbsTime create_timestamp, kMachineProcessFlag flags) : - _pid(pid), - _timespan(create_timestamp, AbsTime(0)), - _flags((uint32_t)flags), - _exit_status(0), - _apptype(-1) -{ - ASSERT(name, "Sanity"); - ASSERT(strlen(name) < sizeof(_name) - 1, "Sanity"); - - // strlcpy guarantees NULL termination - strlcpy(_name, name, sizeof(_name)); -} - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void MachineProcess::validate() const { - ASSERT(strlen(_name), "Must have a non zero length name"); - - if (is_trace_terminated()) { - ASSERT(is_exiting(), "Process is trace terminated without precursor exit event"); - - for (auto thread : _threads_by_time) { - ASSERT(thread->is_trace_terminated(), "process is trace terminated, but has live thread"); - } - } - - for (auto thread : _threads_by_time) { - ASSERT(_timespan.contains(thread->timespan()), "thread outside process timespan"); - thread->validate(); - } - - // Every process should have one and only one primordial (main) thread. - // However, we cannot tell what the main thread is for threadmap processes, - // and processes forwarded from an earlier machine state may have already - // exited their main thread. We can only check exec/fork-exec. - - if ((is_created_by_exec() || is_created_by_fork_exec()) && !is_created_by_previous_machine_state()) { - auto main_threads = 0; - for (auto thread : _threads_by_time) { - if (thread->is_main_thread()) main_threads++; - ASSERT(main_threads <= 1, "More than one main thread in a process"); - } - ASSERT(main_threads == 1, "Incorrect number of main thread in process"); - } - -} -#endif \ No newline at end of file diff --git a/KDBG/MachineProcess.mutable-impl.hpp b/KDBG/MachineProcess.mutable-impl.hpp deleted file mode 100644 index caf2b6f..0000000 --- a/KDBG/MachineProcess.mutable-impl.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// MachineProcess.mutable-impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - -template -void MachineProcess::set_exit_by_syscall(AbsTime timestamp, int32_t exit_status) { - ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); - ASSERT(_exit_initiated_timestamp == 0, "Sanity"); - ASSERT(!is_kernel(), "Kernel process is attempting to exit"); - - _exit_status = exit_status; - _exit_initiated_timestamp = timestamp; - - set_flags(kMachineProcessFlag::IsExitBySyscall); -} - -template -void MachineProcess::set_exit_by_jetsam(AbsTime timestamp) { - ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); - ASSERT(_exit_initiated_timestamp == 0, "Sanity"); - ASSERT(!is_kernel(), "Kernel process is attempting to exit"); - - _exit_initiated_timestamp = timestamp; - - set_flags(kMachineProcessFlag::IsExitByJetsam); -} - -template -void MachineProcess::set_exit_by_exec(AbsTime timestamp) { - ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); - ASSERT(_exit_initiated_timestamp == 0, "Sanity"); - ASSERT(!is_kernel(), "Kernel process is attempting to exit"); - - _exit_initiated_timestamp = timestamp; - set_flags(kMachineProcessFlag::IsExitByExec); - - for (MachineThread* thread : _threads_by_time) { - if (!thread->is_trace_terminated()) { - thread->set_trace_terminated(timestamp); - } - } - - set_trace_terminated(timestamp); -} - -template -void MachineProcess::set_trace_terminated(AbsTime timestamp){ - ASSERT(is_exiting(), "Attempting to set trace terminated without precursor exit event"); - ASSERT(!is_kernel(), "Kernel process is attempting to set trace terminated"); - - DEBUG_ONLY({ - for (MachineThread* thread : _threads_by_time) { - ASSERT(thread->is_trace_terminated(), "Setting process as trace terminated when it still has live threads"); - } - }) - - _timespan.set_max(timestamp + AbsTime(1)); - set_flags(kMachineProcessFlag::IsTraceTerminated); -} - -template -void MachineProcess::set_apptype(uint32_t type) { - ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); - ASSERT(_apptype == -1 || _apptype == type, "Attempt to set apptype more than once, or to change an inherited apptype"); - ASSERT(!is_kernel(), "Kernel is attempting to set apptype"); - ASSERT(!is_exiting(), "Setting apptype after exit"); - - _apptype = type; -} - -template -void MachineProcess::set_apptype_from_trequested(uint32_t type) { - ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); - ASSERT(_apptype == -1 || _apptype == type, "trequested apptype does not match set apptype"); - - _apptype = type; -} - -template -void MachineProcess::set_name(const char* name) { - ASSERT(name, "Sanity"); - ASSERT(strlen(name) < sizeof(_name) - 1, "Sanity"); - - strlcpy(_name, name, sizeof(_name)); -} - -template -void MachineProcess::clear_fork_exec_in_progress() { - ASSERT(!is_unknown(), "Sanity"); - ASSERT(!is_kernel(), "Sanity"); - ASSERT(!is_exiting(), "Sanity"); - ASSERT(!is_exec_in_progress(), "Sanity"); - ASSERT(is_fork_exec_in_progress(), "Sanity"); - - clear_flags(kMachineProcessFlag::IsForkExecInProgress); -} - -template -void MachineProcess::clear_exec_in_progress() { - ASSERT(!is_unknown(), "Sanity"); - ASSERT(!is_kernel(), "Sanity"); - ASSERT(!is_exiting(), "Sanity"); - ASSERT(!is_fork_exec_in_progress(), "Sanity"); - ASSERT(is_exec_in_progress(), "Sanity"); - - clear_flags(kMachineProcessFlag::IsExecInProgress); -} - -template -void MachineProcess::add_thread(MachineThread* thread) { - ASSERT(thread, "Sanity"); - ASSERT(&thread->process() == this, "Sanity"); - ASSERT(!thread->is_trace_terminated(), "Attempt to add thread that is already terminated"); - ASSERT(thread->timespan().location() >= _timespan.location(), "Attempt to add thread that started before this process"); - ASSERT(!is_exiting(), "Adding thread to process that has exited"); - - // 6/20/2014, reworking time handling, is this still true? - // - // Process/thread created by a previous machine state will violate these - // rules, during initialization. However, only threads created in that - // form will be so tagged, and so we can exclude them from this assert. - // - // ASSERT(!is_exited() || thread->is_created_by_previous_machine_state(), "Adding thread to process that has marked itself as exited"); - - DEBUG_ONLY({ - // At this point, the threads vector is not sorted. - // We have to look at everything :-(. - for (MachineThread* process_thread : _threads_by_time) { - if (process_thread->tid() == thread->tid()) { - ASSERT(!process_thread->timespan().intersects(thread->timespan()), "Overlapping duplicate threads"); - } - } - }) - - _threads_by_time.push_back(thread); -} - -template -void MachineProcess::post_initialize(AbsTime last_machine_timestamp) { - // - // For processes that are still alive at the post_initialize phase, - // we want to extend their timespan(s) to the end of the machine state, - // so they can be looked up by pid/name. - // - if (!is_trace_terminated()) { - ASSERT(_timespan.length() == 0, "Should not have timespan set"); - - // Time in a range is always half open. [ 10, 11 ) means 10 is included, - // but 11 is not. In order to include a given timestamp, we must use - // a value one greater. - AbsTime half_open_timestamp = last_machine_timestamp + AbsTime(1); - - _timespan.set_max(half_open_timestamp); - } - - std::sort(_threads_by_time.begin(), _threads_by_time.end(), thread_by_time_sort); -} diff --git a/KDBG/MachineThread.hpp b/KDBG/MachineThread.hpp deleted file mode 100644 index 1d93ba7..0000000 --- a/KDBG/MachineThread.hpp +++ /dev/null @@ -1,124 +0,0 @@ -// -// MachineThread.hpp -// KDBG -// -// Created by James McIlree on 10/26/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -template class MachineProcess; - -enum class kMachineThreadFlag : std::uint32_t { - CreatedByPreviousMachineState = 0x00000001, - CreatedByThreadMap = 0x00000002, - CreatedByTraceDataNewThread = 0x00000004, - CreatedByUnknownTidInTrace = 0x00000008, - CreatedByForkExecEvent = 0x00000010, - CreatedByExecEvent = 0x00000020, - IsMain = 0x00000040, - IsIdle = 0x00000080, - TraceTerminated = 0x00000200, // Set when a MACH_THREAD_TERMINATED is seen. This is definitive, no further trace events should reference this thread. -}; - -template class Machine; -template class JetsamActivity; -template class MachineVoucher; - -template -class MachineThread { - protected: - uint32_t _flags; - typename SIZE::ptr_t _tid; // We're unlikely to ever look at K64 on a 32 bit machine, put this here as best chance to not increase struct size with useless padding bytes. - MachineProcess* _process; - AbsInterval _timespan; - AbsTime _begin_blocked; - AbsTime _begin_vm_fault; - AbsTime _begin_jetsam_activity; - uint32_t _begin_jetsam_activity_type; - std::vector _blocked; - std::vector _vm_faults; - std::vector _jetsam_activity; - std::vector> _vouchers_by_time; - - // - // Mutable API - // - friend class Machine; - friend class MachineProcess; - - MachineProcess& mutable_process() { return *_process; } - - void set_flags(kMachineThreadFlag flags) { _flags |= (uint32_t)flags; } - void clear_flags(kMachineThreadFlag flags) { _flags &= ~(uint32_t)flags; } - bool is_flag_set(kMachineThreadFlag flag) const { return (_flags & (uint32_t)flag) > 0; } - - // This can be discovered after the thread is created. - void set_is_idle_thread(); - void set_trace_terminated(AbsTime timestamp); - - void set_voucher(MachineVoucher* voucher, AbsTime timestamp); - - // - // NOTE! Unrunnable/blocked isn't quite exact; it doesn't match - // the scheduler view of unrunnable/blocked. - // - // 1) If you're not blocked, you're runnable - // 2) A thread is considered "blocked" if the cpu it is on goes idle. - // - void make_runnable(AbsTime timestamp); - void make_unrunnable(AbsTime timestamp); - - void begin_vm_fault(AbsTime timestamp); - void end_vm_fault(AbsTime timestamp); - - void begin_jetsam_activity(uint32_t type, AbsTime timestamp); - void end_jetsam_activity(uint32_t type, AbsTime timestamp); - - void add_io_activity(AbsInterval interval, uint32_t code, uint32_t page_count); - - AbsTime blocked_in_timespan(AbsInterval timespan) const; - AbsTime next_blocked_after(AbsTime timestamp) const; - - // This is called after all events have been processed, to flush any pending state - void post_initialize(AbsTime last_machine_timestamp); - - public: - MachineThread(MachineProcess* process, typename SIZE::ptr_t tid, MachineVoucher* initial_voucher, AbsTime create_timestamp, kMachineThreadFlag flags) : - _flags((uint32_t)flags), - _tid(tid), - _process(process), - _timespan(create_timestamp, AbsTime(0)), - _begin_jetsam_activity_type(0) - { - ASSERT(_tid != 0, "Sanity"); - ASSERT(_process, "Sanity"); - ASSERT(initial_voucher, "Sanity"); - - _vouchers_by_time.emplace_back(initial_voucher, AbsInterval(create_timestamp, AbsTime::END_OF_TIME - create_timestamp)); - } - - typename SIZE::ptr_t tid() const { return _tid; } - AbsInterval timespan() const { return _timespan; } - const MachineProcess& process() const { return *_process; } - uint32_t flags() const { return _flags; } - - const MachineVoucher* voucher(AbsTime timestamp) const; - const MachineVoucher* last_voucher() const; - - const std::vector& vm_faults() const { return _vm_faults; } - const std::vector& jetsam_activity() const { return _jetsam_activity; } - - bool is_created_by_previous_machine_state() const { return is_flag_set(kMachineThreadFlag::CreatedByPreviousMachineState); } - bool is_created_by_thread_map() const { return is_flag_set(kMachineThreadFlag::CreatedByThreadMap); } - bool is_created_by_trace_data_new_thread() const { return is_flag_set(kMachineThreadFlag::CreatedByTraceDataNewThread); } - bool is_created_by_unknown_tid_in_trace() const { return is_flag_set(kMachineThreadFlag::CreatedByUnknownTidInTrace); } - bool is_created_by_fork_exec() const { return is_flag_set(kMachineThreadFlag::CreatedByForkExecEvent); } - bool is_created_by_exec() const { return is_flag_set(kMachineThreadFlag::CreatedByExecEvent); } - - bool is_idle_thread() const { return is_flag_set(kMachineThreadFlag::IsIdle); } - bool is_main_thread() const { return is_flag_set(kMachineThreadFlag::IsMain); } - - bool is_trace_terminated() const { return is_flag_set(kMachineThreadFlag::TraceTerminated); } - - DEBUG_ONLY(void validate() const;) -}; diff --git a/KDBG/MachineThread.impl.hpp b/KDBG/MachineThread.impl.hpp deleted file mode 100644 index ed3297d..0000000 --- a/KDBG/MachineThread.impl.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// MachineThread.impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -template -AbsTime MachineThread::blocked_in_timespan(AbsInterval timespan) const { - auto it = std::lower_bound(_blocked.begin(), _blocked.end(), AbsInterval(timespan.location(), AbsTime(1))); - // The lower bound will report that 0 is lower than [ 10, 20 ), need to check contains! - AbsTime blocked_time; - while (it != _blocked.end() && timespan.intersects(*it)) { - blocked_time += timespan.intersection_range(*it).length(); - ++it; - } - - return blocked_time; -} - -template -AbsTime MachineThread::next_blocked_after(AbsTime timestamp) const { - auto it = std::lower_bound(_blocked.begin(), _blocked.end(), AbsInterval(timestamp, AbsTime(1))); - // The lower bound will report that 0 is lower than [ 10, 20 ), need to check contains! - if (it != _blocked.end()) { - if (it->contains(timestamp)) - return timestamp; - - ASSERT(it->location() > timestamp, "Sanity"); - return it->location(); - } - - return _timespan.max(); -} - -template -const MachineVoucher* MachineThread::voucher(AbsTime timestamp) const { - ASSERT(_timespan.contains(timestamp), "Sanity"); - - auto it = std::upper_bound(_vouchers_by_time.begin(), _vouchers_by_time.end(), timestamp, AbsIntervalMaxVsAbsTimeComparator()); - - // The upper bound will report that 0 is lower than [ 10, 20 ), need to check contains! - if (it != _vouchers_by_time.end() && it->contains(timestamp)) { - return it->voucher(); - } - - return &Machine::UnsetVoucher; -} - -template -const MachineVoucher* MachineThread::last_voucher() const { - ASSERT(!_vouchers_by_time.empty(), "Sanity"); - return _vouchers_by_time.back().voucher(); -} - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void MachineThread::validate() const { - ASSERT(_process, "Sanity"); - ASSERT(_process->timespan().contains(timespan()), "Sanity"); - - ASSERT(is_trange_vector_sorted_and_non_overlapping(_blocked), "Sanity"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(_vm_faults), "Sanity"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(_jetsam_activity), "Sanity"); - ASSERT(is_trange_vector_sorted_and_non_overlapping(_vouchers_by_time), "Sanity"); - - if (!_blocked.empty()) { - ASSERT(_timespan.contains(_blocked.front()), "Blocked interval not contained by thread timespan"); - ASSERT(_timespan.contains(_blocked.back()), "Blocked interval not contained by thread timespan"); - } - - if (!_vm_faults.empty()) { - ASSERT(_timespan.contains(_vm_faults.front()), "vm fault interval not contained by thread timespan"); - ASSERT(_timespan.contains(_vm_faults.back()), "vm_fault interval not contained by thread timespan"); - } - - if (!_jetsam_activity.empty()) { - ASSERT(_timespan.contains(_jetsam_activity.front()), "jetsam_activity interval not contained by thread timespan"); - ASSERT(_timespan.contains(_jetsam_activity.back()), "jetsam_activity interval not contained by thread timespan"); - } - - if (!_vouchers_by_time.empty()) { - ASSERT(_timespan.contains(_vouchers_by_time.front()), "vouchers_by_time interval not contained by thread timespan"); - ASSERT(_timespan.contains(_vouchers_by_time.back()), "vouchers_by_time interval not contained by thread timespan"); - } - - ASSERT(!_process->is_trace_terminated() || is_trace_terminated(), "Process is trace terminated but thread is live"); - - // Each thread should have at least one creation flag. - // Note that created by previous machine state is in addition to the - // actual create flag, so does not count - ASSERT(is_created_by_thread_map() || - is_created_by_trace_data_new_thread() || - is_created_by_unknown_tid_in_trace() || - is_created_by_fork_exec() || - is_created_by_exec(), "Should have at least one create flag"); -} -#endif diff --git a/KDBG/MachineThread.mutable-impl.hpp b/KDBG/MachineThread.mutable-impl.hpp deleted file mode 100644 index 0ae018a..0000000 --- a/KDBG/MachineThread.mutable-impl.hpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// MachineThread.mutable-impl.hpp -// KDBG -// -// Created by James McIlree on 10/30/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - - -template -void MachineThread::set_is_idle_thread() { - ASSERT(!is_trace_terminated(), "Attempt to mark terminated thread as IDLE"); - ASSERT(_process->is_kernel(), "Attempt to set non-kernel thread as IDLE"); - - set_flags(kMachineThreadFlag::IsIdle); -} - -template -void MachineThread::set_trace_terminated(AbsTime timestamp) { - ASSERT(!is_trace_terminated(), "Attempt to trace terminate thread more than once"); - ASSERT(!is_idle_thread(), "Attempt to terminate IDLE thread"); - - AbsTime terminated_timestamp = timestamp + AbsTime(1); - - // If we were killed with a block event pending, we need to flush it - // to the queue. The make_runnable call will do sanity checks to - // handle the corner cases when called from here. - make_runnable(terminated_timestamp); - - // We need to set the final timestamp for this thread's last voucher. - // Note that the null voucher and unset voucher are actual objects, - // they are not represented by NULL or nullptr. - _vouchers_by_time.back().set_max(terminated_timestamp); - - // - // Finally set this threads timespan - // - _timespan.set_max(terminated_timestamp); - - - set_flags(kMachineThreadFlag::TraceTerminated); -} - -template -void MachineThread::make_runnable(AbsTime timestamp) { - ASSERT(!is_trace_terminated(), "Attempting to make terminated thread runnable"); - ASSERT(timestamp >= _timespan.location(), "Attempt to make thread runnable before it exists"); - - if (_begin_blocked > 0) { - ASSERT(timestamp > _begin_blocked, "Sanity"); - ASSERT(_blocked.empty() || _begin_blocked > _blocked.back().max(), "Out of order blocked regions"); - _blocked.emplace_back(_begin_blocked, timestamp - _begin_blocked); - _begin_blocked = AbsTime(0); - } -} - -template -void MachineThread::make_unrunnable(AbsTime timestamp) { - ASSERT(!is_trace_terminated(), "Attempting to make terminated thread unrunnable"); - ASSERT(timestamp >= _timespan.location(), "Attempt to make thread unrunnable before it exists"); - - _begin_blocked = timestamp; -} - -template -void MachineThread::begin_vm_fault(AbsTime timestamp) { - ASSERT(timestamp >= _timespan.location(), "Attempt to begin vm fault before thread exists"); - ASSERT(!is_trace_terminated(), "Attempt to begin vm fault on thread that has terminated"); - ASSERT(!is_idle_thread(), "Attempt to begin vm fault on IDLE thread"); - - ASSERT(_begin_vm_fault == 0, "Attempt to begin vm_fault without end"); - _begin_vm_fault = timestamp; -} - -template -void MachineThread::end_vm_fault(AbsTime timestamp) { - ASSERT(timestamp >= _timespan.location(), "Attempt to end vm fault before thread exists"); - ASSERT(!is_trace_terminated(), "Attempt to end vm fault on thread that has terminated"); - ASSERT(!is_idle_thread(), "Attempt to end vm fault on IDLE thread"); - - if (_begin_vm_fault > 0) { - ASSERT(timestamp > _begin_vm_fault, "Sanity"); - ASSERT(_vm_faults.empty() || _begin_vm_fault > _vm_faults.back().max(), "Out of order vm_fault regions"); - _vm_faults.emplace_back(_begin_vm_fault, timestamp - _begin_vm_fault); - _begin_vm_fault = AbsTime(0); - } -} - -template -void MachineThread::begin_jetsam_activity(uint32_t type, AbsTime timestamp) { - ASSERT(timestamp >= _timespan.location(), "Attempt to begin jetsam activity before thread exists"); - ASSERT(!is_trace_terminated(), "Attempt to begin jetsam activity on thread that has terminated"); - ASSERT(!is_idle_thread(), "Attempt to begin jetsam activity on IDLE thread"); - - ASSERT(_begin_jetsam_activity == 0, "Attempt to begin jetsam activity without end"); - ASSERT(_begin_jetsam_activity_type == 0, "Sanity"); - - _begin_jetsam_activity = timestamp; - DEBUG_ONLY(_begin_jetsam_activity_type = type;) -} - -template -void MachineThread::end_jetsam_activity(uint32_t type, AbsTime timestamp) { - ASSERT(timestamp >= _timespan.location(), "Attempt to end jetsam activity before thread exists"); - ASSERT(!is_trace_terminated(), "Attempt to end jetsam activity on thread that has terminated"); - ASSERT(!is_idle_thread(), "Attempt to end jetsam activity on IDLE thread"); - - if (_begin_jetsam_activity > 0) { - ASSERT(type == _begin_jetsam_activity_type, "End event type does not match start event"); - ASSERT(timestamp > _begin_jetsam_activity, "Sanity"); - ASSERT(_jetsam_activity.empty() || _begin_jetsam_activity > _jetsam_activity.back().max(), "Out of order jetsam activities"); - _jetsam_activity.emplace_back(_begin_jetsam_activity, timestamp - _begin_jetsam_activity); - _begin_jetsam_activity = AbsTime(0); - DEBUG_ONLY(_begin_jetsam_activity_type = 0;) - } -} - -template -void MachineThread::set_voucher(MachineVoucher* voucher, AbsTime timestamp) { - ASSERT(timestamp >= _timespan.location(), "Attempt to set voucher on thread before thread exists"); - ASSERT(!is_trace_terminated(), "Attempt to set voucher on terminated thread"); - ASSERT(!is_idle_thread(), "Attempt to set voucher on IDLE thread"); - ASSERT(!_vouchers_by_time.empty() || _vouchers_by_time.back().max() < timestamp, "Sanity"); - ASSERT(_vouchers_by_time.back().location() < timestamp, "Sanity"); - - VoucherInterval& last_voucher = _vouchers_by_time.back(); - - if (voucher != last_voucher.voucher()) { - ASSERT(last_voucher.max() == AbsTime::END_OF_TIME, "Sanity"); - - // - // By default, the voucher interval has the last voucher continuing "forever". - // We need to trim the time used by that voucher, while handling the case of - // the very first event setting a new voucher as well. - // - // There are three cases possible. - // - // 1) timestamp > last_voucher.location // This is the expected case - // 2) timestamp == last_voucher.location // This should only be possible on the very first event for a thread - // 3) timestamp < last_voucher.location // This is an error at all times. - // - - if (timestamp > last_voucher.location()) { - // Expected case (#1) - last_voucher.set_max(timestamp); - _vouchers_by_time.emplace_back(voucher, AbsInterval(timestamp, AbsTime::END_OF_TIME - timestamp)); - } else if (timestamp == last_voucher.location()) { - // Corner case (#2) - // - // Note that we cannot assert that the voucher being replaced is the unset voucher, - // as vouchers are forwarded during "live" event handling. This means that the thread - // may have a valid voucher that is replaced on the first event. - // - // The timestamp == _timespan.location assert may also be too strong, if we start forwarding threads true lifetimes. - - ASSERT(timestamp == _timespan.location(), "Should only be overriding a voucher on the first event for a given thread."); - ASSERT(_vouchers_by_time.size() == 1, "Attempt to replace the current voucher when it isn't the first voucher"); - _vouchers_by_time.pop_back(); - _vouchers_by_time.emplace_back(voucher, AbsInterval(timestamp, AbsTime::END_OF_TIME - timestamp)); - } else { - ASSERT(false, "Attempting to set a voucher on thread earlier in time than the thread's current voucher"); - - } - } -} - -template -void MachineThread::post_initialize(AbsTime last_machine_timestamp) { - if (!is_trace_terminated()) { - // - // For threads that are still alive at the post_initialize phase, - // we want to extend their timespan(s) to the end of the machine state, - // so they can be looked up by tid/timestamp - // - ASSERT(_timespan.length() == 0, "Sanity"); - - // Time in a range is always half open. [ 10, 11 ) means 10 is included, - // but 11 is not. In order to include a given timestamp, we must use - // a value one greater. - AbsTime half_open_timestamp = last_machine_timestamp + AbsTime(1); - - _timespan.set_max(half_open_timestamp); - - // 6/22/2014 Not sure about this. Just working on the massive time - // cleanup, along with the "we really know when threads and processes - // are done" cleanup. We used to always check and flush any outstanding - // blocked events in post_initialize. This is done explicitly in the trace - // terminated code now. However, it is possible to have a blocked event - // outstanding in a live thread at this point. If we actually forward state - // to future threads, we would want to pick that up, right? - // - // So what do we do here? - // - // We could make sure the intermediate states were properly fowarded - // as the threads are forwarded. That leaves the problem of queries against - // this machine state not showing an existing blocked state, which could - // have begun long ago. - // - // If we flush, how do we tag that last block so the forwarding happens - // correctly? - // - // For now, no one is doing the live update thing and using the cpu - // states, so I'm going to flush. - // - // Note that if the very last event is a make_unrunnable for a thread, - // this is going to yield a zero length blocking event, which might assert. - // - // NEEDS REVIEW, FIX ME. - make_runnable(half_open_timestamp); - - _vouchers_by_time.back().set_max(half_open_timestamp); - } -} diff --git a/KDBG/MachineVoucher.hpp b/KDBG/MachineVoucher.hpp deleted file mode 100644 index 6660b0b..0000000 --- a/KDBG/MachineVoucher.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// MachineVoucher.hpp -// KDBG -// -// Created by James McIlree on 2/18/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kernel_perf_cmds_MachineVoucher_hpp -#define kernel_perf_cmds_MachineVoucher_hpp - -template class Machine; - -enum class kMachineVoucherFlag : std::uint32_t { - CreatedByVoucherCreate = 0x00000001, - CreatedByFirstUse = 0x00000002, - CreatedByPreviousMachineState = 0x00000004, - IsNullVoucher = 0x00000008, - IsUnsetVoucher = 0x00000010, - IsDestroyed = 0x00000020 -}; - -template -class MachineVoucher { - protected: - AbsInterval _timespan; - uint8_t* _content_bytes; - uint32_t _content_bytes_size; - uint32_t _content_bytes_capacity; - uint32_t _id; - uint32_t _flags; - typename SIZE::ptr_t _address; - - static uint32_t voucher_id(); - - // Voucher pointers are used as unique identifiers for the lifespan - // of the voucher, which may exceed the lifespan of the Machine. - // We may not copy or "move" a voucher. - - // Disable copy operators - MachineVoucher(const MachineVoucher& ignored) = delete; - MachineVoucher& operator=(const MachineVoucher& ignored) = delete; - - // Disable move operators - MachineVoucher(MachineVoucher&& ignored) = delete; - MachineVoucher& operator=(MachineVoucher&& ignored) = delete; - - friend class Machine; - - void workaround_16898190(kMachineVoucherFlag flags, uint32_t content_bytes_capacity); - - void add_content_bytes(uint8_t* bytes); - - void set_destroyed(AbsTime timestamp); - - // These are needed to make vouchers that are still alive at the - // end of an event trace appear correctly in searches/queries. - // However, when forwarding live vouchers to a future machine state, - // that work must be undone. - void set_timespan_to_end_of_time() { - ASSERT(is_live(), "Modifying timespan of destroyed voucher"); - ASSERT(_timespan.length() == 0, "Modifying timespan after it has already been set"); - _timespan.set_length(AbsTime(UINT64_MAX) - _timespan.location()); - } - - void set_timespan_to_zero_length() { - ASSERT(is_live(), "Modifying timespan of destroyed voucher"); - ASSERT(_timespan.max() == UINT64_MAX, "Modifying timespan after it has already been set"); - _timespan.set_length(AbsTime(0)); - } - - public: - MachineVoucher(typename SIZE::ptr_t address, AbsInterval create_timespan, kMachineVoucherFlag flags, uint32_t content_bytes_capacity); - - ~MachineVoucher() { - if (_content_bytes) { - free(_content_bytes); - _content_bytes = nullptr; - } - } - - bool operator==(const MachineVoucher& rhs) const { return this->_id == rhs._id; } - bool operator!=(const MachineVoucher& rhs) const { return !(*this == rhs); } - - bool is_live() const { return (_flags & (uint32_t)kMachineVoucherFlag::IsDestroyed) == 0; } - bool is_destroyed() const { return (_flags & (uint32_t)kMachineVoucherFlag::IsDestroyed) > 0; } - bool is_null() const { return (_flags & (uint32_t)kMachineVoucherFlag::IsNullVoucher) > 0; } - bool is_unset() const { return (_flags & (uint32_t)kMachineVoucherFlag::IsUnsetVoucher) > 0; } - bool is_created_by_voucher_create() const { return (_flags & (uint32_t)kMachineVoucherFlag::CreatedByVoucherCreate) > 0; } - bool is_created_by_first_use() const { return (_flags & (uint32_t)kMachineVoucherFlag::CreatedByFirstUse) > 0; } - bool is_created_by_previous_machine_state() const { return (_flags & (uint32_t)kMachineVoucherFlag::CreatedByPreviousMachineState) > 0; } - bool has_valid_contents() const { return _content_bytes_size > 0 && _content_bytes_size == _content_bytes_capacity; } - - typename SIZE::ptr_t address() const { return _address; } - AbsInterval timespan() const { return _timespan; } - const uint8_t* content_bytes() const { return _content_bytes; } - uint32_t content_size() const { return _content_bytes_capacity; } - uint32_t id() const { return _id; } -}; - -template -uint32_t MachineVoucher::voucher_id() { - static uint32_t voucher_id = 1; - return OSAtomicIncrement32Barrier((volatile int32_t*)&voucher_id); -} - -template -MachineVoucher::MachineVoucher(typename SIZE::ptr_t address, AbsInterval timespan, kMachineVoucherFlag flags, uint32_t content_bytes_capacity) : - _timespan(timespan), - _content_bytes((content_bytes_capacity > 0) ? (uint8_t*)malloc((size_t)content_bytes_capacity) : nullptr), - _content_bytes_size(0), - _content_bytes_capacity(content_bytes_capacity), - _id(voucher_id()), - _flags((uint32_t)flags), - _address(address) -{ - DEBUG_ONLY({ - if (!is_null() && !is_unset()) { - ASSERT(timespan.location() != 0 || is_created_by_first_use(), "Only implicitly created vouchers should have an unknown (0) create time"); - ASSERT(is_created_by_voucher_create() || is_created_by_first_use() , "Should have a create flag"); - ASSERT(content_bytes_capacity == 0 || is_created_by_voucher_create(), "Implicitly created vouchers should not have content"); - } - }) -} - -template -void MachineVoucher::workaround_16898190(kMachineVoucherFlag flags, uint32_t content_bytes_capacity) { - ASSERT(_content_bytes_capacity == 0, "Attempting to reset non-zero content_bytes_capacity"); - ASSERT(!is_null(), "Sanity"); - ASSERT(!is_unset(), "Sanity"); - ASSERT(is_live(), "Should be live"); // This may be too strong, some races could have destroy before create - - _flags |= (uint32_t)flags; - _content_bytes_capacity = content_bytes_capacity; -} - -template -void MachineVoucher::add_content_bytes(uint8_t* src) { - ASSERT(src, "Sanity"); - - // If the first reference we see to a voucher is an MACH_IPC_VOUCHER_CREATE_ATTR_DATA, - // we will not have contents. - if (!is_created_by_first_use()) { - size_t bytes_remaining = _content_bytes_capacity - _content_bytes_size; - ASSERT(bytes_remaining > 0, "Sanity"); - - // We either write an entire tracepoint worth of data, - // or the # of bytes remaining. - size_t bytes_to_write = std::min(bytes_remaining, sizeof(typename SIZE::ptr_t) * 4); - auto dest = &_content_bytes[_content_bytes_size]; - memcpy(dest, src, bytes_to_write); - _content_bytes_size += bytes_to_write; - } -} - -template -void MachineVoucher::set_destroyed(AbsTime timestamp) { - ASSERT(!is_destroyed(), "Sanity"); - ASSERT(timestamp > _timespan.location(), "Sanity"); - ASSERT(_timespan.length() == 0, "Sanity"); - - // It turns out this is too strong. The kernel has a limited amount of buffer space available - // to hold the voucher contents. If the voucher exceeds that, no contents are emitted, and we - // fail this assert. - // ASSERT(_content_bytes_capacity == _content_bytes_size, "Destroying voucher with incomplete contents"); - - // +1 to make sure searches for this voucher at the destroy timestamp - // can find it. - _timespan.set_length((timestamp - _timespan.location()) + AbsTime(1)); - _flags |= (uint32_t)kMachineVoucherFlag::IsDestroyed; -} - - -#endif diff --git a/KDBG/MetaTypes.hpp b/KDBG/MetaTypes.hpp deleted file mode 100644 index 98b0324..0000000 --- a/KDBG/MetaTypes.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// MetaTypes.hpp -// KDBG -// -// Created by James McIlree on 10/24/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -class Kernel32 -{ - public: - typedef uint32_t ptr_t; - - enum { PTRMAX = UINT32_MAX }; - enum { is_64_bit = 0 }; -}; - -class Kernel64 -{ - public: - typedef uint64_t ptr_t; - - enum { PTRMAX = UINT64_MAX }; - enum { is_64_bit = 1 }; -}; diff --git a/KDBG/NurseryMachMsg.hpp b/KDBG/NurseryMachMsg.hpp deleted file mode 100644 index 52b084e..0000000 --- a/KDBG/NurseryMachMsg.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// NurseryMachMsg.hpp -// KDBG -// -// Created by James McIlree on 2/20/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kernel_perf_cmds_NurseryMachMsg_hpp -#define kernel_perf_cmds_NurseryMachMsg_hpp - -enum class kNurseryMachMsgState : std::uint32_t { - Uninitialized = 1, - Send, - Recv, - Free -}; - -template -class NurseryMachMsg { - protected: - AbsTime _send_time; - MachineVoucher* _send_voucher; - - typename SIZE::ptr_t _send_tid; - typename SIZE::ptr_t _kmsg_addr; - - uint32_t _id; // This is globally unique for EACH message. - uint32_t _send_msgh_id; - uint32_t _send_msgh_bits; // msgh_bits is modified between send/recv - kNurseryMachMsgState _state; - - // These are intptr_t's so they can be set to -1, indicating "no index" - intptr_t _send_event_index; - - public: - static uint32_t message_id(); - - NurseryMachMsg(typename SIZE::ptr_t kmsg_addr) : - _kmsg_addr(kmsg_addr), - _state(kNurseryMachMsgState::Uninitialized) - { - } - - void send(uintptr_t index, AbsTime time, typename SIZE::ptr_t tid, typename SIZE::ptr_t kmsg_addr, uint32_t msgh_bits, uint32_t msgh_id, MachineVoucher* voucher); - - kNurseryMachMsgState state() const { return _state; } - void set_state(kNurseryMachMsgState state) { _state = state; } - - AbsTime send_time() const { return _send_time; } - typename SIZE::ptr_t send_tid() const { return _send_tid; } - - typename SIZE::ptr_t kmsg_addr() const { return _kmsg_addr; } - MachineVoucher* send_voucher() const { return _send_voucher; } - - uint32_t id() const { return _id; } - uint32_t send_msgh_id() const { return _send_msgh_id; } - uint32_t send_msgh_bits() const { return _send_msgh_bits; } - - void set_send_event_index(intptr_t value) { _send_event_index = value; } - intptr_t send_event_index() const { return _send_event_index; } -}; - -template -uint32_t NurseryMachMsg::message_id() { - static uint32_t message_id = 1; - return OSAtomicIncrement32Barrier((volatile int32_t*)&message_id); -} - -template -void NurseryMachMsg::send(uintptr_t index, AbsTime time, typename SIZE::ptr_t tid, typename SIZE::ptr_t kmsg_addr, uint32_t msgh_bits, uint32_t msgh_id, MachineVoucher* voucher) { - ASSERT(_state == kNurseryMachMsgState::Uninitialized || _state == kNurseryMachMsgState::Free, "Calling send when msg is not in Uninitialized/Free state"); - ASSERT(kmsg_addr == _kmsg_addr, "Sanity"); - - ASSERT(tid, "Sanity"); - ASSERT(msgh_bits, "Sanity"); - - _id = NurseryMachMsg::message_id(); - - _send_event_index = index; - _send_time = time; - _send_tid = tid; - // _kmsg_addr = kmsg_addr; - _send_msgh_bits = msgh_bits; - _send_msgh_id = msgh_id; - _send_voucher = voucher; -} - -#endif diff --git a/KDBG/ProcessSummary.hpp b/KDBG/ProcessSummary.hpp deleted file mode 100644 index 1912eb3..0000000 --- a/KDBG/ProcessSummary.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// ProcessSummary.hpp -// KDBG -// -// Created by James McIlree on 4/23/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_ProcessSummary_hpp -#define kdprof_ProcessSummary_hpp - -template -class MachineProcess; - -template -class MachineThread; - -template -class CPUSummary; - -template -class ProcessSummary { - public: - typedef std::unordered_set, ThreadSummaryHash, ThreadSummaryEqualTo> ThreadSummarySet; - - protected: - const MachineProcess* _process; - - AbsTime _total_run_time; - AbsTime _total_idle_time; - AbsTime _total_intr_time; - AbsTime _total_future_run_time; - AbsTime _total_wallclock_run_time; - AbsTime _total_vm_fault_time; - AbsTime _total_io_time; - AbsTime _total_jetsam_time; - - uint32_t _context_switch_count; - uint32_t _count_idle_events; - uint32_t _count_intr_events; - uint32_t _count_vm_fault_events; - uint32_t _count_io_events; - bool _is_jetsam_killed; - - uint64_t _io_bytes_completed; - - ThreadSummarySet _thread_summaries; - - std::vector _wallclock_run_intervals; // This is the actual wallclock run interval data. - std::vector _per_cpu_wallclock_run_intervals; // We need to accumulate intervals during summary generation, this is a temp buffer. - - friend class Machine; - friend class CPUSummary; - - void add_run_time(AbsTime time) { _total_run_time += time; } - void add_idle_time(AbsTime time) { _total_idle_time += time; _count_idle_events++; } - void add_intr_time(AbsTime time) { _total_intr_time += time; _count_intr_events++; } - void add_future_run_time(AbsTime time) { _total_future_run_time += time; } - void add_vm_fault_time(AbsTime time) { _total_vm_fault_time += time; _count_vm_fault_events++; } - void add_io_time(AbsTime time) { _total_io_time += time; _count_io_events++; } - void add_jetsam_time(AbsTime time) { _total_jetsam_time += time; } - - void add_io_bytes_completed(typename SIZE::ptr_t bytes) { _io_bytes_completed += bytes; } - - // - // Wallclock run intervals are added as each cpu timeline is walked. - // Between cpu(s), the results are accumulated to a single buffer - // After all cpus have been processed, the single buffer is summarized - // - void add_wallclock_run_interval(AbsInterval interval); - void accumulate_wallclock_run_intervals(); - void summarize_wallclock_run_intervals(); - - void incr_context_switches() { _context_switch_count++; } - - void set_jetsam_killed() { ASSERT(!_is_jetsam_killed, "Attempt to jetsam process twice"); _is_jetsam_killed = true; } - - ThreadSummary* mutable_thread_summary(const MachineThread* thread) { - auto it = _thread_summaries.find(thread); - if (it == _thread_summaries.end()) { - // We create any thread summary that is missing. - auto insert_result = _thread_summaries.emplace(thread); - ASSERT(insert_result.second, "Sanity"); - it = insert_result.first; - } - - // NOTE! Because we are using a Set instead of a Map, STL wants - // the objects to be immutable. "it" refers to a const Record, to - // prevent us from changing the hash or equality of the Set. We - // know that the allowed set of mutations will not change these, - // and so we evil hack(tm) and cast away the const'ness. - return const_cast*>(&*it); - } - - ThreadSummarySet& mutable_thread_summaries() { return _thread_summaries; } - - public: - ProcessSummary(const MachineProcess* process) : - _process(process), - _context_switch_count(0), - _count_idle_events(0), - _count_intr_events(0), - _count_vm_fault_events(0), - _count_io_events(0), - _is_jetsam_killed(false), - _io_bytes_completed(0) - { - } - - const MachineProcess* process() const { return _process; } - - AbsTime total_time() const { return _total_run_time + _total_idle_time + _total_intr_time; } - AbsTime total_run_time() const { return _total_run_time; } - AbsTime total_idle_time() const { return _total_idle_time; } - AbsTime total_intr_time() const { return _total_intr_time; } - AbsTime total_future_run_time() const { return _total_future_run_time; } - AbsTime total_wallclock_run_time() const { return _total_wallclock_run_time; } - AbsTime total_vm_fault_time() const { return _total_vm_fault_time; } - AbsTime total_io_time() const { return _total_io_time; } - AbsTime total_jetsam_time() const { return _total_jetsam_time; } - - AbsTime avg_on_cpu_time() const { return _total_run_time / _context_switch_count; } - - uint32_t context_switches() const { return _context_switch_count; } - uint32_t num_idle_events() const { return _count_idle_events; } - uint32_t num_intr_events() const { return _count_intr_events; } - uint32_t num_vm_fault_events() const { return _count_vm_fault_events; } - uint32_t num_io_events() const { return _count_io_events; } - uint32_t num_processes_jetsammed() const { return _is_jetsam_killed ? 1 : 0; } - - uint64_t io_bytes_completed() const { return _io_bytes_completed; } - - const ThreadSummarySet& thread_summaries() const { return _thread_summaries; } - - const ThreadSummary* thread_summary(const MachineThread* thread) const { - auto it = _thread_summaries.find(thread); - return (it == _thread_summaries.end()) ? NULL : &*it; - } - - DEBUG_ONLY(void validate() const;) -}; - -template -void ProcessSummary::add_wallclock_run_interval(AbsInterval interval) { - ASSERT(_per_cpu_wallclock_run_intervals.empty() || (_per_cpu_wallclock_run_intervals.back() < interval && !interval.intersects(_per_cpu_wallclock_run_intervals.back())), "Invariant violated"); - _per_cpu_wallclock_run_intervals.emplace_back(interval); -} - -template -void ProcessSummary::accumulate_wallclock_run_intervals() { - _wallclock_run_intervals = trange_vector_union(_wallclock_run_intervals, _per_cpu_wallclock_run_intervals); - _per_cpu_wallclock_run_intervals.clear(); - // We don't shrink_to_fit here as its expected another CPU's run intervals will be processed next. -} - -template -void ProcessSummary::summarize_wallclock_run_intervals() { - ASSERT(_per_cpu_wallclock_run_intervals.empty(), "Sanity"); - _per_cpu_wallclock_run_intervals.shrink_to_fit(); - - ASSERT(_total_wallclock_run_time == 0, "Called more than once"); - - ASSERT(is_trange_vector_sorted_and_non_overlapping(_wallclock_run_intervals), "Sanity"); - - for (auto& interval : _wallclock_run_intervals) { - _total_wallclock_run_time += interval.length(); - } - - _wallclock_run_intervals.clear(); - _wallclock_run_intervals.shrink_to_fit(); -} - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void ProcessSummary::validate() const { - ASSERT(_total_wallclock_run_time <= _total_run_time, "Sanity"); - - for (const auto& thread_summary : _thread_summaries) { - thread_summary.validate(); - } -} -#endif - -template -struct ProcessSummaryHash { - size_t operator()(const ProcessSummary& summary) const { - return std::hash*>()(summary.process()); - } -}; - -template -struct ProcessSummaryEqualTo { - bool operator()(const ProcessSummary& s1, const ProcessSummary& s2) const { - return s1.process() == s2.process(); - } -}; - -#endif diff --git a/KDBG/TaskEffectivePolicy.hpp b/KDBG/TaskEffectivePolicy.hpp deleted file mode 100644 index 1a4ebc4..0000000 --- a/KDBG/TaskEffectivePolicy.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// TaskEffectivePolicy.hpp -// system_cmds -// -// Created by James McIlree on 6/19/14. -// -// - -// Using the raw struct was causing alignment issues on arm32; it seems that -// structs have very relaxed alignment requirements on the v7 architectures. -// The class wrapper forces a higher alignment and allows for some convenience -// operators (compare, xor, etc) - -class TaskEffectivePolicy { - protected: - union { - Kernel32::ptr_t _kernel_32[2]; - Kernel64::ptr_t _kernel_64; - struct task_effective_policy _policy; - } _content; - - public: - TaskEffectivePolicy() {} - - TaskEffectivePolicy(struct task_effective_policy policy) { - static_assert(sizeof(_content) == sizeof(struct task_effective_policy), "Sanity"); - _content._policy = policy; - } - - TaskEffectivePolicy(Kernel64::ptr_t teffective_0) { - static_assert(sizeof(_content) == sizeof(teffective_0), "Sanity"); - _content._kernel_64 = teffective_0; - } - - TaskEffectivePolicy(Kernel32::ptr_t teffective_0, Kernel32::ptr_t teffective_1) { - static_assert(sizeof(_content) == (sizeof(teffective_0) + sizeof(teffective_1)), "Sanity"); - _content._kernel_32[0] = teffective_0; - _content._kernel_32[1] = teffective_1; - } - - bool operator==(const TaskEffectivePolicy& other) const { return this->_content._kernel_64 == other._content._kernel_64; } - bool operator!=(const TaskEffectivePolicy& other) const { return !(*this == other); } - - TaskEffectivePolicy operator~() const { return TaskEffectivePolicy(~this->_content._kernel_64); } - - struct task_effective_policy as_struct() { return _content._policy; } -}; \ No newline at end of file diff --git a/KDBG/TaskRequestedPolicy.hpp b/KDBG/TaskRequestedPolicy.hpp deleted file mode 100644 index a36d370..0000000 --- a/KDBG/TaskRequestedPolicy.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// TaskRequestedPolicy.hpp -// system_cmds -// -// Created by James McIlree on 6/23/14. -// -// - - -// Using the raw struct was causing alignment issues on arm32; it seems that -// structs have very relaxed alignment requirements on the v7 architectures. -// The class wrapper forces a higher alignment and allows for some convenience -// operators (compare, xor, etc) - -class TaskRequestedPolicy { - protected: - union { - Kernel32::ptr_t _kernel_32[2]; - Kernel64::ptr_t _kernel_64; - struct task_requested_policy _policy; - } _content; - - public: - TaskRequestedPolicy() {} - - TaskRequestedPolicy(struct task_requested_policy policy) { - static_assert(sizeof(_content) == sizeof(struct task_requested_policy), "Sanity"); - _content._policy = policy; - } - - TaskRequestedPolicy(Kernel64::ptr_t trequested_0) { - static_assert(sizeof(_content) == sizeof(trequested_0), "Sanity"); - _content._kernel_64 = trequested_0; - } - - TaskRequestedPolicy(Kernel32::ptr_t trequested_0, Kernel32::ptr_t trequested_1) { - static_assert(sizeof(_content) == (sizeof(trequested_0) + sizeof(trequested_1)), "Sanity"); - _content._kernel_32[0] = trequested_0; - _content._kernel_32[1] = trequested_1; - } - - bool operator==(const TaskRequestedPolicy& other) const { return this->_content._kernel_64 == other._content._kernel_64; } - bool operator!=(const TaskRequestedPolicy& other) const { return !(*this == other); } - - TaskRequestedPolicy operator~() const { return TaskRequestedPolicy(~this->_content._kernel_64); } - - struct task_requested_policy as_struct() { return _content._policy; } -}; \ No newline at end of file diff --git a/KDBG/ThreadSummary.hpp b/KDBG/ThreadSummary.hpp deleted file mode 100644 index 5dda461..0000000 --- a/KDBG/ThreadSummary.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// ThreadSummary.hpp -// KDBG -// -// Created by James McIlree on 4/23/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kdprof_ThreadSummary_hpp -#define kdprof_ThreadSummary_hpp - -template -class MachineThread; - -template -class ThreadSummary { - protected: - const MachineThread* _thread; - - AbsTime _total_run_time; - AbsTime _total_idle_time; - AbsTime _total_intr_time; - AbsTime _total_vm_fault_time; - AbsTime _total_io_time; - AbsTime _total_jetsam_time; - - uint32_t _context_switch_count; - uint32_t _count_idle_events; - uint32_t _count_intr_events; - uint32_t _count_vm_fault_events; - uint32_t _count_io_events; - - uint64_t _io_bytes_completed; - - AbsTime _total_future_run_time; - - // Future run helper vars - AbsTime _total_blocked_in_summary; - AbsTime _max_possible_future_run_time; - AbsTime _first_block_after_summary; - bool _is_blocked_in_future; - bool _is_future_initialized; - - friend class Machine; - - void add_run_time(AbsTime time) { _total_run_time += time; } - void add_idle_time(AbsTime time) { _total_idle_time += time; _count_idle_events++; } - void add_intr_time(AbsTime time) { _total_intr_time += time; _count_intr_events++; } - void add_vm_fault_time(AbsTime time) { _total_vm_fault_time += time; _count_vm_fault_events++; } - void add_io_time(AbsTime time) { _total_io_time += time; _count_io_events++; } - void add_jetsam_time(AbsTime time) { _total_jetsam_time += time; } - - void add_io_bytes_completed(typename SIZE::ptr_t bytes) { _io_bytes_completed += bytes; } - - void incr_context_switches() { _context_switch_count++; } - - bool is_blocked_in_future() { return _is_blocked_in_future; } - void set_is_blocked_in_future() { _is_blocked_in_future = true; } - - AbsTime total_blocked_in_summary() { return _total_blocked_in_summary; } - void set_total_blocked_in_summary(AbsTime time) { _total_blocked_in_summary = time; } - - AbsTime max_possible_future_run_time() { return _max_possible_future_run_time; } - void set_max_possible_future_run_time(AbsTime time) { _max_possible_future_run_time = time; } - - AbsTime first_block_after_summary() { return _first_block_after_summary; } - void set_first_block_after_summary(AbsTime time) { _first_block_after_summary = time; } - - bool is_future_initialized() { return _is_future_initialized; } - void set_future_initialized() { _is_future_initialized = true; } - - AbsTime add_future_run_time(AbsTime time) { - ASSERT(_is_future_initialized, "Sanity"); - ASSERT(!_is_blocked_in_future, "Sanity"); - - AbsTime capped_time = _max_possible_future_run_time - _total_future_run_time; - if (capped_time < time) { - _total_future_run_time += capped_time; - _is_blocked_in_future = true; - return capped_time; - } else { - _total_future_run_time += time; - return time; - } - - ASSERT(_total_future_run_time < _max_possible_future_run_time, "Sanity"); - } - - public: - ThreadSummary(const MachineThread* thread) : - _thread(thread), - _context_switch_count(0), - _count_idle_events(0), - _count_intr_events(0), - _count_vm_fault_events(0), - _count_io_events(0), - _io_bytes_completed(0), - _is_blocked_in_future(false), - _is_future_initialized(false) - { - } - - const MachineThread* thread() const { return _thread; } - - AbsTime total_time() const { return _total_run_time + _total_idle_time + _total_intr_time; } - - AbsTime total_run_time() const { return _total_run_time; } - AbsTime total_idle_time() const { return _total_idle_time; } - AbsTime total_intr_time() const { return _total_intr_time; } - AbsTime total_future_run_time() const { return _total_future_run_time; } - AbsTime total_vm_fault_time() const { return _total_vm_fault_time; } - AbsTime total_wallclock_vm_fault_time() const { return _total_vm_fault_time; } - AbsTime total_io_time() const { return _total_io_time; } - AbsTime total_jetsam_time() const { return _total_jetsam_time; } - - AbsTime avg_on_cpu_time() const { return _total_run_time / _context_switch_count; } - - uint32_t context_switches() const { return _context_switch_count; } - uint32_t num_idle_events() const { return _count_idle_events; } - uint32_t num_intr_events() const { return _count_intr_events; } - uint32_t num_vm_fault_events() const { return _count_vm_fault_events; } - uint32_t num_io_events() const { return _count_io_events; } - - uint64_t io_bytes_completed() const { return _io_bytes_completed; } - - DEBUG_ONLY(void validate() const); -}; - -#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS) -template -void ThreadSummary::validate() const { -} -#endif - -template -struct ThreadSummaryHash { - size_t operator()(const ThreadSummary& summary) const { - return std::hash*>()(summary.thread()); - } -}; - -template -struct ThreadSummaryEqualTo { - bool operator()(const ThreadSummary& s1, const ThreadSummary& s2) const { - return s1.thread() == s2.thread(); - } -}; - -#endif diff --git a/KDBG/TraceCodes.cpp b/KDBG/TraceCodes.cpp deleted file mode 100644 index db55de1..0000000 --- a/KDBG/TraceCodes.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// TraceCodes.cpp -// KDBG -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "KDebug.h" - -std::vector default_trace_code_paths() { - // As of 4/17/2013, this is a single file. - return { "/usr/share/misc/trace.codes" }; -} - -std::unordered_map trace_codes_at_path(const char* path) -{ - std::unordered_map codes; - - if (FILE* fp = fopen(path, "r")) { - char line[PATH_MAX]; - - while (fgets(line, sizeof(line), fp)) { - int code; - char name[128]; - if (sscanf(line, "%x%127s\n", &code, name) == 2) { - ASSERT(code != 0, "Should never have a code equal to zero"); - ASSERT(strlen(name), "Invalid name"); - codes[code] = name; - } - } - - fclose(fp); - } - - return codes; -} - -std::unordered_map resolve_trace_codes(bool should_read_default_codes, int output_fd, std::vector& additional_paths) { - std::unordered_map codes; - - std::vector paths; - - if (should_read_default_codes) { - std::vector default_paths = default_trace_code_paths(); - paths.insert(paths.end(), default_paths.begin(), default_paths.end()); - } - - paths.insert(paths.end(), additional_paths.begin(), additional_paths.end()); - - for (auto& path : paths) { - std::unordered_map partial = trace_codes_at_path(path.c_str()); - - if (output_fd > -1) { - dprintf(output_fd, "Read %zd codes from %s\n", partial.size(), path.c_str()); - } - - if (codes.empty()) { - codes = std::move(partial); - } else { - for (auto& map_pair : partial) { - auto insert_it = codes.insert(map_pair); - if (insert_it.second == false) { - if (map_pair.second != codes[map_pair.first]) { - dprintf(output_fd, "WARNING: code entry for 0x%x has multiple entries (%s, %s)\n", map_pair.first, map_pair.second.c_str(), codes[map_pair.first].c_str()); - } - } - } - } - } - - return codes; -} diff --git a/KDBG/TraceCodes.hpp b/KDBG/TraceCodes.hpp deleted file mode 100644 index 90058c9..0000000 --- a/KDBG/TraceCodes.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// TraceCodes.h -// KDBG -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __kdprof__TraceCodes__ -#define __kdprof__TraceCodes__ - -std::vector default_trace_code_paths(); -std::unordered_map trace_codes_at_path(const char* path); - -// -// Set output_fd to an open fd to print verbose output/warnings. -// -std::unordered_map resolve_trace_codes(bool should_read_default_codes, int output_fd, std::vector& additional_paths); - -#endif /* defined(__kdprof__TraceCodes__) */ diff --git a/KDBG/TraceDataHeader.hpp b/KDBG/TraceDataHeader.hpp deleted file mode 100644 index ab733dd..0000000 --- a/KDBG/TraceDataHeader.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// TraceDataHeader.hpp -// KDBG -// -// Created by James McIlree on 10/25/12. -// Copyright (c) 2014 Apple. All rights reserved. -// - -// -// We have to specialize this, as the K64 min alignment is 4 bytes longer, -// to maintain 8 byte alignment for the uint64_t _TOD_secs. -// - -template class TraceDataHeaderFields {}; - -template <> -class TraceDataHeaderFields { - public: - uint32_t version; - uint32_t thread_count; - uint32_t TOD_secs_top_half; - uint32_t TOD_secs_bottom_half; - uint32_t TOD_usecs; - - // NOTE! The compiler has shown a tendency to place this on non 8 byte - // aligned addresses when stack allocating. We need to construct the - // uint64_t values by logical-or and shifting, treating as a pointer - // will fail! - - TraceDataHeaderFields(uint32_t v, uint32_t tc, uint64_t s, uint32_t us) : - version(v), - thread_count(tc), - TOD_usecs(us) - { - TOD_secs_top_half = (uint32_t)(s >> 32); - TOD_secs_bottom_half = (uint32_t)(s & 0xFFFFFFFF); - } - - uint64_t TOD_secs() { - return ((uint64_t)TOD_secs_top_half << 32) | (uint64_t)TOD_secs_bottom_half; - } -}; - -template <> -class TraceDataHeaderFields { - public: - uint32_t version; - uint32_t thread_count; - uint64_t _TOD_secs; - uint32_t TOD_usecs; - uint32_t _force_alignment; // Need to force 8 byte alignment in 32 bit code - - TraceDataHeaderFields(uint32_t v, uint32_t tc, uint64_t s, uint32_t us) : - version(v), - thread_count(tc), - _TOD_secs(s), - TOD_usecs(us), - _force_alignment(0) - { - } - - uint64_t TOD_secs() { - return _TOD_secs; - } -}; - -template -class TraceDataHeader { - private: - TraceDataHeaderFields _fields; - - public: - TraceDataHeader() : _fields(0, 0, 0, 0) {} - TraceDataHeader(uint32_t v, uint32_t tc, uint64_t s, uint32_t us) : _fields(v, tc, s, us) {} - - uint32_t version() const { return _fields.version; } - uint32_t thread_count() const { return _fields.thread_count; } - uint64_t TOD_secs() const { return _fields.TOD_secs(); } - uint32_t TOD_usecs() const { return _fields.TOD_usecs; } -}; - diff --git a/KDBG/TraceFile.cpp b/KDBG/TraceFile.cpp deleted file mode 100644 index bddf161..0000000 --- a/KDBG/TraceFile.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// TraceFile.cpp -// system_cmds -// -// Created by James McIlree on 4/1/14. -// -// - -#include "KDebug.h" - -TraceFile::TraceFile(const char* path, bool sort_events, uint32_t default_ap_count, uint32_t default_iop_count) : - _file(path), - _version(kTraceFileVersion::Unknown), - _is_64_bit(false), - _is_valid(false), - _threadmap(nullptr), - _threadmap_count(0), - _cpumap(nullptr), - _cpumap_count(0), - _events(nullptr), - _event_count(0) -{ - try { - parse(sort_events, default_ap_count, default_iop_count); - } catch (...) { - parse(sort_events, default_ap_count, default_iop_count); - } -} diff --git a/KDBG/TraceFile.hpp b/KDBG/TraceFile.hpp deleted file mode 100644 index 174493d..0000000 --- a/KDBG/TraceFile.hpp +++ /dev/null @@ -1,257 +0,0 @@ -// -// TraceFile.hpp -// system_cmds -// -// Created by James McIlree on 4/1/14. -// -// - -#ifndef __system_cmds__TraceFile__ -#define __system_cmds__TraceFile__ - -// These are not (yet) defined in debug.h -// Remove and use kdebug.h ASAP. -#define RAW_VERSION2 0x55aa0200 // RAW_VERSION2 is from Instruments/kperf -#define RAW_VERSION3 0x55aa0300 // RAW_VERSION3 is the new hotness from kperf - -enum class kTraceFileVersion : uint32_t { - V0 = 0, - V1 = 1, - V1Plus = 2, // A 1+ is a 1 with a cpumap - V2 = 3, // Can type 2 contain a cpumap? Looks like no. - V3 = 4, - Unknown = UINT32_MAX -}; - -class TraceFile { - protected: - MappedFile _file; - kTraceFileVersion _version; - bool _is_64_bit; - bool _is_valid; - void* _threadmap; - uint32_t _threadmap_count; - KDCPUMapEntry* _cpumap; - uint32_t _cpumap_count; - void* _events; - uintptr_t _event_count; - std::vector _time_sorted_events; // This is empty unless event sorting is requested. - std::vector _default_cpumap; // If the file does not contain a cpumap, this will be used instead - - template - void sanity_check_event_data(); - - template - void parse(bool, uint32_t, uint32_t); - - public: - TraceFile(const char* path, bool sort_events = false, uint32_t default_ap_count = 24, uint32_t default_iop_count = 0); - - // Returns true if a Machine state can be created. - bool is_valid() const { return _is_valid; } - bool is_64_bit() const { return _is_64_bit; } - kTraceFileVersion version() const { return _version; } - - // Exposed so iOS devices can report over sized trace - bool mmap_failed() const { return _file.mmap_failed(); } - - const KDCPUMapEntry* cpumap() const { return _cpumap; } - uint32_t cpumap_count() const { return _cpumap_count; } - - template - const KDThreadMapEntry* threadmap() const { return reinterpret_cast*>(_threadmap); } - uint32_t threadmap_count() const { return _threadmap_count; } - - template - const KDEvent* events() const { return reinterpret_cast*>(_events); } - uintptr_t event_count() const { return _event_count; } -}; - -// -// This is a very simple attempt to sanity check the event data and prevent -// crashes when reading 32b vs 64b trace data. -// -template -void TraceFile::sanity_check_event_data() { - uintptr_t event_check_count = std::min((uintptr_t)10, _event_count); - - AbsTime last_timestamp; - - for (uintptr_t i=0; i& event = reinterpret_cast*>(_events)[i]; - - if (event.cpu() < 0) { - THROW("Event cpu id is less than 0"); - } - - if (event.cpu() >= _cpumap_count) { - THROW("Event cpu id is greater than the number of configured cpus"); - } - - if (event.timestamp() < last_timestamp) { - THROW("Event Data sanity check found out of order timestamps"); - } - - if (SIZE::is_64_bit) { - if (event.unused() != 0) { - THROW("Event has value set in unknown field"); - } - } - - last_timestamp = event.timestamp(); - } -} - -template -void TraceFile::parse(bool should_presort_events, uint32_t default_ap_count, uint32_t default_iop_count) { - if (TraceDataHeader* header = reinterpret_cast*>(_file.address())) { - KDThreadMapEntry* threadmap = NULL; - uint32_t threadmap_count = 0; - KDCPUMapEntry* cpumap = NULL; - uint32_t cpumap_count = 0; - KDEvent* events = NULL; - kTraceFileVersion version; - - switch (header->version()) { - case RAW_VERSION0: - // Should never happen! - ASSERT(false, "File is RAW_VERSION0"); - THROW("RAW_VERSION0 is ILLEGAL"); - break; - - case RAW_VERSION1: - // Could be either v1 or v1+ - break; - - case RAW_VERSION2: - _version = kTraceFileVersion::V2; - // We do not know how to parse a V2 file - THROW("RAW_VERSION2 is unhandled"); - break; - - case RAW_VERSION3: - _version = kTraceFileVersion::V3; - // We do not know how to parse a V3 file - THROW("RAW_VERSION3 is unhandled"); - break; - - default: - // Could be a v0 - break; - } - - if (header->version() != RAW_VERSION1) { - // If the header is not a RAW_VERSION1, we must assume it is a - // RAW_VERSION0. The difficulty here is that RAW_VERSION0 consists - // of 4 bytes, which are the thread_count. We can't do much - // sanity checking. The first four bytes are already read into - // the existing header, reuse them. We must also reset the file - // offset. - - threadmap_count = header->version(); - threadmap = reinterpret_cast*>(_file.address() + 4); - - // Event data starts immediately following the threadmap - size_t offset = 4 + threadmap_count * sizeof(KDThreadMapEntry); - events = reinterpret_cast*>(_file.address() + offset); - - version = kTraceFileVersion::V0; - } else { - // - // RAW_VERSION1 - // - threadmap_count = header->thread_count(); - threadmap = reinterpret_cast*>(_file.address() + sizeof(TraceDataHeader)); - - size_t threadmap_size_in_bytes = threadmap_count * sizeof(KDThreadMapEntry); - size_t offset_to_event_data = (sizeof(TraceDataHeader) + threadmap_size_in_bytes + 4095) & ~4095; - size_t offset_to_cpumap_data = sizeof(TraceDataHeader) + threadmap_size_in_bytes; - size_t cpumap_bytes = offset_to_event_data - offset_to_cpumap_data; - - // - // In a RAW_VERSION1, there *may* be a cpumap. - // If it exists, it will be between the header and the page aligned offset - // that event data begins at. - // - if (cpumap_bytes > sizeof(kd_cpumap_header) + sizeof(kd_cpumap)) { - kd_cpumap_header* cpumap_header = reinterpret_cast(_file.address() + offset_to_cpumap_data); - if (cpumap_header->version_no == RAW_VERSION1) { - cpumap = (KDCPUMapEntry*)&cpumap_header[1]; - cpumap_count = cpumap_header->cpu_count; - } - } - - // Event data starts at the next PAGE alignment boundary. - // - // Hmm, this could be pretty awful in iOS... - // - // Kernel page size is 4k. Userspace page size is 16kb in 64b. - // Kernel writes the data. Unless the kernel call fails, then userspace writes the data. Blech. - events = reinterpret_cast*>(_file.address() + offset_to_event_data); - } - - uintptr_t event_count = (uintptr_t)_file.size() - (reinterpret_cast(events) - reinterpret_cast(_file.address())); - if (event_count % sizeof(KDEvent) != 0) { - // We're probably looking at the wrong k32/k64. Throw and try the other size. - THROW("Bytes in file does not match an even multiple of Event struct"); - } - event_count /= sizeof(KDEvent); - - if (cpumap == NULL || cpumap_count == 0) { - // No cpumap found, we need to fake one up using the default values. - // - // It would be nice if we could just read the events and derive the - // AP/IOP count, but the IOP events do not have valid tid(s), and - // must be ignored. - - for (uint32_t i=0; i> presorted_events; - if (should_presort_events && event_count) { - _time_sorted_events.reserve(event_count * sizeof(KDEvent)); - memcpy(_time_sorted_events.data(), events, event_count * sizeof(KDEvent)); - events = reinterpret_cast*>(_time_sorted_events.data()); - std::sort(events, events + event_count, [](KDEvent const& p0, KDEvent const& p1) -> bool { - return p0.timestamp() < p1.timestamp(); - }); - } - - _threadmap = threadmap; - _threadmap_count = threadmap_count; - - _cpumap = cpumap; - _cpumap_count = cpumap_count; - - _events = events; - _event_count = event_count; - - _version = version; - _is_64_bit = SIZE::is_64_bit; - - sanity_check_event_data(); - - // - // Okay, success if we made it this far. - // - _is_valid = true; - } -} - -#endif /* defined(__system_cmds__TraceFile__) */ diff --git a/KDBG/VoucherInterval.hpp b/KDBG/VoucherInterval.hpp deleted file mode 100644 index 7544b32..0000000 --- a/KDBG/VoucherInterval.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// VoucherInterval.hpp -// KDBG -// -// Created by James McIlree on 2/18/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef kernel_perf_cmds_Header_h -#define kernel_perf_cmds_Header_h - -template -class VoucherInterval : public AbsInterval { - MachineVoucher* _voucher; - - public: - VoucherInterval(MachineVoucher* voucher, AbsInterval interval) : - AbsInterval(interval), - _voucher(voucher) - { - } - - const MachineVoucher* voucher() const { return _voucher; } -}; - -#endif diff --git a/ac.tproj/ac.c b/ac.tproj/ac.c index 6096f99..00aaa06 100644 --- a/ac.tproj/ac.c +++ b/ac.tproj/ac.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,21 +18,21 @@ * 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@ */ /* * Copyright (c) 1994 Christopher G. Demetriou. * @(#)Copyright (c) 1994, Simon J. Gerraty. - * + * * This is free software. It comes with NO WARRANTY. - * Permission to use, modify and distribute this source code + * Permission to use, modify and distribute this source code * is granted subject to the following conditions. - * 1/ that the above copyright notice and this notice - * are preserved in all copies and that due credit be given - * to the author. - * 2/ that any changes to this code are clearly commented - * as such so that the author does not get blamed for bugs + * 1/ that the above copyright notice and this notice + * are preserved in all copies and that due credit be given + * to the author. + * 2/ that any changes to this code are clearly commented + * as such so that the author does not get blamed for bugs * other than his own. */ @@ -86,7 +86,7 @@ struct tty_list { * globals - yes yuk */ #ifdef CONSOLE_TTY -static char *Console = CONSOLE_TTY; +static char *Console = CONSOLE_TTY; #endif static time_t Total = 0; static time_t FirstTime = 0; @@ -121,14 +121,13 @@ struct user_list *update_user __P((struct user_list *, char *, time_t)); void usage __P((void)); struct tty_list * -add_tty(name) - char *name; +add_tty(char *name) { struct tty_list *tp; register char *rcp; Flags |= AC_T; - + if ((tp = NEW(struct tty_list)) == NULL) err(1, "malloc"); tp->len = 0; /* full match */ @@ -152,12 +151,11 @@ add_tty(name) * should we process the named tty? */ int -do_tty(name) - char *name; +do_tty(char *name) { struct tty_list *tp; int def_ret = 0; - + for (tp = Ttys; tp != NULL; tp = tp->next) { if (tp->ret == 0) /* specific don't */ def_ret = 1; /* default do */ @@ -177,8 +175,7 @@ do_tty(name) * is someone logged in on Console? */ int -on_console(head) - struct utmp_list *head; +on_console(struct utmp_list *head) { struct utmp_list *up; @@ -195,10 +192,7 @@ on_console(head) * update user's login time */ struct user_list * -update_user(head, name, secs) - struct user_list *head; - char *name; - time_t secs; +update_user(struct user_list *head, char *name, time_t secs) { struct user_list *up; @@ -214,7 +208,7 @@ update_user(head, name, secs) */ if (Flags & AC_U) return head; - + if ((up = NEW(struct user_list)) == NULL) err(1, "malloc"); up->next = head; @@ -226,9 +220,7 @@ update_user(head, name, secs) } int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { FILE *fp; int c; @@ -278,7 +270,7 @@ main(argc, argv) if (Flags & AC_D) Flags &= ~AC_P; ac(); - + return 0; } @@ -286,17 +278,14 @@ main(argc, argv) * print login time in decimal hours */ void -show(name, secs) - char *name; - time_t secs; +show(char *name, time_t secs) { (void)printf("\t%-*s %8.2f\n", UT_NAMESIZE, name, ((double)secs / 3600)); } void -show_users(list) - struct user_list *list; +show_users(struct user_list *list) { struct user_list *lp; @@ -308,10 +297,7 @@ show_users(list) * print total login time for 24hr period in decimal hours */ void -show_today(users, logins, secs) - struct user_list *users; - struct utmp_list *logins; - time_t secs; +show_today(struct user_list *users, struct utmp_list *logins, time_t secs) { struct user_list *up; struct utmp_list *lp; @@ -323,7 +309,7 @@ show_today(users, logins, secs) /* restore the missing second */ yesterday++; - + for (lp = logins; lp != NULL; lp = lp->next) { secs = yesterday - lp->usr.ut_tv.tv_sec; Users = update_user(Users, lp->usr.ut_user, secs); @@ -334,7 +320,7 @@ show_today(users, logins, secs) secs += up->secs; up->secs = 0; /* for next day */ } - if (secs) + if (secs) (void)printf("%s %11.2f\n", date, ((double)secs / 3600)); } @@ -344,13 +330,11 @@ show_today(users, logins, secs) * been shut down. */ struct utmp_list * -log_out(head, up) - struct utmp_list *head; - struct utmpx *up; +log_out(struct utmp_list *head, struct utmpx *up) { struct utmp_list *lp, *lp2, *tlp; time_t secs; - + for (lp = head, lp2 = NULL; lp != NULL; ) if (up->ut_type == BOOT_TIME || up->ut_type == SHUTDOWN_TIME || strncmp(lp->usr.ut_line, up->ut_line, sizeof (up->ut_line)) == 0) { @@ -386,9 +370,7 @@ log_out(head, up) * if do_tty says ok, login a user */ struct utmp_list * -log_in(head, up) - struct utmp_list *head; - struct utmpx *up; +log_in(struct utmp_list *head, struct utmpx *up) { struct utmp_list *lp; @@ -407,13 +389,13 @@ log_in(head, up) if (up->ut_host[0] == ':') { /* * SunOS 4.0.2 does not treat ":0.0" as special but we - * do. + * do. */ if (on_console(head)) return head; /* * ok, no recorded login, so they were here when wtmp - * started! Adjust ut_tv.tv_sec! + * started! Adjust ut_tv.tv_sec! */ up->ut_tv.tv_sec = FirstTime; /* @@ -453,14 +435,14 @@ log_in(head, up) } int -ac() +ac(void) { struct utmp_list *lp, *head = NULL; struct utmpx *u, end; struct tm *ltm; time_t secs = 0; int day = -1; - + setutxent_wtmp(1); /* read in forward direction */ while ((u = getutxent_wtmp()) != NULL) { if (!FirstTime) @@ -516,7 +498,7 @@ ac() bzero(&end, sizeof(end)); end.ut_tv.tv_sec = time((time_t *)0); end.ut_type = SHUTDOWN_TIME; - + if (Flags & AC_D) { ltm = localtime(&end.ut_tv.tv_sec); if (day >= 0 && day != ltm->tm_yday) { @@ -546,7 +528,7 @@ ac() } void -usage() +usage(void) { (void)fprintf(stderr, #ifdef CONSOLE_TTY diff --git a/accton.tproj/accton.c b/accton.tproj/accton.c index 1fb83ff..dcb7e83 100644 --- a/accton.tproj/accton.c +++ b/accton.tproj/accton.c @@ -80,7 +80,7 @@ main(int argc, char *argv[]) } static void -usage() +usage(void) { (void)fprintf(stderr, "usage: accton [file]\n"); exit(1); diff --git a/arch.tproj/arch.c b/arch.tproj/arch.c index e417309..426fea0 100644 --- a/arch.tproj/arch.c +++ b/arch.tproj/arch.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999, 2006, 2011 Apple Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ @@ -41,6 +41,7 @@ #include #include #include +#include #ifndef ARCH_PROG #define ARCH_PROG "arch" @@ -116,7 +117,7 @@ static void __dead2 arch(int archcmd) { const NXArchInfo *arch = NXGetLocalArchInfo(); - + if(!arch) errx(-1, "Unknown architecture."); if(archcmd) { @@ -143,7 +144,7 @@ spawnIt(CPU *cpu, int pflag, const char *str, char **argv) size_t copied; size_t count = cpu->count; cpu_type_t *prefs = cpu->buf; - + if(count == 0) { if(unrecognizednative32seen) warnx("Unsupported native 32-bit architecture"); @@ -151,12 +152,12 @@ spawnIt(CPU *cpu, int pflag, const char *str, char **argv) warnx("Unsupported native 64-bit architecture"); exit(1); } - + if(unrecognizednative32seen) fprintf(stderr, "warning: unsupported native 32-bit architecture\n"); if(unrecognizednative64seen) fprintf(stderr, "warning: unsupported native 64-bit architecture\n"); - + if((ret = posix_spawnattr_init(&attr)) != 0) errc(1, ret, "posix_spawnattr_init"); /* do the equivalent of exec, rather than creating a separate process */ @@ -322,17 +323,17 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) char fpath[PATH_MAX]; char execpath2[PATH_MAX]; CFDictionaryRef plist = NULL; - NSSearchPathEnumerationState state; + sysdir_search_path_enumeration_state state; size_t count, i; const char *prog = strrchr(*argv, '/'); - + if(prog) prog++; else prog = *argv; if(!*prog) errx(1, "Not program name specified"); - + /* check the environment variable first */ if((count = useEnv(cpu, prog, &epath)) > 0) { /* if we were called as arch, use posix_spawnp */ @@ -342,19 +343,16 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) if(epath) spawnIt(cpu, 0, epath, argv); } - - state = NSStartSearchPathEnumeration(NSLibraryDirectory, NSAllDomainsMask); - while ((state = NSGetNextSearchPathEnumeration(state, fpath))) { - - CFURLRef url; - CFReadStreamRef stream; - + + state = sysdir_start_search_path_enumeration(SYSDIR_DIRECTORY_LIBRARY, SYSDIR_DOMAIN_MASK_ALL); + while ((state = sysdir_get_next_search_path_enumeration(state, fpath))) { + if (fpath[0] == '~') { glob_t pglob; int gret; - + bzero(&pglob, sizeof(pglob)); - + gret = glob(fpath, GLOB_TILDE, NULL, &pglob); if (gret == 0) { int i; @@ -366,13 +364,13 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) } globfree(&pglob); } - + // Handle path strlcat(fpath, "/" kSettingsDir "/", sizeof(fpath)); strlcat(fpath, prog, sizeof(fpath)); strlcat(fpath, kPlistExtension, sizeof(fpath)); // printf("component: %s\n", fpath); - + int fd, ret; size_t length; ssize_t rsize; @@ -403,20 +401,19 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) } close(fd); } - + if (plist) { break; } } - + if (plist) { if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) errx(1, "%s: plist not a dictionary", fpath); } else { errx(1, "Can't find any plists for %s", prog); } - - + int errs = 0; /* scan for all errors and fail later */ do { /* begin block */ /* check the plist version */ @@ -476,9 +473,9 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) } while(0); /* end block */ if(errs) /* exit if there were any reported errors */ exit(1); - + CFRelease(plist); - + /* call posix_spawn */ spawnIt(cpu, 0, execpath2, argv); } @@ -513,9 +510,9 @@ wrapped(const char *name) char *cur, *path; char buf[MAXPATHLEN], rpbuf[MAXPATHLEN]; struct stat sb; - + ln = strlen(name); - + do { /* begin block */ /* If it's an absolute or relative path name, it's easy. */ if(index(name, '/')) { @@ -525,11 +522,11 @@ wrapped(const char *name) } errx(1, "%s isn't executable", name); } - + /* search the PATH, looking for name */ if((path = getenv("PATH")) == NULL) path = _PATH_DEFPATH; - + cur = alloca(strlen(path) + 1); if(cur == NULL) err(1, "alloca"); @@ -544,7 +541,7 @@ wrapped(const char *name) lp = 1; } else lp = strlen(p); - + /* * If the path is too long complain. This is a possible * security issue; given a way to make the path too long @@ -613,7 +610,7 @@ static void __dead2 spawnFromArgs(CPU *cpu, char **argv) { const char *ap, *ret; - + /* process arguments */ for(argv++; *argv && **argv == '-'; argv++) { if((ret = MATCHARGWITHVALUE(argv, "-arch", 5, "-arch without architecture"))) { @@ -670,14 +667,14 @@ spawnFromArgs(CPU *cpu, char **argv) } /* if the program is already a link to arch, then force execpath */ int needexecpath = wrapped(*argv); - + /* * If we don't have any architecutures, try ARCHPREFERENCE and plist * files. */ if((cpu->count == 0) || needexecpath) spawnFromPreferences(cpu, needexecpath, argv); /* doesn't return */ - + /* * Call posix_spawnp on the program name. */ @@ -692,7 +689,7 @@ main(int argc, char **argv) const char *prog = getprogname(); int my_name_is_arch; CPU cpu; - + if(strcmp(prog, MACHINE_PROG) == 0) { if(argc > 1) errx(-1, "no arguments accepted"); @@ -701,14 +698,14 @@ main(int argc, char **argv) if(argc == 1) arch(1); /* the "arch" command with no arguments was called */ } - + initCPU(&cpu); - + if(my_name_is_arch) spawnFromArgs(&cpu, argv); else spawnFromPreferences(&cpu, 1, argv); - + /* should never get here */ errx(1, "returned from spawn"); } diff --git a/at.tproj/at.c b/at.tproj/at.c index 6dd2db3..9b9b67c 100644 --- a/at.tproj/at.c +++ b/at.tproj/at.c @@ -1,4 +1,4 @@ -/* +/* * at.c : Put file into atrun queue * Copyright (C) 1993, 1994 Thomas Koenig * @@ -77,7 +77,7 @@ __FBSDID("$FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/usr.bin/at/at.c,v 1.34 20 /* Macros */ -#ifndef ATJOB_DIR +#ifndef ATJOB_DIR #define ATJOB_DIR _PATH_ATJOBS #endif @@ -129,9 +129,10 @@ static long *get_job_list(int, char *[], int *); /* Signal catching functions */ -static void sigc(int signo __unused) +static void +sigc(int signo __unused) { -/* If the user presses ^C, remove the spool file and exit +/* If the user presses ^C, remove the spool file and exit */ if (fcreated) { @@ -143,7 +144,8 @@ static void sigc(int signo __unused) _exit(EXIT_FAILURE); } -static void alarmc(int signo __unused) +static void +alarmc(int signo __unused) { char buf[1024]; @@ -156,7 +158,8 @@ static void alarmc(int signo __unused) /* Local functions */ -static char *cwdname(void) +static char * +cwdname(void) { /* Read in the current directory; the name will be overwritten on * subsequent calls. @@ -175,10 +178,10 @@ static char *cwdname(void) if (getcwd(ptr, size-1) != NULL) return ptr; - + if (errno != ERANGE) perr("cannot get directory"); - + free (ptr); size += SIZE; if ((ptr = malloc(size)) == NULL) @@ -228,7 +231,7 @@ writefile(time_t runtimer, char queue) mode_t cmask; struct flock lock; char * oldpwd_str = NULL; - + #ifdef __FreeBSD__ (void) setlocale(LC_TIME, ""); #endif @@ -273,7 +276,7 @@ writefile(time_t runtimer, char queue) if ((jobno = nextjob()) == EOF) perr("cannot generate job number"); - sprintf(ppos, "%c%5lx%8lx", queue, + sprintf(ppos, "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer/60)); for(ap=ppos; *ap != '\0'; ap ++) @@ -291,7 +294,7 @@ writefile(time_t runtimer, char queue) */ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); if ((fdes = creat(atfile, O_WRONLY)) == -1) - perr("cannot create atjob file"); + perr("cannot create atjob file"); if ((fd2 = dup(fdes)) <0) perr("error in dup() of job file"); @@ -307,7 +310,7 @@ writefile(time_t runtimer, char queue) REDUCE_PRIV(DAEMON_UID, DAEMON_GID) - /* We've successfully created the file; let's set the flag so it + /* We've successfully created the file; let's set the flag so it * gets removed in case of an interrupt or error. */ fcreated = 1; @@ -329,7 +332,7 @@ writefile(time_t runtimer, char queue) if (mailname == NULL) mailname = getenv("LOGNAME"); - if ((mailname == NULL) || (mailname[0] == '\0') + if ((mailname == NULL) || (mailname[0] == '\0') || (strlen(mailname) >= MAXLOGNAME) || (getpwnam(mailname)==NULL)) { pass_entry = getpwuid(real_uid); @@ -377,7 +380,7 @@ writefile(time_t runtimer, char queue) for (i=0; ipw_name : "???", - queue, - (S_IXUSR & buf.st_mode) ? "":"(done)", + printf("%s\t%s\t%c%s\t%s\n", + timestr, + pw ? pw->pw_name : "???", + queue, + (S_IXUSR & buf.st_mode) ? "":"(done)", name); } } @@ -543,13 +546,13 @@ list_one_job(char *name, long *joblist, int len, int *first) static void list_jobs(long *joblist, int len) { - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, + /* List all a user's jobs in the queue, by looping through ATJOB_DIR, * or everybody's if we are root */ DIR *spool; struct dirent *dirent; int first=1; - + #ifdef __FreeBSD__ (void) setlocale(LC_TIME, ""); #endif @@ -579,7 +582,7 @@ list_jobs(long *joblist, int len) if ((spool = opendir(".")) == NULL) perr("cannot open " ATJOB_DIR); - /* Loop over every file in the directory + /* Loop over every file in the directory */ while((dirent = readdir(spool)) != NULL) { list_one_job(dirent->d_name, joblist, len, &first); @@ -612,7 +615,7 @@ process_jobs(int argc, char **argv, int what) PRIV_END - /* Loop over every file in the directory + /* Loop over every file in the directory */ while((dirent = readdir(spool)) != NULL) { @@ -686,10 +689,10 @@ ttime(const char *arg) struct tm *t; int yearset; char *p; - + if (gettimeofday(&tv[0], NULL)) panic("Cannot get current time"); - + /* Start with the current time. */ now = tv[0].tv_sec; if ((t = localtime(&now)) == NULL) @@ -703,7 +706,7 @@ ttime(const char *arg) *p++ = '\0'; t->tm_sec = ATOI2(p); } - + yearset = 0; switch(strlen(arg)) { case 12: /* CCYYMMDDhhmm */ @@ -731,7 +734,7 @@ ttime(const char *arg) default: goto terr; } - + t->tm_isdst = -1; /* Figure out DST. */ tv[0].tv_sec = tv[1].tv_sec = mktime(t); if (tv[0].tv_sec != -1) @@ -787,7 +790,7 @@ main(int argc, char **argv) timer = -1; RELINQUISH_PRIVS - if (argv[0] == NULL) + if (argv[0] == NULL) usage(); /* Eat any leading paths */ @@ -829,7 +832,7 @@ main(int argc, char **argv) case 'f': atinput = optarg; break; - + case 'q': /* specify queue */ if (strlen(optarg) > 1) usage(); @@ -916,9 +919,9 @@ main(int argc, char **argv) case AT: /* * If timer is > -1, then the user gave the time with -t. In that - * case, it's already been set. If not, set it now. + * case, it's already been set. If not, set it now. */ - if (timer == -1) + if (timer == -1) timer = parsetime(argc, argv); if (atverify) @@ -939,7 +942,7 @@ main(int argc, char **argv) timer = parsetime(argc, argv); else timer = time(NULL); - + if (atverify) { struct tm *tm = localtime(&timer); diff --git a/at.tproj/at.h b/at.tproj/at.h index ff8008d..a3dc18a 100644 --- a/at.tproj/at.h +++ b/at.tproj/at.h @@ -1,4 +1,4 @@ -/* +/* * at.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * diff --git a/at.tproj/panic.c b/at.tproj/panic.c index 76831a8..b1d99d8 100644 --- a/at.tproj/panic.c +++ b/at.tproj/panic.c @@ -1,4 +1,4 @@ -/* +/* * panic.c - terminate fast in case of error * Copyright (C) 1993 Thomas Koenig * diff --git a/at.tproj/panic.h b/at.tproj/panic.h index d656d61..d50405e 100644 --- a/at.tproj/panic.h +++ b/at.tproj/panic.h @@ -1,4 +1,4 @@ -/* +/* * panic.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * diff --git a/at.tproj/parsetime.c b/at.tproj/parsetime.c index efd626d..3aeea6c 100644 --- a/at.tproj/parsetime.c +++ b/at.tproj/parsetime.c @@ -1,4 +1,4 @@ -/* +/* * parsetime.c - parse time for at(1) * Copyright (C) 1993, 1994 Thomas Koenig * @@ -272,7 +272,7 @@ plonk(int tok) } /* plonk */ -/* +/* * expect() gets a token and dies most horribly if it's not the token we want */ static void @@ -320,7 +320,7 @@ plus(struct tm *tm) tm->tm_min += delay; break; default: - plonk(sc_tokid); + plonk(sc_tokid); break; } @@ -343,32 +343,32 @@ next(struct tm *tm) case YEARS: tm->tm_year++; break; - + case MONTHS: tm->tm_mon++; break; - + case WEEKS: tm->tm_mday += 7; break; - + case DAYS: tm->tm_mday++; break; - + case HOURS: tm->tm_hour++; break; - + case MINUTES: tm->tm_min++; break; - + default: - plonk(sc_tokid); + plonk(sc_tokid); break; } - + if (sc_tokplur) { warnx("pluralization is wrong"); } @@ -387,10 +387,10 @@ tod(struct tm *tm) { int hour, minute = 0; size_t tlen; - + hour = atoi(sc_token); tlen = strlen(sc_token); - + /* first pick out the time of day - if it's 4 digits, we assume * a HHMM time, otherwise it's HH DOT MM time */ @@ -407,7 +407,7 @@ tod(struct tm *tm) panic("garbled time"); hour = hour/100; } - + /* check if an AM or PM specifier was given */ switch (sc_tokid) { @@ -415,7 +415,7 @@ tod(struct tm *tm) case PM: if (hour > 12) panic("garbled time"); - + if (sc_tokid == PM) { if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */ hour += 12; @@ -425,7 +425,7 @@ tod(struct tm *tm) } if (UTC != token()) break; /* else fallthrough */ - + case UTC: hour += tm->tm_gmtoff/(60*60); while (hour < 0) @@ -441,18 +441,18 @@ tod(struct tm *tm) panic("garbled time"); break; } - + /* if we specify an absolute time, we don't want to bump the day even * if we've gone past that time - but if we're specifying a time plus * a relative offset, it's okay to bump things * If minutes are the same assume tomorrow was meant */ - if ((sc_tokid == EOF || sc_tokid == PLUS) && + if ((sc_tokid == EOF || sc_tokid == PLUS) && ((tm->tm_hour > hour) || ((tm->tm_hour == hour) && (tm->tm_min >= minute)))) { tm->tm_mday++; tm->tm_wday++; } - + tm->tm_hour = hour; tm->tm_min = minute; if (tm->tm_hour == 24) { @@ -504,7 +504,7 @@ assign_date(struct tm *tm, int mday, int mon, int year) } /* assign_date */ -/* +/* * month() picks apart a month specification * * /[ NUMBER [NUMBER]] \ @@ -648,19 +648,19 @@ parsetime(int argc, char **argv) struct tm nowtime, runtime; int hr = 0; /* this MUST be initialized to zero for midnight/noon/teatime */ - + nowtimer = time(NULL); nowtime = *localtime(&nowtimer); - + runtime = nowtime; runtime.tm_sec = 0; runtime.tm_isdst = 0; - + if (argc <= optind) usage(); - + init_scanner(argc-optind, argv+optind); - + switch (token()) { case NOW: if (scc < 1) { @@ -671,30 +671,30 @@ parsetime(int argc, char **argv) case PLUS: plus(&runtime); break; - + case NEXT: next(&runtime); break; - + default: plonk(sc_token); break; } break; - + case PLUS: plus(&runtime); break; - + case NEXT: next(&runtime); break; - + case NUMBER: tod(&runtime); month(&runtime); break; - + /* evil coding for TEATIME|NOON|MIDNIGHT - we've initialised * hr to zero up above, then fall into this case in such a * way so we add +12 +4 hours to it for teatime, +12 hours @@ -720,17 +720,17 @@ parsetime(int argc, char **argv) break; } /* ugly case statement */ expect(EOF); - + /* convert back to time_t */ runtime.tm_isdst = -1; runtimer = mktime(&runtime); - + if (runtimer < 0) panic("garbled time"); - + if (nowtimer > runtimer) panic("trying to travel back in time"); - + return runtimer; } /* parsetime */ diff --git a/at.tproj/parsetime.h b/at.tproj/parsetime.h index 30c3f20..cf426bb 100644 --- a/at.tproj/parsetime.h +++ b/at.tproj/parsetime.h @@ -1,4 +1,4 @@ -/* +/* * at.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * diff --git a/at.tproj/pathnames.h b/at.tproj/pathnames.h index b05b7a5..c409b6e 100644 --- a/at.tproj/pathnames.h +++ b/at.tproj/pathnames.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ @@ -61,7 +61,7 @@ #define _PATH_ATJOBS "/usr/lib/cron/jobs/" #define _PATH_ATSPOOL "/usr/lib/cron/spool/" -/* Note: _PATH_LOCKFILE appears to be unused; /usr/lib/cron/jobs/.lockfile +/* Note: _PATH_LOCKFILE appears to be unused; /usr/lib/cron/jobs/.lockfile is the file currently being used by at.*/ #define _PATH_LOCKFILE "/usr/lib/cron/.lockfile" #define _PATH_AT "/usr/lib/cron/" diff --git a/at.tproj/perm.c b/at.tproj/perm.c index dd9749b..82bab87 100644 --- a/at.tproj/perm.c +++ b/at.tproj/perm.c @@ -1,4 +1,4 @@ -/* +/* * perm.c - check user permission for at(1) * Copyright (C) 1994 Thomas Koenig * diff --git a/at.tproj/perm.h b/at.tproj/perm.h index 92d0e31..9781ef8 100644 --- a/at.tproj/perm.h +++ b/at.tproj/perm.h @@ -1,4 +1,4 @@ -/* +/* * perm.h - header for at(1) * Copyright (C) 1994 Thomas Koenig * diff --git a/at.tproj/privs.h b/at.tproj/privs.h index 359728c..4a43b6c 100644 --- a/at.tproj/privs.h +++ b/at.tproj/privs.h @@ -1,5 +1,5 @@ -/* - * privs.h - header for privileged operations +/* + * privs.h - header for privileged operations * Copyright (C) 1993 Thomas Koenig * * Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ extern #endif uid_t real_uid, effective_uid; -#ifndef MAIN +#ifndef MAIN extern #endif gid_t real_gid, effective_gid; diff --git a/atrun.tproj/atrun.c b/atrun.tproj/atrun.c index 4d35a04..0981614 100644 --- a/atrun.tproj/atrun.c +++ b/atrun.tproj/atrun.c @@ -1,4 +1,4 @@ -/* +/* * atrun.c - run jobs queued by at; run with root privileges. * Copyright (C) 1993, 1994 Thomas Koenig * @@ -154,7 +154,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) pid = fork(); if (pid == -1) perr("cannot fork"); - + else if (pid != 0) return; @@ -214,16 +214,16 @@ run_file(const char *filename, uid_t uid, gid_t gid) if (S_ISLNK(lbuf.st_mode)) perrx("Symbolic link encountered in job %s - aborting", filename); - + if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || (lbuf.st_size!=buf.st_size)) perrx("Somebody changed files from under us for job %s - aborting", filename); - + if (buf.st_nlink > 1) perrx("Somebody is trying to run a linked script for job %s", filename); - + if ((fflags = fcntl(fd_in, F_GETFD)) <0) perr("error in fcntl"); @@ -238,7 +238,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) if (mailbuf[0] == '-') perrx("Illegal mail name %s in %s", mailbuf, filename); - + mailname = mailbuf; if (nuid != uid) @@ -253,10 +253,10 @@ run_file(const char *filename, uid_t uid, gid_t gid) if (chdir(ATSPOOL_DIR) < 0) perr("cannot chdir to %s", ATSPOOL_DIR); - + /* Create a file to hold the output of the job we are about to run. * Write the mail header. - */ + */ if((fd_out=open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) perr("cannot create output file"); @@ -270,7 +270,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); - + pid = fork(); if (pid < 0) perr("error in fork"); @@ -306,7 +306,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) PRIV_START nice(tolower(queue) - 'a'); - + #ifdef LOGIN_CAP /* * For simplicity and safety, set all aspects of the user context @@ -356,7 +356,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) unlink(filename); if ((buf.st_size != size) || send_mail) - { + { PRIV_START #ifdef LOGIN_CAP @@ -476,7 +476,7 @@ main(int argc, char *argv[]) { switch (c) { - case 'l': + case 'l': if (sscanf(optarg, "%lf", &load_avg) != 1) perr("garbled option -l"); if (load_avg <= 0.) @@ -520,7 +520,7 @@ main(int argc, char *argv[]) /* We don't want directories */ - if (!S_ISREG(buf.st_mode)) + if (!S_ISREG(buf.st_mode)) continue; if (sscanf(dirent->d_name,"%c%5lx%8lx",&queue,&jobno,&ctm) != 3) @@ -535,7 +535,7 @@ main(int argc, char *argv[]) batch_uid = buf.st_uid; batch_gid = buf.st_gid; } - + /* The file is executable and old enough */ if (islower(queue)) @@ -565,7 +565,7 @@ usage(void) if (debug) fprintf(stderr, "usage: atrun [-l load_avg] [-d]\n"); else - syslog(LOG_ERR, "usage: atrun [-l load_avg] [-d]"); + syslog(LOG_ERR, "usage: atrun [-l load_avg] [-d]"); exit(EXIT_FAILURE); } diff --git a/atrun.tproj/gloadavg.c b/atrun.tproj/gloadavg.c index c4ecce6..267a8c8 100644 --- a/atrun.tproj/gloadavg.c +++ b/atrun.tproj/gloadavg.c @@ -1,4 +1,4 @@ -/* +/* * gloadavg.c - get load average for Linux * Copyright (C) 1993 Thomas Koenig * @@ -55,7 +55,7 @@ gloadavg(void) double result; #ifndef __FreeBSD__ FILE *fp; - + if((fp=fopen(PROC_DIR "loadavg","r")) == NULL) result = -1.0; else diff --git a/atrun.tproj/gloadavg.h b/atrun.tproj/gloadavg.h index 3ead6ca..b81a4fc 100644 --- a/atrun.tproj/gloadavg.h +++ b/atrun.tproj/gloadavg.h @@ -1,4 +1,4 @@ -/* +/* * gloadavg.h - header for atrun(8) * Copyright (C) 1993 Thomas Koenig * diff --git a/chkpasswd.tproj/file_passwd.c b/chkpasswd.tproj/file_passwd.c index 24d4913..90f54f2 100644 --- a/chkpasswd.tproj/file_passwd.c +++ b/chkpasswd.tproj/file_passwd.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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 @@ -36,18 +36,18 @@ #define _PASSWD_FIELDS 10 #define BUFSIZE 8192 -extern void checkpasswd(char *, char *); +#include "passwd.h" -char * +static char * _getline(FILE *fp) { static char s[BUFSIZE]; - int len; + size_t len; - s[0] = '\0'; + s[0] = '\0'; - fgets(s, BUFSIZE, fp); - if (s == NULL || s[0] == '\0') return NULL; + fgets(s, BUFSIZE, fp); + if (s[0] == '\0') return NULL; if (s[0] == '#') return s; @@ -57,7 +57,7 @@ _getline(FILE *fp) return s; } -struct passwd * +static struct passwd * parse_user(char *line) { static struct passwd pw = {0}; @@ -107,7 +107,7 @@ parse_user(char *line) return &pw; } -struct passwd * +static struct passwd * find_user(char *uname, FILE *fp) { char *line; @@ -127,14 +127,15 @@ find_user(char *uname, FILE *fp) return (struct passwd *)NULL; } -void +#if 0 +static void rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) { char *line; struct passwd *pw; FILE *tfp, *cfp; char fname[256]; - + sprintf(fname, "%s.%d", TEMP_FILE, getpid()); tfp = fopen(fname, "w+"); @@ -241,6 +242,7 @@ rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) fclose(tfp); unlink(fname); } +#endif /* 0 */ int file_check_passwd(char *uname, char *locn) diff --git a/chkpasswd.tproj/nis_passwd.c b/chkpasswd.tproj/nis_passwd.c index 89b0411..c2e6e4f 100644 --- a/chkpasswd.tproj/nis_passwd.c +++ b/chkpasswd.tproj/nis_passwd.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,10 +18,10 @@ * 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@ */ -/* +/* * Copyright (c) 1998 by Apple Computer, Inc. * Portions Copyright (c) 1988 by Sun Microsystems, Inc. * Portions Copyright (c) 1988 The Regents of the University of California. @@ -69,9 +69,9 @@ #include #include #include -#include -#include #include +#include +#include #include #include #include @@ -80,13 +80,13 @@ #include #include -extern int getrpcport(char *, int, int, int); -extern void checkpasswd(char *, char *); +#include "passwd.h" static struct passwd *ypgetpwnam(char *name, char *domain); -int nis_check_passwd(char *uname, char *domain) -{ +int +nis_check_passwd(char *uname, char *domain) +{ int port; char *master; struct passwd *pwd; @@ -99,13 +99,13 @@ int nis_check_passwd(char *uname, char *domain) exit(1); } } - + if (yp_master(domain, "passwd.byname", &master) != 0) { (void)fprintf(stderr, "can't get master for passwd file\n"); exit(1); } - + port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); if (port == 0) @@ -127,11 +127,11 @@ int nis_check_passwd(char *uname, char *domain) (void)fprintf(stderr, "user %s not found\n", uname); exit(1); } - + checkpasswd(uname, pwd->pw_passwd); return(0); } - + static char * pwskip(register char *p) { @@ -142,7 +142,7 @@ pwskip(register char *p) return (p); } -struct passwd * +static struct passwd * interpret(struct passwd *pwent, char *line) { register char *p = line; @@ -182,7 +182,6 @@ interpret(struct passwd *pwent, char *line) return (pwent); } - static struct passwd * ypgetpwnam(char *nam, char *domain) { @@ -191,7 +190,7 @@ ypgetpwnam(char *nam, char *domain) int reason, vallen; static char *__yplin = NULL; - reason = yp_match(domain, "passwd.byname", nam, strlen(nam), + reason = yp_match(domain, "passwd.byname", nam, (int)strlen(nam), &val, &vallen); switch(reason) { case 0: diff --git a/chkpasswd.tproj/od_passwd.c b/chkpasswd.tproj/od_passwd.c index ab3a68a..2ea724f 100644 --- a/chkpasswd.tproj/od_passwd.c +++ b/chkpasswd.tproj/od_passwd.c @@ -1,5 +1,5 @@ -/* - * Copyright (c) 1998-2008 Apple Inc. All rights reserved. +/* + * Copyright (c) 1998-2016 Apple Inc. All rights reserved. * Portions Copyright (c) 1988 by Sun Microsystems, Inc. * Portions Copyright (c) 1988 The Regents of the University of California. * All rights reserved. @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ - + #include #include #include @@ -52,14 +52,17 @@ #include +#include "passwd.h" + //------------------------------------------------------------------------------------- // od_check_passwd //------------------------------------------------------------------------------------- -int od_check_passwd(const char *uname, const char *domain) +int +od_check_passwd(const char *uname, const char *domain) { int authenticated = 0; - + ODSessionRef session = NULL; ODNodeRef node = NULL; ODRecordRef rec = NULL; @@ -92,7 +95,7 @@ int od_check_passwd(const char *uname, const char *domain) } } } - + if (!authenticated) { fprintf(stderr, "Sorry\n"); exit(1); @@ -100,9 +103,3 @@ int od_check_passwd(const char *uname, const char *domain) return 0; } - - - - - - diff --git a/chkpasswd.tproj/pam_passwd.c b/chkpasswd.tproj/pam_passwd.c index 65790fd..07d9919 100644 --- a/chkpasswd.tproj/pam_passwd.c +++ b/chkpasswd.tproj/pam_passwd.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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 @@ -25,6 +25,8 @@ #include #include /* for openpam_ttyconv() */ +#include "passwd.h" + extern char* progname; static pam_handle_t *pamh; static struct pam_conv pamc; @@ -33,7 +35,8 @@ static struct pam_conv pamc; // pam_check_passwd //------------------------------------------------------------------------------------- -int pam_check_passwd(char* uname) +int +pam_check_passwd(char* uname) { int retval = PAM_SUCCESS; @@ -61,8 +64,8 @@ int pam_check_passwd(char* uname) /* Open the session. */ if (PAM_SUCCESS != (retval = pam_open_session(pamh, 0))) - goto pamerr; - + goto pamerr; + /* Close the session. */ if (PAM_SUCCESS != (retval = pam_close_session(pamh, 0))) goto pamerr; diff --git a/chkpasswd.tproj/passwd.c b/chkpasswd.tproj/passwd.c index 408fe03..bff8280 100644 --- a/chkpasswd.tproj/passwd.c +++ b/chkpasswd.tproj/passwd.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ #define INFO_FILE 1 @@ -45,15 +45,12 @@ #define _PASSWORD_LEN 8 #endif +#include "passwd.h" + const char* progname = "chkpasswd"; static int literal = 0; -extern int file_check_passwd(char *, char *); -extern int nis_check_passwd(char *, char *); -extern int od_check_passwd(char *, char *); -extern int pam_check_passwd(char *); - void checkpasswd(char *name, char *old_pw) { @@ -80,8 +77,8 @@ checkpasswd(char *name, char *old_pw) return; } -void -usage() +static void +usage(void) { fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n"); fprintf(stderr, " infosystem:\n"); @@ -139,7 +136,7 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; - + if (argc > 1) { usage(); } else if (argc == 1) { @@ -156,7 +153,7 @@ main(int argc, char *argv[]) exit(1); } } - + switch (infosystem) { case INFO_FILE: @@ -175,4 +172,3 @@ main(int argc, char *argv[]) exit(0); } - diff --git a/chkpasswd.tproj/passwd.h b/chkpasswd.tproj/passwd.h new file mode 100644 index 0000000..692722b --- /dev/null +++ b/chkpasswd.tproj/passwd.h @@ -0,0 +1,5 @@ +int file_check_passwd(char *, char *); +int nis_check_passwd(char *, char *); +int od_check_passwd(const char *, const char *); +int pam_check_passwd(char *); +void checkpasswd(char *, char *); diff --git a/chkpasswd.tproj/stringops.c b/chkpasswd.tproj/stringops.c index a3621e3..960ce19 100644 --- a/chkpasswd.tproj/stringops.c +++ b/chkpasswd.tproj/stringops.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ #import @@ -27,9 +27,10 @@ #import #import "stringops.h" -char *copyString(char *s) +char * +copyString(char *s) { - int len; + size_t len; char *t; if (s == NULL) return NULL; @@ -40,9 +41,10 @@ char *copyString(char *s) return t; } -char *concatString(char *s, char *t) +char * +concatString(char *s, char *t) { - int len; + size_t len; if (t == NULL) return s; @@ -52,12 +54,13 @@ char *concatString(char *s, char *t) return s; } -char **insertString(char *s, char **l, unsigned int x) +char ** +insertString(char *s, char **l, unsigned int x) { int i, len; if (s == NULL) return l; - if (l == NULL) + if (l == NULL) { l = (char **)malloc(2 * sizeof(char *)); l[0] = copyString(s); @@ -82,12 +85,14 @@ char **insertString(char *s, char **l, unsigned int x) return l; } -char **appendString(char *s, char **l) +char ** +appendString(char *s, char **l) { return insertString(s, l, IndexNull); } -void freeList(char **l) +void +freeList(char **l) { int i; @@ -100,13 +105,15 @@ void freeList(char **l) if (l != NULL) free(l); } -void freeString(char *s) +void +freeString(char *s) { if (s == NULL) return; free(s); } -unsigned int listLength(char **l) +unsigned int +listLength(char **l) { int i; @@ -115,7 +122,8 @@ unsigned int listLength(char **l) return i; } -unsigned int listIndex(char *s,char **l) +unsigned int +listIndex(char *s,char **l) { int i; @@ -127,7 +135,8 @@ unsigned int listIndex(char *s,char **l) return IndexNull; } -char *prefix(char *s, char c) +char * +prefix(char *s, char c) { int i; char *t; @@ -144,9 +153,11 @@ char *prefix(char *s, char c) return t; } -char *postfix(char *s, char c) +char * +postfix(char *s, char c) { - int i, len; + int i; + size_t len; char *t; if (s == NULL) return NULL; @@ -162,10 +173,12 @@ char *postfix(char *s, char c) t[len] = '\0'; return t; } - -char *presuffix(char *s, char c) + +char * +presuffix(char *s, char c) { - int i, len; + ssize_t i; + size_t len; char *t; if (s == NULL) return NULL; @@ -181,9 +194,11 @@ char *presuffix(char *s, char c) return t; } -char *suffix(char *s, char c) +char * +suffix(char *s, char c) { - int i, len; + ssize_t i; + size_t len; char *t; if (s == NULL) return NULL; @@ -200,7 +215,8 @@ char *suffix(char *s, char c) return t; } -char *lowerCase(char *s) +char * +lowerCase(char *s) { int i; char *t; @@ -208,7 +224,7 @@ char *lowerCase(char *s) if (s == NULL) return NULL; t = malloc(strlen(s) + 1); - for (i = 0; s[i] != '\0'; i++) + for (i = 0; s[i] != '\0'; i++) { if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32; else t[i] = s[i]; @@ -217,7 +233,8 @@ char *lowerCase(char *s) return t; } -char **explode(char *s, char c) +char ** +explode(char *s, char c) { char **l = NULL; char *p, *t; diff --git a/chkpasswd.tproj/stringops.h b/chkpasswd.tproj/stringops.h index e0a679e..776adf6 100644 --- a/chkpasswd.tproj/stringops.h +++ b/chkpasswd.tproj/stringops.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ #define streq(A, B) (strcmp(A, B) == 0) diff --git a/chpass.tproj/chpass.c b/chpass.tproj/chpass.c index 44f37d5..6b265c0 100644 --- a/chpass.tproj/chpass.c +++ b/chpass.tproj/chpass.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- @@ -135,7 +135,7 @@ main(int argc, char *argv[]) CFStringRef username = NULL; CFStringRef authname = NULL; CFStringRef location = NULL; - + progname = strrchr(argv[0], '/'); if (progname) progname++; else progname = argv[0]; @@ -241,7 +241,7 @@ main(int argc, char *argv[]) } else if (strcmp(progname, "chpass") == 0) { cfprintf(stderr, "Changing account information for %@.\n", username); } - + /* * odGetUser updates DSPath global variable, performs authentication * if necessary, and extracts the attributes. @@ -249,7 +249,7 @@ main(int argc, char *argv[]) CFDictionaryRef attrs_orig = NULL; CFDictionaryRef attrs = NULL; ODRecordRef rec = odGetUser(location, authname, username, &attrs_orig); - + if (!rec || !attrs_orig) exit(1); #endif /* OPEN_DIRECTORY */ @@ -273,9 +273,9 @@ main(int argc, char *argv[]) #ifdef OPEN_DIRECTORY else { ENTRY* ep; - + setrestricted(attrs_orig); - + for (ep = list; ep->prompt; ep++) { if (strncasecmp(ep->prompt, "shell", ep->len) == 0) { if (!ep->restricted) { @@ -356,11 +356,11 @@ main(int argc, char *argv[]) pw_fini(); if (pw == NULL) err(1, "edit()"); - /* + /* * pw_equal does not check for crypted passwords, so we * should do it explicitly */ - if (pw_equal(old_pw, pw) && + if (pw_equal(old_pw, pw) && strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0) errx(0, "user information unchanged"); #endif /* OPEN_DIRECTORY */ @@ -379,7 +379,7 @@ main(int argc, char *argv[]) #ifdef OPEN_DIRECTORY odUpdateUser(rec, attrs_orig, attrs); - + if (rec) CFRelease(rec); exit(0); @@ -434,14 +434,12 @@ main(int argc, char *argv[]) static void baduser(void) { - errx(1, "%s", strerror(EACCES)); } static void usage(void) { - (void)fprintf(stderr, "usage: chpass%s %s [user]\n", #ifdef OPEN_DIRECTORY diff --git a/chpass.tproj/chpass.h b/chpass.tproj/chpass.h index 2fabe66..739601f 100644 --- a/chpass.tproj/chpass.h +++ b/chpass.tproj/chpass.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /* diff --git a/chpass.tproj/edit.c b/chpass.tproj/edit.c index d535654..7c87050 100644 --- a/chpass.tproj/edit.c +++ b/chpass.tproj/edit.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- @@ -199,7 +199,7 @@ display(const char *tfn, struct passwd *pw) (void)fprintf(fp, "# No fields are available to change\n"); (void)fprintf(fp, "###################################\n"); } -#else OPEN_DIRECTORY +#else /* OPEN_DIRECTORY */ (void)fprintf(fp, "#Changing user information for %s.\n", pw->pw_name); if (master_mode) { diff --git a/chpass.tproj/field.c b/chpass.tproj/field.c index 784f2a8..5ae326a 100644 --- a/chpass.tproj/field.c +++ b/chpass.tproj/field.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /* @@ -143,7 +143,7 @@ p_uid(char *p, struct passwd *pw, ENTRY *ep __unused) return (-1); } errno = 0; - id = strtoul(p, &np, 10); + id = (uid_t)strtoul(p, &np, 10); if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { warnx("illegal uid"); return (-1); @@ -177,7 +177,7 @@ p_gid(char *p, struct passwd *pw, ENTRY *ep __unused) return (0); } errno = 0; - id = strtoul(p, &np, 10); + id = (gid_t)strtoul(p, &np, 10); if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { warnx("illegal gid"); return (-1); @@ -317,7 +317,6 @@ p_shell(char *p, struct passwd *pw, ENTRY *ep __unused) return (0); } - #ifdef OPEN_DIRECTORY #include /* ARGSUSED */ diff --git a/chpass.tproj/open_directory.c b/chpass.tproj/open_directory.c index 5f9392b..5949eac 100644 --- a/chpass.tproj/open_directory.c +++ b/chpass.tproj/open_directory.c @@ -24,7 +24,7 @@ setrestricted(CFDictionaryRef attrs) // expressly permitted above // for root, everything is permitted except for the values expressly // restricted above - + for (ep = list; ep->prompt; ep++) { ep->restricted = restrict_by_default; pp = restrict_by_default ? user_allowed : root_restricted; @@ -34,7 +34,7 @@ setrestricted(CFDictionaryRef attrs) break; } } - + // If not root, then it is only permitted to change the shell // when the original value is one of the approved shells. // Otherwise, the assumption is that root has given this user @@ -82,10 +82,10 @@ show_error(CFErrorRef error) { } desc = CFErrorCopyFailureReason(error); if (desc) cfprintf(stderr, " %@", desc); - + desc = CFErrorCopyRecoverySuggestion(error); if (desc) cfprintf(stderr, " %@", desc); - + fprintf(stderr, "\n"); } } @@ -130,11 +130,11 @@ odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictio */ if (authname || !master_mode || (DSPath && CFStringCompareWithOptions(DSPath, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo)) { - + CFStringRef password = NULL; - + if (!authname) authname = user; - + password = prompt_passwd(authname); if (!ODRecordSetNodeCredentials(rec, authname, password, &error)) { CFRelease(rec); @@ -153,9 +153,9 @@ odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs) CFErrorRef error = NULL; int updated = 0; ENTRY* ep; - + for (ep = list; ep->prompt; ep++) { - + // Nothing to update if (!rec || !attrs_orig || !attrs) break; @@ -165,7 +165,7 @@ odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs) CFArrayRef values_orig = CFDictionaryGetValue(attrs_orig, *ep->attrName); CFTypeRef value_orig = values_orig && CFArrayGetCount(values_orig) ? CFArrayGetValueAtIndex(values_orig, 0) : NULL; CFTypeRef value = CFDictionaryGetValue(attrs, *ep->attrName); - + // No need to update if both values are the same if (value == value_orig) continue; @@ -174,12 +174,12 @@ odUpdateUser(ODRecordRef rec, CFDictionaryRef attrs_orig, CFDictionaryRef attrs) if (CFGetTypeID(value_orig) == CFStringGetTypeID() && CFStringCompare(value_orig, value, 0) == kCFCompareEqualTo) continue; } - + // No need to update if empty string replaces NULL if (!value_orig && value) { if (CFStringGetLength(value) == 0) continue; } - + // Needs update if (value) { // if new value is an empty string, send an empty dictionary which will delete the property. diff --git a/chpass.tproj/pw_copy.c b/chpass.tproj/pw_copy.c index b6d156a..a9b9c70 100644 --- a/chpass.tproj/pw_copy.c +++ b/chpass.tproj/pw_copy.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- @@ -69,9 +69,7 @@ extern char *tempname; void -pw_copy(ffd, tfd, pw) - int ffd, tfd; - struct passwd *pw; +pw_copy(int ffd, int tfd, struct passwd *pw) { FILE *from, *to; int done; diff --git a/chpass.tproj/pw_copy.h b/chpass.tproj/pw_copy.h index 8616d2e..7c7af0a 100644 --- a/chpass.tproj/pw_copy.h +++ b/chpass.tproj/pw_copy.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- diff --git a/chpass.tproj/table.c b/chpass.tproj/table.c index dba2154..ba1523d 100644 --- a/chpass.tproj/table.c +++ b/chpass.tproj/table.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- diff --git a/chpass.tproj/util.c b/chpass.tproj/util.c index 493fb4e..d3ab03f 100644 --- a/chpass.tproj/util.c +++ b/chpass.tproj/util.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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@ */ /*- @@ -139,7 +139,7 @@ atot(char *p, time_t *store) if (!*mp) goto bad; if (!strncasecmp(*mp, t, 3)) { - month = mp - months + 1; + month = (int)(mp - months + 1); break; } } @@ -223,27 +223,28 @@ dup_shell(char *name) #if OPEN_DIRECTORY int -cfprintf(FILE* file, const char* format, ...) { - char* cstr; - int result = 0; - va_list args; - va_start(args, format); - CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull); - if (formatStr) { - CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args); - if (str) { - size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1; - va_end(args); - cstr = malloc(size); - if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) { - result = fprintf(file, "%s", cstr); - free(cstr); - } - CFRelease(str); +cfprintf(FILE* file, const char* format, ...) +{ + char* cstr; + int result = 0; + va_list args; + va_start(args, format); + CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull); + if (formatStr) { + CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args); + if (str) { + size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1; + va_end(args); + cstr = malloc(size); + if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) { + result = fprintf(file, "%s", cstr); + free(cstr); } - CFRelease(formatStr); + CFRelease(str); } - return result; + CFRelease(formatStr); + } + return result; } /* @@ -262,9 +263,9 @@ editfile(const char* tfn) if ((editor = getenv("EDITOR")) == NULL) editor = _PATH_VI; - if (p = strrchr(editor, '/')) + if ((p = strrchr(editor, '/'))) ++p; - else + else p = editor; if (stat(tfn, &st1) == -1) @@ -321,12 +322,14 @@ editfile(const char* tfn) return (st1.st_mtime != st2.st_mtime); } -void +#if 0 +static void pw_error(char *name, int err, int eval) { if (err) warn("%s", name); exit(eval); } +#endif #endif /* OPEN_DIRECTORY */ diff --git a/dmesg.tproj/dmesg.c b/dmesg.tproj/dmesg.c index 0315017..ed62442 100644 --- a/dmesg.tproj/dmesg.c +++ b/dmesg.tproj/dmesg.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /*- @@ -60,14 +60,16 @@ #include #include -void -usage() { +static void +usage(void) +{ (void)fprintf(stderr, "usage: sudo dmesg\n"); exit(1); } int -main(int argc, char **argv) { +main(int argc, char **argv) +{ char *msgbuf, *visbuf; int msgbufsize; size_t sysctlsize = sizeof(msgbufsize); @@ -97,4 +99,3 @@ main(int argc, char **argv) { free(msgbuf); exit(0); } - diff --git a/dynamic_pager.tproj/backing_store_alerts.defs b/dynamic_pager.tproj/backing_store_alerts.defs deleted file mode 100644 index 4326949..0000000 --- a/dynamic_pager.tproj/backing_store_alerts.defs +++ /dev/null @@ -1,23 +0,0 @@ -/* - * File: dynamic_pager.tproj/backing_store_alerts.defs - * Author: Chris Youngworth - * Date: Oct, 1999 - * - * Exported alerts from the dynamic_pager facility. - */ - -subsystem - - backing_store_alerts 1000; - -#ifndef __MigTypeCheck -#define __MigTypeCheck 1 -#endif - -#include -#include - - -simpleroutine backing_store_alert( - alert_port : mach_port_t; - in flags : int); diff --git a/dynamic_pager.tproj/backing_store_triggers.defs b/dynamic_pager.tproj/backing_store_triggers.defs deleted file mode 100644 index bbb45a1..0000000 --- a/dynamic_pager.tproj/backing_store_triggers.defs +++ /dev/null @@ -1,25 +0,0 @@ -/* - * File: dynamic_pager.tproj/backing_store_triggers.defs - * Author: Chris Youngworth - * Date: Oct, 1999 - * - * Exported client calls to the dynamic_pager facility. - */ -subsystem - - backing_store_triggers 1200; - - -#ifndef __MigTypeCheck -#define __MigTypeCheck 1 -#endif - -#include -#include - - -simpleroutine backing_store_triggers( - dynamic_pager : mach_port_t; - in hi_wat : int; - in flags : int; - in trigger_port : mach_port_t); diff --git a/dynamic_pager.tproj/default_pager_alerts.defs b/dynamic_pager.tproj/default_pager_alerts.defs deleted file mode 100644 index 4d8fe61..0000000 --- a/dynamic_pager.tproj/default_pager_alerts.defs +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/dynamic_pager.tproj/dynamic_pager.c b/dynamic_pager.tproj/dynamic_pager.c index 9fb3369..9c0f435 100644 --- a/dynamic_pager.tproj/dynamic_pager.c +++ b/dynamic_pager.tproj/dynamic_pager.c @@ -1,4 +1,3 @@ - #define mig_external #include @@ -18,7 +17,6 @@ * -- it could set the prefix for the swapfile name. */ - static void clean_swap_directory(const char *path) { @@ -35,7 +33,7 @@ clean_swap_directory(const char *path) while ((entry = readdir(dir)) != NULL) { if (entry->d_namlen>= 4 && strncmp(entry->d_name, "swap", 4) == 0) { snprintf(buf, sizeof buf, "%s/%s", path, entry->d_name); - unlink(buf); + unlink(buf); } } @@ -85,11 +83,11 @@ main(int argc, char **argv) if (statfs(tmp, &sfs) == -1) { /* - * Setup the swap directory. - */ + * Setup the swap directory. + */ - if (mkdir(tmp, 0755) == -1) { - (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp); + if (mkdir(tmp, 0755) == -1) { + (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp); } } diff --git a/fs_usage.tproj/fs_usage.1 b/fs_usage.tproj/fs_usage.1 index 5fe9c95..3ab0cff 100644 --- a/fs_usage.tproj/fs_usage.1 +++ b/fs_usage.tproj/fs_usage.1 @@ -19,7 +19,7 @@ operate. By default, the activity monitored includes all system processes except the running .Nm fs_usage -process, Terminal, telnetd, sshd, rlogind, tcsh, csh and sh. +process, Terminal, telnetd, telnet, sshd, rlogind, tcsh, csh, sh, and zsh. These defaults can be overridden such that output is limited to include or exclude a list of processes specified by the user. .Pp @@ -119,18 +119,6 @@ excluding sampled data relating to the given list of process IDs or commands. .El .Pp -If you set the DYLD_IMAGE_SUFFIX environment variable to -.Dq Li _debug , -then an application will use the debug version of all libraries, -including the Carbon FileManager. -See -.Xr dyld 1 . -When -.Nm fs_usage -is run against a Carbon Application launched in this environment, -then the high-level Carbon FileManager calls -will be displayed bracketing the system calls that they are built on. -.Pp The data columns displayed are as follows: .Bl -tag -width Ds .Pp diff --git a/fs_usage.tproj/fs_usage.c b/fs_usage.tproj/fs_usage.c index 83b1fda..d128d2d 100644 --- a/fs_usage.tproj/fs_usage.c +++ b/fs_usage.tproj/fs_usage.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,19 +18,18 @@ * 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@ */ /* -cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -lutil -o fs_usage fs_usage.c -*/ + * SDKROOT=macosx.internal cc -I`xcrun -sdk macosx.internal --show-sdk-path`/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -arch x86_64 -Os -lktrace -lutil -o fs_usage fs_usage.c + */ #include #include #include #include -#include #include #include #include @@ -41,326 +40,138 @@ cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRI #include #include +#include +#include + #include #include #include #include #include #include -#include #include #include - -#ifndef KERNEL_PRIVATE -#define KERNEL_PRIVATE -#include -#undef KERNEL_PRIVATE -#else -#include -#endif /*KERNEL_PRIVATE*/ +#include #import #import - - -#define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */ -#define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */ -#define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */ - - -#ifndef RAW_VERSION1 -typedef struct { - int version_no; - int thread_count; - uint64_t TOD_secs; - uint32_t TOD_usecs; -} RAW_header; - -#define RAW_VERSION0 0x55aa0000 -#define RAW_VERSION1 0x55aa0101 -#endif - - -#define MAXINDEX 2048 - -typedef struct LibraryRange { - uint64_t b_address; - uint64_t e_address; -} LibraryRange; - -LibraryRange framework32 = {0,0}; -LibraryRange framework64 = {0,0}; -LibraryRange framework64h = {0,0}; - - -#define TEXT_R 0 -#define DATA_R 1 -#define OBJC_R 2 -#define IMPORT_R 3 -#define UNICODE_R 4 -#define IMAGE_R 5 -#define LINKEDIT_R 6 - - -char *frameworkType[] = { - " ", - " ", - " ", - " ", - " ", - " ", - "", -}; - - -typedef struct LibraryInfo { - uint64_t b_address; - uint64_t e_address; - int r_type; - char *name; -} LibraryInfo; - -LibraryInfo frameworkInfo[MAXINDEX]; -int numFrameworks = 0; - - -/* +/* * MAXCOLS controls when extra data kicks in. * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path. - * If NUMPARMS changes to match the kernel, it will automatically - * get reflected in the -w mode output. */ -#define NUMPARMS 23 -#define PATHLENGTH (NUMPARMS*sizeof(uintptr_t)) - #define MAXCOLS 132 -#define MAX_WIDE_MODE_COLS (PATHLENGTH + 80) +#define MAX_WIDE_MODE_COLS 264 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64 -#define MAX_PATHNAMES 3 -#define MAX_SCALL_PATHNAMES 2 - -typedef struct th_info *th_info_t; - -struct lookup { - uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */ -}; - -struct th_info { - th_info_t next; - uintptr_t thread; - uintptr_t child_thread; - - int in_filemgr; - int in_hfs_update; - int pid; - int type; - int arg1; - int arg2; - int arg3; - int arg4; - int arg5; - int arg6; - int arg7; - int arg8; - int waited; - double stime; - uint64_t vnodeid; - char *nameptr; - uintptr_t *pathptr; - int pn_scall_index; - int pn_work_index; - struct lookup lookups[MAX_PATHNAMES]; -}; - - -typedef struct threadmap * threadmap_t; - -struct threadmap { - threadmap_t tm_next; - - uintptr_t tm_thread; - unsigned int tm_setsize; /* this is a bit count */ - unsigned long *tm_setptr; /* file descripter bitmap */ - char tm_command[MAXCOMLEN + 1]; -}; - +typedef struct th_info { + struct th_info *next; + uintptr_t thread; -typedef struct vnode_info * vnode_info_t; - -struct vnode_info { - vnode_info_t vn_next; - uint64_t vn_id; - uintptr_t vn_pathname[NUMPARMS + 1]; -}; + /* this is needed for execve()/posix_spawn(), because the command name at the end probe is the new name, which we don't want */ + char command[MAXCOMLEN + 1]; -typedef struct meta_info * meta_info_t; + /* + * sometimes a syscall can cause multiple VFS_LOOKUPs of the same vnode with multiple paths + * (e.g., one absolute, one relative). traditional fs_usage behavior was to display the + * *first* lookup, so we need to save it off once we see it. + */ + unsigned long vnodeid; /* the vp of the VFS_LOOKUP we're currently in, 0 if we are not in one */ + char pathname[MAXPATHLEN]; + char pathname2[MAXPATHLEN]; + char *newest_pathname; /* points to pathname2 if it's filled, otherwise pathname if it's filled, otherwise NULL */ + + int pid; + int type; + unsigned long arg1; + unsigned long arg2; + unsigned long arg3; + unsigned long arg4; + unsigned long arg5; + unsigned long arg6; + unsigned long arg7; + unsigned long arg8; + int waited; + uint64_t stime; +} *th_info_t; -struct meta_info { - meta_info_t m_next; - uint64_t m_blkno; - char *m_nameptr; +struct diskio { + struct diskio *next; + struct diskio *prev; + unsigned long type; + unsigned long bp; + unsigned long dev; + unsigned long blkno; + unsigned long iosize; + unsigned long io_errno; + unsigned long is_meta; + uint64_t vnodeid; + uintptr_t issuing_thread; + pid_t issuing_pid; + uintptr_t completion_thread; + char issuing_command[MAXCOMLEN + 1]; + uint64_t issued_time; + uint64_t completed_time; + struct timeval completed_walltime; + uint32_t bc_info; }; #define HASH_SIZE 1024 #define HASH_MASK (HASH_SIZE - 1) -th_info_t th_info_hash[HASH_SIZE]; -th_info_t th_info_freelist; - -threadmap_t threadmap_hash[HASH_SIZE]; -threadmap_t threadmap_freelist; - - -#define VN_HASH_SHIFT 3 -#define VN_HASH_SIZE 16384 -#define VN_HASH_MASK (VN_HASH_SIZE - 1) - -vnode_info_t vn_info_hash[VN_HASH_SIZE]; -meta_info_t m_info_hash[VN_HASH_SIZE]; - - -int filemgr_in_progress = 0; -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 */ -int select_pid_mode = 0; /* Flag set indicates that output is restricted - to selected pids or commands */ - -char *arguments = 0; -int argmax = 0; - - -#define USLEEP_MIN 1 -#define USLEEP_BEHIND 2 -#define USLEEP_MAX 32 -int usleep_ms = USLEEP_MIN; - -/* - * Network only or filesystem only output filter - * Default of zero means report all activity - no filtering - */ -#define FILESYS_FILTER 0x01 -#define NETWORK_FILTER 0x02 -#define EXEC_FILTER 0x08 -#define PATHNAME_FILTER 0x10 -#define DISKIO_FILTER 0x20 -#define DEFAULT_DO_NOT_FILTER 0x00 - -int filter_mode = DEFAULT_DO_NOT_FILTER; - -boolean_t show_cachehits = FALSE; - +void setup_ktrace_callbacks(void); +void extend_syscall(uintptr_t thread, int type, ktrace_event_t event); + +/* printing routines */ +bool check_filter_mode(pid_t pid, th_info_t ti, unsigned long type, int error, int retval, char *sc_name); +void format_print(th_info_t ti, char *sc_name, ktrace_event_t event, unsigned long type, int format, uint64_t now, uint64_t stime, int waited, const char *pathname, struct diskio *dio); + +/* metadata info hash routines */ +void meta_add_name(uint64_t blockno, const char *pathname); +const char *meta_find_name(uint64_t blockno); +void meta_delete_all(void); + +/* event ("thread info") routines */ +void event_enter(int type, ktrace_event_t event); +void event_exit(char *sc_name, int type, ktrace_event_t event, int format); +th_info_t event_find(uintptr_t thread, int type); +void event_delete(th_info_t ti_to_delete); +void event_delete_all(void); +void event_mark_thread_waited(uintptr_t); + +/* network fd set routines */ +void fd_set_is_network(pid_t pid, unsigned long fd, bool set); +bool fd_is_network(pid_t pid, unsigned long fd); +void fd_clear_pid(pid_t pid); +void fd_clear_all(void); + +/* shared region address lookup routines */ +void init_shared_cache_mapping(void); +void lookup_name(uint64_t user_addr, char **type, char **name); + +/* disk I/O tracking routines */ +struct diskio *diskio_start(unsigned long type, unsigned long bp, unsigned long dev, unsigned long blkno, unsigned long iosize, ktrace_event_t event); +struct diskio *diskio_find(unsigned long bp); +struct diskio *diskio_complete(unsigned long bp, unsigned long io_errno, unsigned long resid, uintptr_t thread, uint64_t curtime, struct timeval curtime_wall); +void diskio_print(struct diskio *dio); +void diskio_free(struct diskio *dio); + +/* disk name routines */ #define NFS_DEV -1 #define CS_DEV -2 - -struct diskrec { - struct diskrec *next; - char *diskname; - int dev; -}; - -struct diskio { - struct diskio *next; - struct diskio *prev; - int type; - int bp; - int dev; - int blkno; - int iosize; - int io_errno; - int is_meta; - uint64_t vnodeid; - uintptr_t issuing_thread; - uintptr_t completion_thread; - char issuing_command[MAXCOMLEN + 1]; - double issued_time; - double completed_time; - uint32_t bc_info; -}; - -struct diskrec *disk_list = NULL; -struct diskio *free_diskios = NULL; -struct diskio *busy_diskios = NULL; - - -struct diskio *insert_diskio(); -struct diskio *find_diskio(int); -struct diskio *complete_diskio(); -void free_diskio(); -void print_diskio(); - -int check_filter_mode(struct th_info *, int, int, int, char *); -void format_print(struct th_info *, char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double, double, int, char *, struct diskio *); -void enter_event_now(uintptr_t, int, kd_buf *, char *, double); -void enter_event(uintptr_t, int, kd_buf *, char *, double); -void exit_event(char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double); -void extend_syscall(uintptr_t, int, kd_buf *); - -char *generate_cs_disk_name(int, char *s); -char *find_disk_name(int); -void cache_disk_names(); -void recache_disk_names(); - -void lookup_name(uint64_t user_addr, char **type, char **name); -int ReadSharedCacheMap(const char *, LibraryRange *, char *); -void SortFrameworkAddresses(); - -void fs_usage_fd_set(uintptr_t, unsigned int); -int fs_usage_fd_isset(uintptr_t, unsigned int); -void fs_usage_fd_clear(uintptr_t, unsigned int); - -void init_arguments_buffer(); -int get_real_command_name(int, char *, int); - -void delete_all_events(); -void delete_event(th_info_t); -th_info_t add_event(uintptr_t, int); -th_info_t find_event(uintptr_t, int); -void mark_thread_waited(uintptr_t); - -void read_command_map(); -void delete_all_map_entries(); -void create_map_entry(uintptr_t, int, char *); -void delete_map_entry(uintptr_t); -threadmap_t find_map_entry(uintptr_t); - -char *add_vnode_name(uint64_t, char *); -char *find_vnode_name(uint64_t); -char *find_meta_name(uint64_t); -void add_meta_name(uint64_t, char *); - -void getdivisor(); -void argtopid(); -void set_remove(); -void set_pidcheck(); -void set_pidexclude(); -int quit(); - +char *generate_cs_disk_name(unsigned long dev, char *s); +char *find_disk_name(unsigned long dev); +void cache_disk_names(void); #define CLASS_MASK 0xff000000 #define CSC_MASK 0xffff0000 #define BSC_INDEX(type) ((type >> 2) & 0x3fff) - -#define TRACE_DATA_NEWTHREAD 0x07000004 -#define TRACE_DATA_EXEC 0x07000008 -#define TRACE_STRING_NEWTHREAD 0x07010004 -#define TRACE_STRING_EXEC 0x07010008 - #define MACH_vmfault 0x01300008 #define MACH_pageout 0x01300004 #define MACH_sched 0x01400000 #define MACH_stkhandoff 0x01400008 #define MACH_idle 0x01400024 -#define VFS_LOOKUP 0x03010090 -#define VFS_ALIAS_VP 0x03010094 #define BSC_thread_terminate 0x040c05a4 @@ -385,10 +196,6 @@ int quit(); (s == BC_PLAYBACK_IO) ? "PLBK" : \ (s == 0x0) ? "NONE" : "UNKN" ) -#ifndef DKIO_NOCACHE -#define DKIO_NOCACHE 0x80 -#endif - #define P_DISKIO_READ (DKIO_READ << 2) #define P_DISKIO_ASYNC (DKIO_ASYNC << 2) #define P_DISKIO_META (DKIO_META << 2) @@ -428,7 +235,6 @@ int quit(); #define MSC_map_fd 0x010c00ac #define BSC_BASE 0x040C0000 -#define MSC_BASE 0x010C0000 // Network related codes #define BSC_recvmsg 0x040C006C @@ -469,7 +275,7 @@ int quit(); #define BSC_dup 0x040C00A4 #define BSC_ioctl 0x040C00D8 #define BSC_revoke 0x040C00E0 -#define BSC_symlink 0x040C00E4 +#define BSC_symlink 0x040C00E4 #define BSC_readlink 0x040C00E8 #define BSC_execve 0x040C00EC #define BSC_umask 0x040C00F0 @@ -477,45 +283,45 @@ int quit(); #define BSC_msync 0x040C0104 #define BSC_dup2 0x040C0168 #define BSC_fcntl 0x040C0170 -#define BSC_fsync 0x040C017C -#define BSC_readv 0x040C01E0 -#define BSC_writev 0x040C01E4 -#define BSC_fchown 0x040C01EC -#define BSC_fchmod 0x040C01F0 +#define BSC_fsync 0x040C017C +#define BSC_readv 0x040C01E0 +#define BSC_writev 0x040C01E4 +#define BSC_fchown 0x040C01EC +#define BSC_fchmod 0x040C01F0 #define BSC_rename 0x040C0200 #define BSC_flock 0x040C020C -#define BSC_mkfifo 0x040C0210 -#define BSC_mkdir 0x040C0220 +#define BSC_mkfifo 0x040C0210 +#define BSC_mkdir 0x040C0220 #define BSC_rmdir 0x040C0224 #define BSC_utimes 0x040C0228 #define BSC_futimes 0x040C022C #define BSC_pread 0x040C0264 #define BSC_pwrite 0x040C0268 -#define BSC_statfs 0x040C0274 +#define BSC_statfs 0x040C0274 #define BSC_fstatfs 0x040C0278 #define BSC_unmount 0x040C027C #define BSC_mount 0x040C029C #define BSC_fdatasync 0x040C02EC -#define BSC_stat 0x040C02F0 -#define BSC_fstat 0x040C02F4 -#define BSC_lstat 0x040C02F8 -#define BSC_pathconf 0x040C02FC +#define BSC_stat 0x040C02F0 +#define BSC_fstat 0x040C02F4 +#define BSC_lstat 0x040C02F8 +#define BSC_pathconf 0x040C02FC #define BSC_fpathconf 0x040C0300 #define BSC_getdirentries 0x040C0310 #define BSC_mmap 0x040c0314 #define BSC_lseek 0x040c031c #define BSC_truncate 0x040C0320 -#define BSC_ftruncate 0x040C0324 +#define BSC_ftruncate 0x040C0324 #define BSC_undelete 0x040C0334 -#define BSC_open_dprotected_np 0x040C0360 -#define BSC_getattrlist 0x040C0370 -#define BSC_setattrlist 0x040C0374 -#define BSC_getdirentriesattr 0x040C0378 -#define BSC_exchangedata 0x040C037C -#define BSC_checkuseraccess 0x040C0380 -#define BSC_searchfs 0x040C0384 -#define BSC_delete 0x040C0388 -#define BSC_copyfile 0x040C038C +#define BSC_open_dprotected_np 0x040C0360 +#define BSC_getattrlist 0x040C0370 +#define BSC_setattrlist 0x040C0374 +#define BSC_getdirentriesattr 0x040C0378 +#define BSC_exchangedata 0x040C037C +#define BSC_checkuseraccess 0x040C0380 +#define BSC_searchfs 0x040C0384 +#define BSC_delete 0x040C0388 +#define BSC_copyfile 0x040C038C #define BSC_fgetattrlist 0x040C0390 #define BSC_fsetattrlist 0x040C0394 #define BSC_getxattr 0x040C03A8 @@ -526,9 +332,9 @@ int quit(); #define BSC_fremovexattr 0x040C03BC #define BSC_listxattr 0x040C03C0 #define BSC_flistxattr 0x040C03C4 -#define BSC_fsctl 0x040C03C8 -#define BSC_posix_spawn 0x040C03D0 -#define BSC_ffsctl 0x040C03D4 +#define BSC_fsctl 0x040C03C8 +#define BSC_posix_spawn 0x040C03D0 +#define BSC_ffsctl 0x040C03D4 #define BSC_open_extended 0x040C0454 #define BSC_umask_extended 0x040C0458 #define BSC_stat_extended 0x040C045C @@ -574,7 +380,7 @@ int quit(); #define BSC_writev_nocancel 0x040c0670 #define BSC_pread_nocancel 0x040c0678 #define BSC_pwrite_nocancel 0x040c067c -#define BSC_aio_suspend_nocancel 0x40c0694 +#define BSC_aio_suspend_nocancel 0x40c0694 #define BSC_guarded_open_np 0x040c06e4 #define BSC_guarded_close_np 0x040c06e8 @@ -582,18 +388,18 @@ int quit(); #define BSC_getattrlistbulk 0x040c0734 -#define BSC_openat 0x040c073c +#define BSC_openat 0x040c073c #define BSC_openat_nocancel 0x040c0740 #define BSC_renameat 0x040c0744 -#define BSC_chmodat 0x040c074c -#define BSC_chownat 0x040c0750 -#define BSC_fstatat 0x040c0754 +#define BSC_chmodat 0x040c074c +#define BSC_chownat 0x040c0750 +#define BSC_fstatat 0x040c0754 #define BSC_fstatat64 0x040c0758 -#define BSC_linkat 0x040c075c +#define BSC_linkat 0x040c075c #define BSC_unlinkat 0x040c0760 #define BSC_readlinkat 0x040c0764 #define BSC_symlinkat 0x040c0768 -#define BSC_mkdirat 0x040c076c +#define BSC_mkdirat 0x040c076c #define BSC_getattrlistat 0x040c0770 #define BSC_msync_extended 0x040e0104 @@ -602,79 +408,7 @@ int quit(); #define BSC_mmap_extended 0x040e0314 #define BSC_mmap_extended2 0x040f0314 -// Carbon File Manager support -#define FILEMGR_PBGETCATALOGINFO 0x1e000020 -#define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024 -#define FILEMGR_PBCREATEFILEUNICODE 0x1e000028 -#define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c -#define FILEMGR_PBCREATEFORK 0x1e000030 -#define FILEMGR_PBDELETEFORK 0x1e000034 -#define FILEMGR_PBITERATEFORK 0x1e000038 -#define FILEMGR_PBOPENFORK 0x1e00003c -#define FILEMGR_PBREADFORK 0x1e000040 -#define FILEMGR_PBWRITEFORK 0x1e000044 -#define FILEMGR_PBALLOCATEFORK 0x1e000048 -#define FILEMGR_PBDELETEOBJECT 0x1e00004c -#define FILEMGR_PBEXCHANGEOBJECT 0x1e000050 -#define FILEMGR_PBGETFORKCBINFO 0x1e000054 -#define FILEMGR_PBGETVOLUMEINFO 0x1e000058 -#define FILEMGR_PBMAKEFSREF 0x1e00005c -#define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060 -#define FILEMGR_PBMOVEOBJECT 0x1e000064 -#define FILEMGR_PBOPENITERATOR 0x1e000068 -#define FILEMGR_PBRENAMEUNICODE 0x1e00006c -#define FILEMGR_PBSETCATALOGINFO 0x1e000070 -#define FILEMGR_PBSETVOLUMEINFO 0x1e000074 -#define FILEMGR_FSREFMAKEPATH 0x1e000078 -#define FILEMGR_FSPATHMAKEREF 0x1e00007c - -#define FILEMGR_PBGETCATINFO 0x1e010000 -#define FILEMGR_PBGETCATINFOLITE 0x1e010004 -#define FILEMGR_PBHGETFINFO 0x1e010008 -#define FILEMGR_PBXGETVOLINFO 0x1e01000c -#define FILEMGR_PBHCREATE 0x1e010010 -#define FILEMGR_PBHOPENDF 0x1e010014 -#define FILEMGR_PBHOPENRF 0x1e010018 -#define FILEMGR_PBHGETDIRACCESS 0x1e01001c -#define FILEMGR_PBHSETDIRACCESS 0x1e010020 -#define FILEMGR_PBHMAPID 0x1e010024 -#define FILEMGR_PBHMAPNAME 0x1e010028 -#define FILEMGR_PBCLOSE 0x1e01002c -#define FILEMGR_PBFLUSHFILE 0x1e010030 -#define FILEMGR_PBGETEOF 0x1e010034 -#define FILEMGR_PBSETEOF 0x1e010038 -#define FILEMGR_PBGETFPOS 0x1e01003c -#define FILEMGR_PBREAD 0x1e010040 -#define FILEMGR_PBWRITE 0x1e010044 -#define FILEMGR_PBGETFCBINFO 0x1e010048 -#define FILEMGR_PBSETFINFO 0x1e01004c -#define FILEMGR_PBALLOCATE 0x1e010050 -#define FILEMGR_PBALLOCCONTIG 0x1e010054 -#define FILEMGR_PBSETFPOS 0x1e010058 -#define FILEMGR_PBSETCATINFO 0x1e01005c -#define FILEMGR_PBGETVOLPARMS 0x1e010060 -#define FILEMGR_PBSETVINFO 0x1e010064 -#define FILEMGR_PBMAKEFSSPEC 0x1e010068 -#define FILEMGR_PBHGETVINFO 0x1e01006c -#define FILEMGR_PBCREATEFILEIDREF 0x1e010070 -#define FILEMGR_PBDELETEFILEIDREF 0x1e010074 -#define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078 -#define FILEMGR_PBFLUSHVOL 0x1e01007c -#define FILEMGR_PBHRENAME 0x1e010080 -#define FILEMGR_PBCATMOVE 0x1e010084 -#define FILEMGR_PBEXCHANGEFILES 0x1e010088 -#define FILEMGR_PBHDELETE 0x1e01008c -#define FILEMGR_PBDIRCREATE 0x1e010090 -#define FILEMGR_PBCATSEARCH 0x1e010094 -#define FILEMGR_PBHSETFLOCK 0x1e010098 -#define FILEMGR_PBHRSTFLOCK 0x1e01009c -#define FILEMGR_PBLOCKRANGE 0x1e0100a0 -#define FILEMGR_PBUNLOCKRANGE 0x1e0100a4 - - -#define FILEMGR_CLASS 0x1e -#define FILEMGR_BASE 0x1e000000 - +#define FMT_NOTHING -1 #define FMT_DEFAULT 0 #define FMT_FD 1 #define FMT_FD_IO 2 @@ -724,405 +458,232 @@ int quit(); #define FMT_RENAMEAT 46 #define FMT_IOCTL_SYNCCACHE 47 -#define MAX_BSD_SYSCALL 526 - -struct bsd_syscall { - char *sc_name; - int sc_format; -} bsd_syscalls[MAX_BSD_SYSCALL]; - - -int bsd_syscall_types[] = { - BSC_recvmsg, - BSC_recvmsg_nocancel, - BSC_sendmsg, - BSC_sendmsg_nocancel, - BSC_recvfrom, - BSC_recvfrom_nocancel, - BSC_accept, - BSC_accept_nocancel, - BSC_select, - BSC_select_nocancel, - BSC_socket, - BSC_connect, - BSC_connect_nocancel, - BSC_bind, - BSC_listen, - BSC_sendto, - BSC_sendto_nocancel, - BSC_socketpair, - BSC_read, - BSC_read_nocancel, - BSC_write, - BSC_write_nocancel, - BSC_open, - BSC_open_nocancel, - BSC_close, - BSC_close_nocancel, - BSC_link, - BSC_unlink, - BSC_chdir, - BSC_fchdir, - BSC_mknod, - BSC_chmod, - BSC_chown, - BSC_access, - BSC_chflags, - BSC_fchflags, - BSC_sync, - BSC_dup, - BSC_revoke, - BSC_symlink, - BSC_readlink, - BSC_exit, - BSC_execve, - BSC_posix_spawn, - BSC_umask, - BSC_chroot, - BSC_dup2, - BSC_fsync, - BSC_fsync_nocancel, - BSC_readv, - BSC_readv_nocancel, - BSC_writev, - BSC_writev_nocancel, - BSC_fchown, - BSC_fchmod, - BSC_rename, - BSC_mkfifo, - BSC_mkdir, - BSC_rmdir, - BSC_utimes, - BSC_futimes, - BSC_pread, - BSC_pread_nocancel, - BSC_pwrite, - BSC_pwrite_nocancel, - BSC_statfs, - BSC_fstatfs, - BSC_fdatasync, - BSC_stat, - BSC_fstat, - BSC_lstat, - BSC_mount, - BSC_unmount, - BSC_pathconf, - BSC_fpathconf, - BSC_getdirentries, - BSC_mmap, - BSC_lseek, - BSC_truncate, - BSC_ftruncate, - BSC_flock, - BSC_undelete, - BSC_open_dprotected_np, - BSC_getattrlist, - BSC_setattrlist, - BSC_fgetattrlist, - BSC_fsetattrlist, - BSC_getdirentriesattr, - BSC_exchangedata, - BSC_checkuseraccess, - BSC_searchfs, - BSC_delete, - BSC_copyfile, - BSC_getxattr, - BSC_fgetxattr, - BSC_setxattr, - BSC_fsetxattr, - BSC_removexattr, - BSC_fremovexattr, - BSC_listxattr, - BSC_flistxattr, - BSC_fsctl, - BSC_ffsctl, - BSC_open_extended, - BSC_umask_extended, - BSC_stat_extended, - BSC_lstat_extended, - BSC_fstat_extended, - BSC_chmod_extended, - BSC_fchmod_extended, - BSC_access_extended, - BSC_mkfifo_extended, - BSC_mkdir_extended, - BSC_aio_fsync, - BSC_aio_return, - BSC_aio_suspend, - BSC_aio_suspend_nocancel, - BSC_aio_cancel, - BSC_aio_error, - BSC_aio_read, - BSC_aio_write, - BSC_lio_listio, - BSC_lchown, - BSC_sendfile, - BSC_msync, - BSC_msync_nocancel, - BSC_fcntl, - BSC_fcntl_nocancel, - BSC_ioctl, - BSC_stat64, - BSC_fstat64, - BSC_lstat64, - BSC_stat64_extended, - BSC_lstat64_extended, - BSC_fstat64_extended, - BSC_getdirentries64, - BSC_statfs64, - BSC_fstatfs64, - BSC_pthread_chdir, - BSC_pthread_fchdir, - BSC_getfsstat, - BSC_getfsstat64, - BSC_guarded_open_np, - BSC_guarded_close_np, - BSC_fsgetpath, - BSC_getattrlistbulk, - BSC_openat, - BSC_openat_nocancel, - BSC_renameat, - BSC_chmodat, - BSC_chownat, - BSC_fstatat, - BSC_fstatat64, - BSC_linkat, - BSC_unlinkat, - BSC_readlinkat, - BSC_symlinkat, - BSC_mkdirat, - BSC_getattrlistat, - 0 -}; - - -#define MAX_FILEMGR 512 - -struct filemgr_call { - char *fm_name; -} filemgr_calls[MAX_FILEMGR]; - - -int filemgr_call_types[] = { - FILEMGR_PBGETCATALOGINFO, - FILEMGR_PBGETCATALOGINFOBULK, - FILEMGR_PBCREATEFILEUNICODE, - FILEMGR_PBCREATEDIRECTORYUNICODE, - FILEMGR_PBCREATEFORK, - FILEMGR_PBDELETEFORK, - FILEMGR_PBITERATEFORK, - FILEMGR_PBOPENFORK, - FILEMGR_PBREADFORK, - FILEMGR_PBWRITEFORK, - FILEMGR_PBALLOCATEFORK, - FILEMGR_PBDELETEOBJECT, - FILEMGR_PBEXCHANGEOBJECT, - FILEMGR_PBGETFORKCBINFO, - FILEMGR_PBGETVOLUMEINFO, - FILEMGR_PBMAKEFSREF, - FILEMGR_PBMAKEFSREFUNICODE, - FILEMGR_PBMOVEOBJECT, - FILEMGR_PBOPENITERATOR, - FILEMGR_PBRENAMEUNICODE, - FILEMGR_PBSETCATALOGINFO, - FILEMGR_PBSETVOLUMEINFO, - FILEMGR_FSREFMAKEPATH, - FILEMGR_FSPATHMAKEREF, - - FILEMGR_PBGETCATINFO, - FILEMGR_PBGETCATINFOLITE, - FILEMGR_PBHGETFINFO, - FILEMGR_PBXGETVOLINFO, - FILEMGR_PBHCREATE, - FILEMGR_PBHOPENDF, - FILEMGR_PBHOPENRF, - FILEMGR_PBHGETDIRACCESS, - FILEMGR_PBHSETDIRACCESS, - FILEMGR_PBHMAPID, - FILEMGR_PBHMAPNAME, - FILEMGR_PBCLOSE, - FILEMGR_PBFLUSHFILE, - FILEMGR_PBGETEOF, - FILEMGR_PBSETEOF, - FILEMGR_PBGETFPOS, - FILEMGR_PBREAD, - FILEMGR_PBWRITE, - FILEMGR_PBGETFCBINFO, - FILEMGR_PBSETFINFO, - FILEMGR_PBALLOCATE, - FILEMGR_PBALLOCCONTIG, - FILEMGR_PBSETFPOS, - FILEMGR_PBSETCATINFO, - FILEMGR_PBGETVOLPARMS, - FILEMGR_PBSETVINFO, - FILEMGR_PBMAKEFSSPEC, - FILEMGR_PBHGETVINFO, - FILEMGR_PBCREATEFILEIDREF, - FILEMGR_PBDELETEFILEIDREF, - FILEMGR_PBRESOLVEFILEIDREF, - FILEMGR_PBFLUSHVOL, - FILEMGR_PBHRENAME, - FILEMGR_PBCATMOVE, - FILEMGR_PBEXCHANGEFILES, - FILEMGR_PBHDELETE, - FILEMGR_PBDIRCREATE, - FILEMGR_PBCATSEARCH, - FILEMGR_PBHSETFLOCK, - FILEMGR_PBHRSTFLOCK, - FILEMGR_PBLOCKRANGE, - FILEMGR_PBUNLOCKRANGE, - 0 -}; - - - -#define MAX_PIDS 256 -int pids[MAX_PIDS]; - -int num_of_pids = 0; -int exclude_pids = 0; -int exclude_default_pids = 1; - - -struct kinfo_proc *kp_buffer = 0; -int kp_nentries = 0; - -#define EVENT_BASE 60000 - -int num_events = EVENT_BASE; - - #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) -#define DBG_FUNC_MASK 0xfffffffc - -double divisor = 0.0; /* Trace divisor converts to microseconds */ - -int mib[6]; -size_t needed; -char *my_buffer; - -kbufinfo_t bufinfo = {0, 0, 0, 0, 0}; - - -/* defines for tracking file descriptor state */ -#define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per - thread that we will track */ -#define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8) -#define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long)) +#pragma mark global state -int trace_enabled = 0; -int set_remove_flag = 1; - -int BC_flag = 0; - -char *RAW_file = (char *)0; -int RAW_flag = 0; -int RAW_fd = 0; - -uint64_t sample_TOD_secs; -uint32_t sample_TOD_usecs; - -double bias_now = 0.0; -double start_time = 0.0; -double end_time = 999999999999.9; - - -void set_numbufs(); -void set_filter(); -void set_init(); -void set_enable(); -void sample_sc(); -int quit(); +ktrace_session_t s; +bool BC_flag = false; +bool RAW_flag = false; +bool wideflag = false; +bool include_waited_flag = false; +bool want_kernel_task = true; +dispatch_source_t stop_timer, sigquit_source, sigpipe_source, sighup_source, sigterm_source, sigwinch_source; +uint64_t mach_time_of_first_event; +uint64_t start_time_ns = 0; +uint64_t end_time_ns = UINT64_MAX; +unsigned int columns = 0; /* - * signal handlers + * Network only or filesystem only output filter + * Default of zero means report all activity - no filtering */ +#define FILESYS_FILTER 0x01 +#define NETWORK_FILTER 0x02 +#define EXEC_FILTER 0x08 +#define PATHNAME_FILTER 0x10 +#define DISKIO_FILTER 0x20 +#define DEFAULT_DO_NOT_FILTER 0x00 -void leave() /* exit under normal conditions -- INT handler */ -{ - int i; - void set_enable(); - void set_pidcheck(); - void set_pidexclude(); - void set_remove(); - - fflush(0); - - set_enable(0); - - if (exclude_pids == 0) { - for (i = 0; i < num_of_pids; i++) - set_pidcheck(pids[i], 0); - } - else { - for (i = 0; i < num_of_pids; i++) - set_pidexclude(pids[i], 0); - } - set_remove(); - - exit(0); -} - - -int -quit(s) -char *s; -{ - if (trace_enabled) - set_enable(0); +int filter_mode = DEFAULT_DO_NOT_FILTER; +bool show_cachehits = false; - /* - * This flag is turned off when calling - * quit() due to a set_remove() failure. - */ - if (set_remove_flag) - set_remove(); +#pragma mark syscall lookup table - fprintf(stderr, "fs_usage: "); - if (s) - fprintf(stderr, "%s", s); +#define MAX_BSD_SYSCALL 526 - exit(1); -} +struct bsd_syscall { + char *sc_name; + int sc_format; +}; +#define NORMAL_SYSCALL(name) \ + [BSC_INDEX(BSC_##name)] = {#name, FMT_DEFAULT} + +#define SYSCALL(name, format) \ + [BSC_INDEX(BSC_##name)] = {#name, format} + +#define SYSCALL_NAMED(name, displayname, format) \ + [BSC_INDEX(BSC_##name)] = {#displayname, format} + +#define SYSCALL_WITH_NOCANCEL(name, format) \ + [BSC_INDEX(BSC_##name)] = {#name, format}, \ + [BSC_INDEX(BSC_##name##_nocancel)] = {#name, format} + +const struct bsd_syscall bsd_syscalls[MAX_BSD_SYSCALL] = { + SYSCALL(sendfile, FMT_FD), /* this should be changed to FMT_SENDFILE once we add an extended info trace event */ + SYSCALL_WITH_NOCANCEL(recvmsg, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(sendmsg, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(recvfrom, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(sendto, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(select, FMT_SELECT), + SYSCALL_WITH_NOCANCEL(accept, FMT_FD_2), + SYSCALL(socket, FMT_SOCKET), + SYSCALL_WITH_NOCANCEL(connect, FMT_FD), + SYSCALL(bind, FMT_FD), + SYSCALL(listen, FMT_FD), + SYSCALL(mmap, FMT_MMAP), + NORMAL_SYSCALL(socketpair), + NORMAL_SYSCALL(getxattr), + NORMAL_SYSCALL(setxattr), + NORMAL_SYSCALL(removexattr), + NORMAL_SYSCALL(listxattr), + NORMAL_SYSCALL(stat), + NORMAL_SYSCALL(stat64), + NORMAL_SYSCALL(stat_extended), + SYSCALL_NAMED(stat64_extended, stat_extended64, FMT_DEFAULT), /* should be stat64_extended ? */ + SYSCALL(mount, FMT_MOUNT), + SYSCALL(unmount, FMT_UNMOUNT), + NORMAL_SYSCALL(exit), + NORMAL_SYSCALL(execve), + NORMAL_SYSCALL(posix_spawn), + SYSCALL_WITH_NOCANCEL(open, FMT_OPEN), + SYSCALL(open_extended, FMT_OPEN), + SYSCALL(guarded_open_np, FMT_OPEN), + SYSCALL_NAMED(open_dprotected_np, open_dprotected, FMT_OPEN), + SYSCALL(dup, FMT_FD_2), + SYSCALL(dup2, FMT_FD_2), + SYSCALL_WITH_NOCANCEL(close, FMT_FD), + SYSCALL(guarded_close_np, FMT_FD), + SYSCALL_WITH_NOCANCEL(read, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(write, FMT_FD_IO), + SYSCALL(fgetxattr, FMT_FD), + SYSCALL(fsetxattr, FMT_FD), + SYSCALL(fremovexattr, FMT_FD), + SYSCALL(flistxattr, FMT_FD), + SYSCALL(fstat, FMT_FD), + SYSCALL(fstat64, FMT_FD), + SYSCALL(fstat_extended, FMT_FD), + SYSCALL(fstat64_extended, FMT_FD), + NORMAL_SYSCALL(lstat), + NORMAL_SYSCALL(lstat64), + NORMAL_SYSCALL(lstat_extended), + SYSCALL_NAMED(lstat64_extended, lstat_extended64, FMT_DEFAULT), + NORMAL_SYSCALL(link), + NORMAL_SYSCALL(unlink), + NORMAL_SYSCALL(mknod), + SYSCALL(umask, FMT_UMASK), + SYSCALL(umask_extended, FMT_UMASK), + SYSCALL(chmod, FMT_CHMOD), + SYSCALL(chmod_extended, FMT_CHMOD_EXT), + SYSCALL(fchmod, FMT_FCHMOD), + SYSCALL(fchmod_extended, FMT_FCHMOD_EXT), + NORMAL_SYSCALL(chown), + NORMAL_SYSCALL(lchown), + SYSCALL(fchown, FMT_FD), + SYSCALL(access, FMT_ACCESS), + NORMAL_SYSCALL(access_extended), + NORMAL_SYSCALL(chdir), + NORMAL_SYSCALL(pthread_chdir), + NORMAL_SYSCALL(chroot), + NORMAL_SYSCALL(utimes), + SYSCALL_NAMED(delete, delete-Carbon, FMT_DEFAULT), + NORMAL_SYSCALL(undelete), + NORMAL_SYSCALL(revoke), + NORMAL_SYSCALL(fsctl), + SYSCALL(ffsctl, FMT_FD), + SYSCALL(chflags, FMT_CHFLAGS), + SYSCALL(fchflags, FMT_FCHFLAGS), + SYSCALL(fchdir, FMT_FD), + SYSCALL(pthread_fchdir, FMT_FD), + SYSCALL(futimes, FMT_FD), + NORMAL_SYSCALL(sync), + NORMAL_SYSCALL(symlink), + NORMAL_SYSCALL(readlink), + SYSCALL_WITH_NOCANCEL(fsync, FMT_FD), + SYSCALL(fdatasync, FMT_FD), + SYSCALL_WITH_NOCANCEL(readv, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(writev, FMT_FD_IO), + SYSCALL_WITH_NOCANCEL(pread, FMT_PREAD), + SYSCALL_WITH_NOCANCEL(pwrite, FMT_PREAD), + NORMAL_SYSCALL(mkdir), + NORMAL_SYSCALL(mkdir_extended), + NORMAL_SYSCALL(mkfifo), + NORMAL_SYSCALL(mkfifo_extended), + NORMAL_SYSCALL(rmdir), + NORMAL_SYSCALL(statfs), + NORMAL_SYSCALL(statfs64), + NORMAL_SYSCALL(getfsstat), + NORMAL_SYSCALL(getfsstat64), + SYSCALL(fstatfs, FMT_FD), + SYSCALL(fstatfs64, FMT_FD), + NORMAL_SYSCALL(pathconf), + SYSCALL(fpathconf, FMT_FD), + SYSCALL(getdirentries, FMT_FD_IO), + SYSCALL(getdirentries64, FMT_FD_IO), + SYSCALL(lseek, FMT_LSEEK), + SYSCALL(truncate, FMT_TRUNC), + SYSCALL(ftruncate, FMT_FTRUNC), + SYSCALL(flock, FMT_FLOCK), + NORMAL_SYSCALL(getattrlist), + NORMAL_SYSCALL(setattrlist), + SYSCALL(fgetattrlist, FMT_FD), + SYSCALL(fsetattrlist, FMT_FD), + SYSCALL(getdirentriesattr, FMT_FD), + NORMAL_SYSCALL(exchangedata), + NORMAL_SYSCALL(rename), + NORMAL_SYSCALL(copyfile), + NORMAL_SYSCALL(checkuseraccess), + NORMAL_SYSCALL(searchfs), + SYSCALL(aio_fsync, FMT_AIO_FSYNC), + SYSCALL(aio_return, FMT_AIO_RETURN), + SYSCALL_WITH_NOCANCEL(aio_suspend, FMT_AIO_SUSPEND), + SYSCALL(aio_cancel, FMT_AIO_CANCEL), + SYSCALL(aio_error, FMT_AIO), + SYSCALL(aio_read, FMT_AIO), + SYSCALL(aio_write, FMT_AIO), + SYSCALL(lio_listio, FMT_LIO_LISTIO), + SYSCALL_WITH_NOCANCEL(msync, FMT_MSYNC), + SYSCALL_WITH_NOCANCEL(fcntl, FMT_FCNTL), + SYSCALL(ioctl, FMT_IOCTL), + NORMAL_SYSCALL(fsgetpath), + NORMAL_SYSCALL(getattrlistbulk), + SYSCALL_WITH_NOCANCEL(openat, FMT_OPENAT), /* open_nocancel() was previously shown as "open_nocanel" (note spelling) */ + SYSCALL(renameat, FMT_RENAMEAT), + SYSCALL(chmodat, FMT_CHMODAT), + SYSCALL(chownat, FMT_AT), + SYSCALL(fstatat, FMT_AT), + SYSCALL(fstatat64, FMT_AT), + SYSCALL(linkat, FMT_AT), + SYSCALL(unlinkat, FMT_AT), + SYSCALL(readlinkat, FMT_AT), + SYSCALL(symlinkat, FMT_AT), + SYSCALL(mkdirat, FMT_AT), + SYSCALL(getattrlistat, FMT_AT), +}; -void get_screenwidth() +static void +get_screenwidth(void) { - struct winsize size; + struct winsize size; columns = MAXCOLS; - if (isatty(1)) { - if (ioctl(1, TIOCGWINSZ, &size) != -1) { - columns = size.ws_col; + if (isatty(STDOUT_FILENO)) { + if (ioctl(1, TIOCGWINSZ, &size) != -1) { + columns = size.ws_col; if (columns > MAXWIDTH) - columns = MAXWIDTH; + columns = MAXWIDTH; } } } - -void sigwinch() -{ - if (!wideflag) - get_screenwidth(); -} - - -void getdivisor() +static uint64_t +mach_to_nano(uint64_t mach) { - struct mach_timebase_info mti; - - mach_timebase_info(&mti); + uint64_t nanoseconds = 0; + assert(ktrace_convert_timestamp_to_nanoseconds(s, mach, &nanoseconds) == 0); - divisor = ((double)mti.denom / (double)mti.numer) * 1000; + return nanoseconds; } +static void +exit_usage(void) +{ + const char *myname; -int -exit_usage(char *myname) { + myname = getprogname(); fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [-b] [-t seconds] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd] ...]\n", myname); fprintf(stderr, " -e exclude the specified list of pids from the sample\n"); @@ -1142,3119 +703,1850 @@ exit_usage(char *myname) { fprintf(stderr, " -E if -R is specified, selects an end point in microseconds\n"); fprintf(stderr, " pid selects process(s) to sample\n"); fprintf(stderr, " cmd selects process(s) matching command string to sample\n"); - fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS); fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n"); fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n"); exit(1); } +int +main(int argc, char *argv[]) +{ + char ch; + int rv; + bool exclude_pids = false; + double time_limit = 0.0; -int filemgr_index(type) { - - if (type & 0x10000) - return (((type >> 2) & 0x3fff) + 256); - - return (((type >> 2) & 0x3fff)); -} + get_screenwidth(); + s = ktrace_session_create(); + assert(s); -void init_tables(void) -{ int i; - int type; - int code; + while ((ch = getopt(argc, argv, "bewf:R:S:E:t:W")) != -1) { + switch (ch) { + case 'e': + exclude_pids = true; + break; + case 'w': + wideflag = 1; + columns = MAX_WIDE_MODE_COLS; + break; - for (i = 0; i < MAX_BSD_SYSCALL; i++) { - bsd_syscalls[i].sc_name = NULL; - bsd_syscalls[i].sc_format = FMT_DEFAULT; - } + case 'W': + include_waited_flag = true; + break; - for (i = 0; i < MAX_FILEMGR; i++) { - filemgr_calls[i].fm_name = NULL; - } + case 'f': + if (!strcmp(optarg, "network")) + filter_mode |= NETWORK_FILTER; + else if (!strcmp(optarg, "filesys")) + filter_mode |= FILESYS_FILTER; + else if (!strcmp(optarg, "cachehit")) + show_cachehits = true; + else if (!strcmp(optarg, "exec")) + filter_mode |= EXEC_FILTER; + else if (!strcmp(optarg, "pathname")) + filter_mode |= PATHNAME_FILTER; + else if (!strcmp(optarg, "diskio")) + filter_mode |= DISKIO_FILTER; - for (i = 0; (type = bsd_syscall_types[i]); i++) { + break; - code = BSC_INDEX(type); + case 'b': + BC_flag = true; + break; - if (code >= MAX_BSD_SYSCALL) { - printf("BSD syscall init (%x): type exceeds table size\n", type); - continue; - } - switch (type) { + case 't': + time_limit = atof(optarg); - case BSC_sendfile: - bsd_syscalls[code].sc_name = "sendfile"; - bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */ - break; /* once we add an extended info trace event */ - - case BSC_recvmsg: - case BSC_recvmsg_nocancel: - bsd_syscalls[code].sc_name = "recvmsg"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_sendmsg: - case BSC_sendmsg_nocancel: - bsd_syscalls[code].sc_name = "sendmsg"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_recvfrom: - case BSC_recvfrom_nocancel: - bsd_syscalls[code].sc_name = "recvfrom"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_sendto: - case BSC_sendto_nocancel: - bsd_syscalls[code].sc_name = "sendto"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_select: - case BSC_select_nocancel: - bsd_syscalls[code].sc_name = "select"; - bsd_syscalls[code].sc_format = FMT_SELECT; - break; - - case BSC_accept: - case BSC_accept_nocancel: - bsd_syscalls[code].sc_name = "accept"; - bsd_syscalls[code].sc_format = FMT_FD_2; - break; - - case BSC_socket: - bsd_syscalls[code].sc_name = "socket"; - bsd_syscalls[code].sc_format = FMT_SOCKET; - break; - - case BSC_connect: - case BSC_connect_nocancel: - bsd_syscalls[code].sc_name = "connect"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_bind: - bsd_syscalls[code].sc_name = "bind"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_listen: - bsd_syscalls[code].sc_name = "listen"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_mmap: - bsd_syscalls[code].sc_name = "mmap"; - bsd_syscalls[code].sc_format = FMT_MMAP; - break; - - case BSC_socketpair: - bsd_syscalls[code].sc_name = "socketpair"; - break; - - case BSC_getxattr: - bsd_syscalls[code].sc_name = "getxattr"; - break; - - case BSC_setxattr: - bsd_syscalls[code].sc_name = "setxattr"; - break; - - case BSC_removexattr: - bsd_syscalls[code].sc_name = "removexattr"; - break; - - case BSC_listxattr: - bsd_syscalls[code].sc_name = "listxattr"; - break; - - case BSC_stat: - bsd_syscalls[code].sc_name = "stat"; - break; - - case BSC_stat64: - bsd_syscalls[code].sc_name = "stat64"; - break; - - case BSC_stat_extended: - bsd_syscalls[code].sc_name = "stat_extended"; - break; - - case BSC_stat64_extended: - bsd_syscalls[code].sc_name = "stat_extended64"; - break; - - case BSC_mount: - bsd_syscalls[code].sc_name = "mount"; - bsd_syscalls[code].sc_format = FMT_MOUNT; - break; - - case BSC_unmount: - bsd_syscalls[code].sc_name = "unmount"; - bsd_syscalls[code].sc_format = FMT_UNMOUNT; - break; - - case BSC_exit: - bsd_syscalls[code].sc_name = "exit"; - break; - - case BSC_execve: - bsd_syscalls[code].sc_name = "execve"; - break; - - case BSC_posix_spawn: - bsd_syscalls[code].sc_name = "posix_spawn"; - break; - - case BSC_open: - case BSC_open_nocancel: - bsd_syscalls[code].sc_name = "open"; - bsd_syscalls[code].sc_format = FMT_OPEN; - break; - - case BSC_open_extended: - bsd_syscalls[code].sc_name = "open_extended"; - bsd_syscalls[code].sc_format = FMT_OPEN; - break; - - case BSC_guarded_open_np: - bsd_syscalls[code].sc_name = "guarded_open_np"; - bsd_syscalls[code].sc_format = FMT_OPEN; - break; - - case BSC_open_dprotected_np: - bsd_syscalls[code].sc_name = "open_dprotected"; - bsd_syscalls[code].sc_format = FMT_OPEN; - break; - - case BSC_dup: - bsd_syscalls[code].sc_name = "dup"; - bsd_syscalls[code].sc_format = FMT_FD_2; - break; - - case BSC_dup2: - bsd_syscalls[code].sc_name = "dup2"; - bsd_syscalls[code].sc_format = FMT_FD_2; - break; - - case BSC_close: - case BSC_close_nocancel: - bsd_syscalls[code].sc_name = "close"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_guarded_close_np: - bsd_syscalls[code].sc_name = "guarded_close_np"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_read: - case BSC_read_nocancel: - bsd_syscalls[code].sc_name = "read"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_write: - case BSC_write_nocancel: - bsd_syscalls[code].sc_name = "write"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_fgetxattr: - bsd_syscalls[code].sc_name = "fgetxattr"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fsetxattr: - bsd_syscalls[code].sc_name = "fsetxattr"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fremovexattr: - bsd_syscalls[code].sc_name = "fremovexattr"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_flistxattr: - bsd_syscalls[code].sc_name = "flistxattr"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fstat: - bsd_syscalls[code].sc_name = "fstat"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fstat64: - bsd_syscalls[code].sc_name = "fstat64"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fstat_extended: - bsd_syscalls[code].sc_name = "fstat_extended"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fstat64_extended: - bsd_syscalls[code].sc_name = "fstat64_extended"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_lstat: - bsd_syscalls[code].sc_name = "lstat"; - break; - - case BSC_lstat64: - bsd_syscalls[code].sc_name = "lstat64"; - break; - - case BSC_lstat_extended: - bsd_syscalls[code].sc_name = "lstat_extended"; - break; - - case BSC_lstat64_extended: - bsd_syscalls[code].sc_name = "lstat_extended64"; - break; - - case BSC_link: - bsd_syscalls[code].sc_name = "link"; - break; - - case BSC_unlink: - bsd_syscalls[code].sc_name = "unlink"; - break; - - case BSC_mknod: - bsd_syscalls[code].sc_name = "mknod"; - break; - - case BSC_umask: - bsd_syscalls[code].sc_name = "umask"; - bsd_syscalls[code].sc_format = FMT_UMASK; - break; - - case BSC_umask_extended: - bsd_syscalls[code].sc_name = "umask_extended"; - bsd_syscalls[code].sc_format = FMT_UMASK; - break; - - case BSC_chmod: - bsd_syscalls[code].sc_name = "chmod"; - bsd_syscalls[code].sc_format = FMT_CHMOD; - break; - - case BSC_chmod_extended: - bsd_syscalls[code].sc_name = "chmod_extended"; - bsd_syscalls[code].sc_format = FMT_CHMOD_EXT; - break; - - case BSC_fchmod: - bsd_syscalls[code].sc_name = "fchmod"; - bsd_syscalls[code].sc_format = FMT_FCHMOD; - break; - - case BSC_fchmod_extended: - bsd_syscalls[code].sc_name = "fchmod_extended"; - bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT; - break; - - case BSC_chown: - bsd_syscalls[code].sc_name = "chown"; - break; - - case BSC_lchown: - bsd_syscalls[code].sc_name = "lchown"; - break; - - case BSC_fchown: - bsd_syscalls[code].sc_name = "fchown"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_access: - bsd_syscalls[code].sc_name = "access"; - bsd_syscalls[code].sc_format = FMT_ACCESS; - break; - - case BSC_access_extended: - bsd_syscalls[code].sc_name = "access_extended"; - break; - - case BSC_chdir: - bsd_syscalls[code].sc_name = "chdir"; - break; - - case BSC_pthread_chdir: - bsd_syscalls[code].sc_name = "pthread_chdir"; - break; - - case BSC_chroot: - bsd_syscalls[code].sc_name = "chroot"; - break; - - case BSC_utimes: - bsd_syscalls[code].sc_name = "utimes"; - break; - - case BSC_delete: - bsd_syscalls[code].sc_name = "delete-Carbon"; - break; - - case BSC_undelete: - bsd_syscalls[code].sc_name = "undelete"; - break; - - case BSC_revoke: - bsd_syscalls[code].sc_name = "revoke"; - break; - - case BSC_fsctl: - bsd_syscalls[code].sc_name = "fsctl"; - break; - - case BSC_ffsctl: - bsd_syscalls[code].sc_name = "ffsctl"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_chflags: - bsd_syscalls[code].sc_name = "chflags"; - bsd_syscalls[code].sc_format = FMT_CHFLAGS; - break; - - case BSC_fchflags: - bsd_syscalls[code].sc_name = "fchflags"; - bsd_syscalls[code].sc_format = FMT_FCHFLAGS; - break; - - case BSC_fchdir: - bsd_syscalls[code].sc_name = "fchdir"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_pthread_fchdir: - bsd_syscalls[code].sc_name = "pthread_fchdir"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_futimes: - bsd_syscalls[code].sc_name = "futimes"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_sync: - bsd_syscalls[code].sc_name = "sync"; - break; - - case BSC_symlink: - bsd_syscalls[code].sc_name = "symlink"; - break; - - case BSC_readlink: - bsd_syscalls[code].sc_name = "readlink"; - break; - - case BSC_fsync: - case BSC_fsync_nocancel: - bsd_syscalls[code].sc_name = "fsync"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fdatasync: - bsd_syscalls[code].sc_name = "fdatasync"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_readv: - case BSC_readv_nocancel: - bsd_syscalls[code].sc_name = "readv"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_writev: - case BSC_writev_nocancel: - bsd_syscalls[code].sc_name = "writev"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_pread: - case BSC_pread_nocancel: - bsd_syscalls[code].sc_name = "pread"; - bsd_syscalls[code].sc_format = FMT_PREAD; - break; - - case BSC_pwrite: - case BSC_pwrite_nocancel: - bsd_syscalls[code].sc_name = "pwrite"; - bsd_syscalls[code].sc_format = FMT_PREAD; - break; - - case BSC_mkdir: - bsd_syscalls[code].sc_name = "mkdir"; - break; - - case BSC_mkdir_extended: - bsd_syscalls[code].sc_name = "mkdir_extended"; - break; - - case BSC_mkfifo: - bsd_syscalls[code].sc_name = "mkfifo"; - break; - - case BSC_mkfifo_extended: - bsd_syscalls[code].sc_name = "mkfifo_extended"; - break; - - case BSC_rmdir: - bsd_syscalls[code].sc_name = "rmdir"; - break; - - case BSC_statfs: - bsd_syscalls[code].sc_name = "statfs"; - break; - - case BSC_statfs64: - bsd_syscalls[code].sc_name = "statfs64"; - break; - - case BSC_getfsstat: - bsd_syscalls[code].sc_name = "getfsstat"; - break; - - case BSC_getfsstat64: - bsd_syscalls[code].sc_name = "getfsstat64"; - break; - - case BSC_fstatfs: - bsd_syscalls[code].sc_name = "fstatfs"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fstatfs64: - bsd_syscalls[code].sc_name = "fstatfs64"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_pathconf: - bsd_syscalls[code].sc_name = "pathconf"; - break; - - case BSC_fpathconf: - bsd_syscalls[code].sc_name = "fpathconf"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_getdirentries: - bsd_syscalls[code].sc_name = "getdirentries"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_getdirentries64: - bsd_syscalls[code].sc_name = "getdirentries64"; - bsd_syscalls[code].sc_format = FMT_FD_IO; - break; - - case BSC_lseek: - bsd_syscalls[code].sc_name = "lseek"; - bsd_syscalls[code].sc_format = FMT_LSEEK; - break; - - case BSC_truncate: - bsd_syscalls[code].sc_name = "truncate"; - bsd_syscalls[code].sc_format = FMT_TRUNC; - break; - - case BSC_ftruncate: - bsd_syscalls[code].sc_name = "ftruncate"; - bsd_syscalls[code].sc_format = FMT_FTRUNC; - break; - - case BSC_flock: - bsd_syscalls[code].sc_name = "flock"; - bsd_syscalls[code].sc_format = FMT_FLOCK; - break; - - case BSC_getattrlist: - bsd_syscalls[code].sc_name = "getattrlist"; - break; - - case BSC_setattrlist: - bsd_syscalls[code].sc_name = "setattrlist"; - break; - - case BSC_fgetattrlist: - bsd_syscalls[code].sc_name = "fgetattrlist"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_fsetattrlist: - bsd_syscalls[code].sc_name = "fsetattrlist"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_getdirentriesattr: - bsd_syscalls[code].sc_name = "getdirentriesattr"; - bsd_syscalls[code].sc_format = FMT_FD; - break; - - case BSC_exchangedata: - bsd_syscalls[code].sc_name = "exchangedata"; - break; - - case BSC_rename: - bsd_syscalls[code].sc_name = "rename"; - break; - - case BSC_copyfile: - bsd_syscalls[code].sc_name = "copyfile"; - break; - - case BSC_checkuseraccess: - bsd_syscalls[code].sc_name = "checkuseraccess"; - break; - - case BSC_searchfs: - bsd_syscalls[code].sc_name = "searchfs"; - break; - - case BSC_aio_fsync: - bsd_syscalls[code].sc_name = "aio_fsync"; - bsd_syscalls[code].sc_format = FMT_AIO_FSYNC; - break; - - case BSC_aio_return: - bsd_syscalls[code].sc_name = "aio_return"; - bsd_syscalls[code].sc_format = FMT_AIO_RETURN; - break; - - case BSC_aio_suspend: - case BSC_aio_suspend_nocancel: - bsd_syscalls[code].sc_name = "aio_suspend"; - bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND; - break; - - case BSC_aio_cancel: - bsd_syscalls[code].sc_name = "aio_cancel"; - bsd_syscalls[code].sc_format = FMT_AIO_CANCEL; - break; - - case BSC_aio_error: - bsd_syscalls[code].sc_name = "aio_error"; - bsd_syscalls[code].sc_format = FMT_AIO; - break; - - case BSC_aio_read: - bsd_syscalls[code].sc_name = "aio_read"; - bsd_syscalls[code].sc_format = FMT_AIO; - break; - - case BSC_aio_write: - bsd_syscalls[code].sc_name = "aio_write"; - bsd_syscalls[code].sc_format = FMT_AIO; - break; - - case BSC_lio_listio: - bsd_syscalls[code].sc_name = "lio_listio"; - bsd_syscalls[code].sc_format = FMT_LIO_LISTIO; - break; - - case BSC_msync: - case BSC_msync_nocancel: - bsd_syscalls[code].sc_name = "msync"; - bsd_syscalls[code].sc_format = FMT_MSYNC; - break; - - case BSC_fcntl: - case BSC_fcntl_nocancel: - bsd_syscalls[code].sc_name = "fcntl"; - bsd_syscalls[code].sc_format = FMT_FCNTL; - break; - - case BSC_ioctl: - bsd_syscalls[code].sc_name = "ioctl"; - bsd_syscalls[code].sc_format = FMT_IOCTL; - break; - - case BSC_fsgetpath: - bsd_syscalls[code].sc_name = "fsgetpath"; - break; - - case BSC_getattrlistbulk: - bsd_syscalls[code].sc_name = "getattrlistbulk"; - break; - - case BSC_openat: - bsd_syscalls[code].sc_name = "openat"; - bsd_syscalls[code].sc_format = FMT_OPENAT; - break; - - case BSC_openat_nocancel: - bsd_syscalls[code].sc_name = "openat_nocanel"; - bsd_syscalls[code].sc_format = FMT_OPENAT; - break; - - case BSC_renameat: - bsd_syscalls[code].sc_name = "renameat"; - bsd_syscalls[code].sc_format = FMT_RENAMEAT; - break; - - case BSC_chmodat: - bsd_syscalls[code].sc_name = "chmodat"; - bsd_syscalls[code].sc_format = FMT_CHMODAT; - break; - - case BSC_chownat: - bsd_syscalls[code].sc_name = "chownat"; - bsd_syscalls[code].sc_format = FMT_AT; - break; - - case BSC_fstatat: - bsd_syscalls[code].sc_name = "fstatat"; - bsd_syscalls[code].sc_format = FMT_AT; - break; - - case BSC_fstatat64: - bsd_syscalls[code].sc_name = "fstatat64"; - bsd_syscalls[code].sc_format = FMT_AT; - break; - - case BSC_linkat: - bsd_syscalls[code].sc_name = "linkat"; - bsd_syscalls[code].sc_format = FMT_AT; break; - - case BSC_unlinkat: - bsd_syscalls[code].sc_name = "unlinkat"; - bsd_syscalls[code].sc_format = FMT_AT; - break; - - case BSC_readlinkat: - bsd_syscalls[code].sc_name = "readlinkat"; - bsd_syscalls[code].sc_format = FMT_AT; - break; - - case BSC_symlinkat: - bsd_syscalls[code].sc_name = "symlinkat"; - bsd_syscalls[code].sc_format = FMT_AT; + + case 'R': + RAW_flag = true; + rv = ktrace_set_file(s, optarg); + if (rv) { + fprintf(stderr, "ERROR: reading trace from '%s' failed (%s)\n", optarg, strerror(errno)); + exit(1); + } break; - - case BSC_mkdirat: - bsd_syscalls[code].sc_name = "mkdirat"; - bsd_syscalls[code].sc_format = FMT_AT; + + case 'S': + start_time_ns = NSEC_PER_SEC * atof(optarg); break; - - case BSC_getattrlistat: - bsd_syscalls[code].sc_name = "getattrlistat"; - bsd_syscalls[code].sc_format = FMT_AT; + + case 'E': + end_time_ns = NSEC_PER_SEC * atof(optarg); break; + + default: + exit_usage(); } } - for (i = 0; (type = filemgr_call_types[i]); i++) { - char * p; + argc -= optind; + argv += optind; - code = filemgr_index(type); - - if (code >= MAX_FILEMGR) { - printf("FILEMGR call init (%x): type exceeds table size\n", type); - continue; + if (time_limit > 0.0) { + if (RAW_flag) { + fprintf(stderr, "NOTE: time limit ignored when a raw file is specified\n"); + } else { + stop_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + dispatch_source_set_timer(stop_timer, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * time_limit), DISPATCH_TIME_FOREVER, 0); + dispatch_source_set_event_handler(stop_timer, ^{ + ktrace_end(s, 0); + }); + dispatch_resume(stop_timer); } - switch (type) { + } - case FILEMGR_PBGETCATALOGINFO: - p = "GetCatalogInfo"; - break; + if (!RAW_flag) { + if (geteuid() != 0) { + fprintf(stderr, "'fs_usage' must be run as root...\n"); + exit(1); + } - case FILEMGR_PBGETCATALOGINFOBULK: - p = "GetCatalogInfoBulk"; - break; + /* + * ktrace can't both *in*clude and *ex*clude pids, so: if we are + * already excluding pids, or if we are not explicitly including + * or excluding any pids, then exclude the defaults. + * + * if on the other hand we are explicitly including pids, we'll + * filter the defaults out naturally. + */ + if (exclude_pids || argc == 0) { + ktrace_exclude_process(s, "fs_usage"); + ktrace_exclude_process(s, "Terminal"); + ktrace_exclude_process(s, "telnetd"); + ktrace_exclude_process(s, "telnet"); + ktrace_exclude_process(s, "sshd"); + ktrace_exclude_process(s, "rlogind"); + ktrace_exclude_process(s, "tcsh"); + ktrace_exclude_process(s, "csh"); + ktrace_exclude_process(s, "sh"); + ktrace_exclude_process(s, "zsh"); +#if TARGET_OS_EMBEDDED + ktrace_exclude_process(s, "dropbear"); +#endif /* TARGET_OS_EMBEDDED */ + } + } - case FILEMGR_PBCREATEFILEUNICODE: - p = "CreateFileUnicode"; - break; + /* + * If we're *in*cluding processes, also *in*clude the kernel_task, which + * issues trace points when disk I/Os complete. But set a flag for us to + * avoid showing events attributed to the kernel_task. + * + * If the user actually wants to those events, we'll change that flag in + * the loop below. + */ + if (argc > 0 && !exclude_pids) { + ktrace_filter_pid(s, 0); + want_kernel_task = false; + } - case FILEMGR_PBCREATEDIRECTORYUNICODE: - p = "CreateDirectoryUnicode"; - break; + /* + * Process the list of specified pids, and in/exclude them as + * appropriate. + */ + while (argc > 0) { + pid_t pid; + char *name; + char *endptr; - case FILEMGR_PBCREATEFORK: - p = "PBCreateFork"; - break; + name = argv[0]; + pid = (pid_t)strtoul(name, &endptr, 10); - case FILEMGR_PBDELETEFORK: - p = "PBDeleteFork"; - break; + if (*name != '\0' && *endptr == '\0') { + if (exclude_pids) { + rv = ktrace_exclude_pid(s, pid); + } else { + if (pid == 0) + want_kernel_task = true; + else + rv = ktrace_filter_pid(s, pid); + } + } else { + if (exclude_pids) { + rv = ktrace_exclude_process(s, name); + } else { + if (!strcmp(name, "kernel_task")) + want_kernel_task = true; + else + rv = ktrace_filter_process(s, name); + } + } - case FILEMGR_PBITERATEFORK: - p = "PBIterateFork"; - break; + if (rv == EINVAL) { + fprintf(stderr, "ERROR: cannot both include and exclude simultaneously\n"); + exit(1); + } else { + assert(!rv); + } - case FILEMGR_PBOPENFORK: - p = "PBOpenFork"; - break; + argc--; + argv++; + } - case FILEMGR_PBREADFORK: - p = "PBReadFork"; - break; + /* provides SIGINT, SIGHUP, SIGPIPE, SIGTERM handlers */ + ktrace_set_signal_handler(s); - case FILEMGR_PBWRITEFORK: - p = "PBWriteFork"; - break; + ktrace_set_completion_handler(s, ^{ + exit(0); + }); - case FILEMGR_PBALLOCATEFORK: - p = "PBAllocateFork"; - break; + signal(SIGWINCH, SIG_IGN); + sigwinch_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGWINCH, 0, dispatch_get_main_queue()); + dispatch_source_set_event_handler(sigwinch_source, ^{ + if (!wideflag) + get_screenwidth(); + }); + dispatch_resume(sigwinch_source); - case FILEMGR_PBDELETEOBJECT: - p = "PBDeleteObject"; - break; + init_shared_cache_mapping(); - case FILEMGR_PBEXCHANGEOBJECT: - p = "PBExchangeObject"; - break; + cache_disk_names(); - case FILEMGR_PBGETFORKCBINFO: - p = "PBGetForkCBInfo"; - break; + setup_ktrace_callbacks(); - case FILEMGR_PBGETVOLUMEINFO: - p = "PBGetVolumeInfo"; - break; - - case FILEMGR_PBMAKEFSREF: - p = "PBMakeFSRef"; - break; + ktrace_set_dropped_events_handler(s, ^{ + fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly\n"); - case FILEMGR_PBMAKEFSREFUNICODE: - p = "PBMakeFSRefUnicode"; - break; + /* clear any state that is now potentially invalid */ - case FILEMGR_PBMOVEOBJECT: - p = "PBMoveObject"; - break; + event_delete_all(); + fd_clear_all(); + meta_delete_all(); + }); - case FILEMGR_PBOPENITERATOR: - p = "PBOpenIterator"; - break; + ktrace_set_default_event_names_enabled(KTRACE_FEATURE_DISABLED); + ktrace_set_execnames_enabled(s, KTRACE_FEATURE_LAZY); + ktrace_set_vnode_paths_enabled(s, true); - case FILEMGR_PBRENAMEUNICODE: - p = "PBRenameUnicode"; - break; + rv = ktrace_start(s, dispatch_get_main_queue()); - case FILEMGR_PBSETCATALOGINFO: - p = "SetCatalogInfo"; - break; + if (rv) { + perror("ktrace_start"); + exit(1); + } - case FILEMGR_PBSETVOLUMEINFO: - p = "SetVolumeInfo"; - break; + dispatch_main(); - case FILEMGR_FSREFMAKEPATH: - p = "FSRefMakePath"; - break; + return 0; +} - case FILEMGR_FSPATHMAKEREF: - p = "FSPathMakeRef"; - break; +void +setup_ktrace_callbacks(void) +{ + ktrace_events_subclass(s, DBG_MACH, DBG_MACH_EXCP_SC, ^(ktrace_event_t event) { + int type; - case FILEMGR_PBGETCATINFO: - p = "GetCatInfo"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBGETCATINFOLITE: - p = "GetCatInfoLite"; - break; + if (type == MSC_map_fd) { + if (event->debugid & DBG_FUNC_START) { + event_enter(type, event); + } else { + event_exit("map_fd", type, event, FMT_FD); + } + } + }); - case FILEMGR_PBHGETFINFO: - p = "PBHGetFInfo"; - break; + ktrace_events_subclass(s, DBG_MACH, DBG_MACH_VM, ^(ktrace_event_t event) { + th_info_t ti; + unsigned int type; - case FILEMGR_PBXGETVOLINFO: - p = "PBXGetVolInfo"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBHCREATE: - p = "PBHCreate"; - break; + if (type != MACH_pageout && type != MACH_vmfault) + return; - case FILEMGR_PBHOPENDF: - p = "PBHOpenDF"; - break; + if (event->debugid & DBG_FUNC_START) { + event_enter(type, event); + } else { + switch (type) { + case MACH_pageout: + if (event->arg2) + event_exit("PAGE_OUT_ANON", type, event, FMT_PGOUT); + else + event_exit("PAGE_OUT_FILE", type, event, FMT_PGOUT); + + break; + + case MACH_vmfault: + if (event->arg4 == DBG_PAGEIN_FAULT) + event_exit("PAGE_IN", type, event, FMT_PGIN); + else if (event->arg4 == DBG_PAGEINV_FAULT) + event_exit("PAGE_IN_FILE", type, event, FMT_PGIN); + else if (event->arg4 == DBG_PAGEIND_FAULT) + event_exit("PAGE_IN_ANON", type, event, FMT_PGIN); + else if (event->arg4 == DBG_CACHE_HIT_FAULT) + event_exit("CACHE_HIT", type, event, FMT_CACHEHIT); + else if ((ti = event_find(event->threadid, type))) + event_delete(ti); + + break; + + default: + abort(); + } + } + }); - case FILEMGR_PBHOPENRF: - p = "PBHOpenRF"; - break; + if (include_waited_flag || RAW_flag) { + ktrace_events_subclass(s, DBG_MACH, DBG_MACH_SCHED, ^(ktrace_event_t event) { + int type; - case FILEMGR_PBHGETDIRACCESS: - p = "PBHGetDirAccess"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBHSETDIRACCESS: - p = "PBHSetDirAccess"; - break; + switch (type) { + case MACH_idle: + case MACH_sched: + case MACH_stkhandoff: + event_mark_thread_waited(event->threadid); + } + }); + } - case FILEMGR_PBHMAPID: - p = "PBHMapID"; - break; + ktrace_events_subclass(s, DBG_FSYSTEM, DBG_FSRW, ^(ktrace_event_t event) { + th_info_t ti; + int type; - case FILEMGR_PBHMAPNAME: - p = "PBHMapName"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBCLOSE: - p = "PBClose"; - break; + switch (type) { + case HFS_modify_block_end: + /* + * the expected path here is as follows: + * enter syscall + * look up a path, which gets stored in ti->vnode / ti->pathname + * modify a metadata block -- we assume the modification has something to do with the path that was looked up + * leave syscall + * ... + * later, someone writes that metadata block; the last path associated with it is attributed + */ + if ((ti = event_find(event->threadid, 0))) { + if (ti->newest_pathname) + meta_add_name(event->arg2, ti->newest_pathname); + } - case FILEMGR_PBFLUSHFILE: - p = "PBFlushFile"; - break; + break; - case FILEMGR_PBGETEOF: - p = "PBGetEOF"; - break; + case VFS_LOOKUP: + if (event->debugid & DBG_FUNC_START) { + if ((ti = event_find(event->threadid, 0)) && !ti->vnodeid) { + ti->vnodeid = event->arg1; + } + } - case FILEMGR_PBSETEOF: - p = "PBSetEOF"; - break; + /* it can be both start and end */ - case FILEMGR_PBGETFPOS: - p = "PBGetFPos"; - break; + if (event->debugid & DBG_FUNC_END) { + if ((ti = event_find(event->threadid, 0)) && ti->vnodeid) { + const char *pathname; - case FILEMGR_PBREAD: - p = "PBRead"; - break; + pathname = ktrace_get_path_for_vp(s, ti->vnodeid); - case FILEMGR_PBWRITE: - p = "PBWrite"; - break; + ti->vnodeid = 0; - case FILEMGR_PBGETFCBINFO: - p = "PBGetFCBInfo"; - break; + if (pathname) { + if (ti->pathname[0] == '\0') { + strncpy(ti->pathname, pathname, MAXPATHLEN); + ti->newest_pathname = ti->pathname; + } else if (ti->pathname2[0] == '\0') { + strncpy(ti->pathname2, pathname, MAXPATHLEN); + ti->newest_pathname = ti->pathname2; + } + } + } + } - case FILEMGR_PBSETFINFO: - p = "PBSetFInfo"; - break; - - case FILEMGR_PBALLOCATE: - p = "PBAllocate"; - break; + break; + } - case FILEMGR_PBALLOCCONTIG: - p = "PBAllocContig"; - break; + if (type != Throttled && type != HFS_update) + return; - case FILEMGR_PBSETFPOS: - p = "PBSetFPos"; - break; + if (event->debugid & DBG_FUNC_START) { + event_enter(type, event); + } else { + switch (type) { + case Throttled: + event_exit(" THROTTLED", type, event, FMT_NOTHING); + break; - case FILEMGR_PBSETCATINFO: - p = "PBSetCatInfo"; - break; + case HFS_update: + event_exit(" HFS_update", type, event, FMT_HFS_update); + break; - case FILEMGR_PBGETVOLPARMS: - p = "PBGetVolParms"; - break; + default: + abort(); + } + } + }); - case FILEMGR_PBSETVINFO: - p = "PBSetVInfo"; - break; + ktrace_events_subclass(s, DBG_FSYSTEM, DBG_DKRW, ^(ktrace_event_t event) { + struct diskio *dio; + unsigned int type; - case FILEMGR_PBMAKEFSSPEC: - p = "PBMakeFSSpec"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBHGETVINFO: - p = "PBHGetVInfo"; - break; + if ((type & P_DISKIO_MASK) == P_DISKIO) { + diskio_start(type, event->arg1, event->arg2, event->arg3, event->arg4, event); + } else if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) { + if ((dio = diskio_complete(event->arg1, event->arg4, event->arg3, event->threadid, event->timestamp, event->walltime))) { + dio->vnodeid = event->arg2; + diskio_print(dio); + diskio_free(dio); + } + } + }); - case FILEMGR_PBCREATEFILEIDREF: - p = "PBCreateFileIDRef"; - break; + ktrace_events_subclass(s, DBG_FSYSTEM, DBG_IOCTL, ^(ktrace_event_t event) { + th_info_t ti; + int type; + pid_t pid; - case FILEMGR_PBDELETEFILEIDREF: - p = "PBDeleteFileIDRef"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBRESOLVEFILEIDREF: - p = "PBResolveFileIDRef"; - break; + switch (type) { + case SPEC_unmap_info: + pid = ktrace_get_pid_for_thread(s, event->threadid); - case FILEMGR_PBFLUSHVOL: - p = "PBFlushVol"; - break; + if (check_filter_mode(pid, NULL, SPEC_unmap_info, 0, 0, "SPEC_unmap_info")) + format_print(NULL, " TrimExtent", event, type, FMT_UNMAP_INFO, event->timestamp, event->timestamp, 0, "", NULL); - case FILEMGR_PBHRENAME: - p = "PBHRename"; - break; + break; - case FILEMGR_PBCATMOVE: - p = "PBCatMove"; - break; + case SPEC_ioctl: + if (event->debugid & DBG_FUNC_START) { + event_enter(type, event); + } else { + if (event->arg2 == DKIOCSYNCHRONIZECACHE) + event_exit("IOCTL", type, event, FMT_IOCTL_SYNCCACHE); + else if (event->arg2 == DKIOCUNMAP) + event_exit("IOCTL", type, event, FMT_IOCTL_UNMAP); + else if (event->arg2 == DKIOCSYNCHRONIZE && (event->debugid & DBG_FUNC_ALL) == DBG_FUNC_NONE) + event_exit("IOCTL", type, event, FMT_IOCTL_SYNC); + else if ((ti = event_find(event->threadid, type))) + event_delete(ti); + } - case FILEMGR_PBEXCHANGEFILES: - p = "PBExchangeFiles"; - break; + break; + } + }); + + if (BC_flag || RAW_flag) { + ktrace_events_subclass(s, DBG_FSYSTEM, DBG_BOOTCACHE, ^(ktrace_event_t event) { + struct diskio *dio; + unsigned int type; + + type = event->debugid & KDBG_EVENTID_MASK; + + switch (type) { + case BC_IO_HIT: + case BC_IO_HIT_STALLED: + case BC_IO_MISS: + case BC_IO_MISS_CUT_THROUGH: + case BC_PLAYBACK_IO: + if ((dio = diskio_find(event->arg1)) != NULL) + dio->bc_info = type; + } + }); + } - case FILEMGR_PBHDELETE: - p = "PBHDelete"; - break; + void (^bsd_sc_proc_cb)(ktrace_event_t event) = ^(ktrace_event_t event) { + int type, index; + pid_t pid; - case FILEMGR_PBDIRCREATE: - p = "PBDirCreate"; - break; + type = event->debugid & KDBG_EVENTID_MASK; - case FILEMGR_PBCATSEARCH: - p = "PBCatSearch"; - break; + switch (type) { + case BSC_exit: /* see below */ + return; - case FILEMGR_PBHSETFLOCK: - p = "PBHSetFlock"; - break; + case proc_exit: + event->arg1 = event->arg2 >> 8; + type = BSC_exit; - case FILEMGR_PBHRSTFLOCK: - p = "PBHRstFLock"; - break; + pid = ktrace_get_pid_for_thread(s, event->threadid); + fd_clear_pid(pid); - case FILEMGR_PBLOCKRANGE: - p = "PBLockRange"; - break; + break; - case FILEMGR_PBUNLOCKRANGE: - p = "PBUnlockRange"; - break; + case BSC_mmap: + if (event->arg4 & MAP_ANON) + return; - default: - p = NULL; - break; + break; } - filemgr_calls[code].fm_name = p; - } -} + if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL) + return; + if (!bsd_syscalls[index].sc_name) + return; -int -main(argc, argv) - int argc; - char *argv[]; -{ - char *myname = "fs_usage"; - int i; - char ch; + if (event->debugid & DBG_FUNC_START) { + event_enter(type, event); + } else { + event_exit(bsd_syscalls[index].sc_name, type, event, bsd_syscalls[index].sc_format); + } + }; + + ktrace_events_subclass(s, DBG_BSD, DBG_BSD_EXCP_SC, bsd_sc_proc_cb); + ktrace_events_subclass(s, DBG_BSD, DBG_BSD_PROC, bsd_sc_proc_cb); + + ktrace_events_range(s, KDBG_EVENTID(DBG_BSD, DBG_BSD_SC_EXTENDED_INFO, 0), KDBG_EVENTID(DBG_BSD, DBG_BSD_SC_EXTENDED_INFO2 + 1, 0), ^(ktrace_event_t event) { + extend_syscall(event->threadid, event->debugid & KDBG_EVENTID_MASK, event); + }); + + ktrace_events_subclass(s, DBG_CORESTORAGE, DBG_CS_IO, ^(ktrace_event_t event) { + // the usual DBG_FUNC_START/END does not work for i/o since it will + // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit + // instead. the trace command doesn't know how handle either method + // (unmatched start/end or 0x4) but works a little better this way. + + struct diskio *dio; + int cs_type = event->debugid & P_CS_Type_Mask; // strip out the done bit + bool start = (event->debugid & P_CS_IO_Done) != P_CS_IO_Done; + + switch (cs_type) { + case P_CS_ReadChunk: + case P_CS_WriteChunk: + case P_CS_MetaRead: + case P_CS_MetaWrite: + if (start) { + diskio_start(cs_type, event->arg2, event->arg1, event->arg3, event->arg4, event); + } else { + if ((dio = diskio_complete(event->arg2, event->arg4, event->arg3, event->threadid, event->timestamp, event->walltime))) { + diskio_print(dio); + diskio_free(dio); + } + } - time_t stop_at_time = 0; + break; + case P_CS_TransformRead: + case P_CS_TransformWrite: + case P_CS_MigrationRead: + case P_CS_MigrationWrite: + if (start) { + diskio_start(cs_type, event->arg2, CS_DEV, event->arg3, event->arg4, event); + } else { + if ((dio = diskio_complete(event->arg2, event->arg4, event->arg3, event->threadid, event->timestamp, event->walltime))) { + diskio_print(dio); + diskio_free(dio); + } + } - if (0 != reexec_to_match_kernel()) { - fprintf(stderr, "Could not re-execute: %d\n", errno); - exit(1); - } - get_screenwidth(); + break; + } + }); - /* - * get our name - */ - if (argc > 0) { - if ((myname = rindex(argv[0], '/')) == 0) - myname = argv[0]; - else - myname++; - } - - while ((ch = getopt(argc, argv, "bewf:R:S:E:t:W")) != EOF) { + ktrace_events_subclass(s, DBG_CORESTORAGE, 1 /* DBG_CS_SYNC */, ^(ktrace_event_t event) { + int cs_type = event->debugid & P_CS_Type_Mask; // strip out the done bit + bool start = (event->debugid & P_CS_IO_Done) != P_CS_IO_Done; + + if (cs_type == P_CS_SYNC_DISK) { + if (start) { + event_enter(cs_type, event); + } else { + event_exit(" SyncCacheCS", cs_type, event, FMT_SYNC_DISK_CS); + } + } + }); +} - switch(ch) { +/* + * Handle system call extended trace data. + * pread and pwrite: + * Wipe out the kd args that were collected upon syscall_entry + * because it is the extended info that we really want, and it + * is all we really need. + */ +void +extend_syscall(uintptr_t thread, int type, ktrace_event_t event) +{ + th_info_t ti; - case 'e': - exclude_pids = 1; - exclude_default_pids = 0; - break; + switch (type) { + case BSC_mmap_extended: + if ((ti = event_find(thread, BSC_mmap)) == NULL) + return; - case 'w': - wideflag = 1; - if ((uint)columns < MAX_WIDE_MODE_COLS) - columns = MAX_WIDE_MODE_COLS; - break; + ti->arg8 = ti->arg3; /* save protection */ + ti->arg1 = event->arg1; /* the fd */ + ti->arg3 = event->arg2; /* bottom half address */ + ti->arg5 = event->arg3; /* bottom half size */ + break; - case 'W': - include_waited_flag = 1; - break; + case BSC_mmap_extended2: + if ((ti = event_find(thread, BSC_mmap)) == NULL) + return; - case 'f': - if (!strcmp(optarg, "network")) - filter_mode |= NETWORK_FILTER; - else if (!strcmp(optarg, "filesys")) - filter_mode |= FILESYS_FILTER; - else if (!strcmp(optarg, "cachehit")) - show_cachehits = TRUE; - else if (!strcmp(optarg, "exec")) - filter_mode |= EXEC_FILTER; - else if (!strcmp(optarg, "pathname")) - filter_mode |= PATHNAME_FILTER; - else if (!strcmp(optarg, "diskio")) - filter_mode |= DISKIO_FILTER; - break; - - case 'b': - BC_flag = 1; + ti->arg2 = event->arg1; /* top half address */ + ti->arg4 = event->arg2; /* top half size */ + ti->arg6 = event->arg3; /* top half file offset */ + ti->arg7 = event->arg4; /* bottom half file offset */ break; - case 't': - stop_at_time = time(NULL) + strtoul(optarg, NULL, 10); + case BSC_msync_extended: + if ((ti = event_find(thread, BSC_msync)) == NULL) { + if ((ti = event_find(thread, BSC_msync_nocancel)) == NULL) + return; + } + + ti->arg4 = event->arg1; /* top half address */ + ti->arg5 = event->arg2; /* top half size */ break; - case 'R': - RAW_flag = 1; - RAW_file = optarg; - break; - - case 'S': - start_time = atof(optarg); - break; - - case 'E': - end_time = atof(optarg); - break; - - default: - exit_usage(myname); - } - } - if (!RAW_flag) { - if ( geteuid() != 0 ) { - fprintf(stderr, "'fs_usage' must be run as root...\n"); - exit(1); - } - } - argc -= optind; - argv += optind; + case BSC_pread_extended: + if ((ti = event_find(thread, BSC_pread)) == NULL) { + if ((ti = event_find(thread, BSC_pread_nocancel)) == NULL) + return; + } - /* - * when excluding, fs_usage should be the first in line for pids[] - * - * the !exclude_pids && argc == 0 catches the exclude_default_pids - * case below where exclude_pids is later set and the fs_usage PID - * needs to make it into pids[] - */ - if (exclude_pids || (!exclude_pids && argc == 0)) { - if (num_of_pids < (MAX_PIDS - 1)) - pids[num_of_pids++] = getpid(); - } + ti->arg1 = event->arg1; /* the fd */ + ti->arg2 = event->arg2; /* nbytes */ + ti->arg3 = event->arg3; /* top half offset */ + ti->arg4 = event->arg4; /* bottom half offset */ + break; - /* - * If we process any list of pids/cmds, then turn off the defaults - */ - if (argc > 0) - exclude_default_pids = 0; + case BSC_pwrite_extended: + if ((ti = event_find(thread, BSC_pwrite)) == NULL) { + if ((ti = event_find(thread, BSC_pwrite_nocancel)) == NULL) + return; + } - while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) { - select_pid_mode++; - argtopid(argv[0]); - argc--; - argv++; - } - /* - * Exclude a set of default pids - */ - if (exclude_default_pids) { - argtopid("Terminal"); - argtopid("telnetd"); - argtopid("telnet"); - argtopid("sshd"); - argtopid("rlogind"); - argtopid("tcsh"); - argtopid("csh"); - argtopid("sh"); - exclude_pids = 1; - } -#if 0 - for (i = 0; i < num_of_pids; i++) { - if (exclude_pids) - fprintf(stderr, "exclude pid %d\n", pids[i]); - else - fprintf(stderr, "pid %d\n", pids[i]); + ti->arg1 = event->arg1; /* the fd */ + ti->arg2 = event->arg2; /* nbytes */ + ti->arg3 = event->arg3; /* top half offset */ + ti->arg4 = event->arg4; /* bottom half offset */ + break; } -#endif - if (!RAW_flag) { - struct sigaction osa; - int num_cpus; - size_t len; +} - /* set up signal handlers */ - signal(SIGINT, leave); - signal(SIGQUIT, leave); - signal(SIGPIPE, leave); +#pragma mark printing routines - sigaction(SIGHUP, (struct sigaction *)NULL, &osa); +static void +get_mode_nibble(char *buf, unsigned long smode, unsigned long special, char x_on, char x_off) +{ + if (smode & 04) + buf[0] = 'r'; - if (osa.sa_handler == SIG_DFL) - signal(SIGHUP, leave); - signal(SIGTERM, leave); - /* - * grab the number of cpus - */ - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - mib[2] = 0; - len = sizeof(num_cpus); + if (smode & 02) + buf[1] = 'w'; - sysctl(mib, 2, &num_cpus, &len, NULL, 0); - num_events = EVENT_BASE * num_cpus; + if (smode & 01) { + if (special) + buf[2] = x_on; + else + buf[2] = 'x'; + } else { + if (special) + buf[2] = x_off; } - signal(SIGWINCH, sigwinch); +} + +static void +get_mode_string(unsigned long mode, char *buf) +{ + memset(buf, '-', 9); + buf[9] = '\0'; - if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0) - quit("can't allocate memory for tracing info\n"); + get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T'); + get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S'); + get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S'); +} - ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386"); +static int +clip_64bit(char *s, uint64_t value) +{ + int clen = 0; - 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"); - } + if ( (value & 0xff00000000000000LL) ) + clen = printf("%s0x%16.16qx", s, value); + else if ( (value & 0x00ff000000000000LL) ) + clen = printf("%s0x%14.14qx ", s, value); + else if ( (value & 0x0000ff0000000000LL) ) + clen = printf("%s0x%12.12qx ", s, value); + else if ( (value & 0x000000ff00000000LL) ) + clen = printf("%s0x%10.10qx ", s, value); + else + clen = printf("%s0x%8.8qx ", s, value); - SortFrameworkAddresses(); + return clen; +} - cache_disk_names(); +/* + * ret = 1 means print the entry + * ret = 0 means don't print the entry + */ - if (!RAW_flag) { +/* + * meaning of filter flags: + * cachehit turn on display of CACHE_HIT events (which are filtered out by default) + * + * exec show exec/posix_spawn + * pathname show events with a pathname and close() + * diskio show disk I/Os + * filesys show filesystem events + * network show network events + * + * filters may be combined; default is all filters on (except cachehit) + */ +bool +check_filter_mode(pid_t pid, th_info_t ti, unsigned long type, int error, int retval, char *sc_name) +{ + bool ret = false; + int network_fd_isset = 0; + unsigned long fd; - set_remove(); - set_numbufs(num_events); - set_init(); + /* cachehit is special -- it's not on by default */ + if (sc_name[0] == 'C' && !strcmp(sc_name, "CACHE_HIT")) { + return show_cachehits; + } - if (exclude_pids == 0) { - for (i = 0; i < num_of_pids; i++) - set_pidcheck(pids[i], 1); - } else { - for (i = 0; i < num_of_pids; i++) - set_pidexclude(pids[i], 1); - } - if (select_pid_mode && !one_good_pid) { - /* - * An attempt to restrict output to a given - * pid or command has failed. Exit gracefully - */ - set_remove(); - exit_usage(myname); - } + if (filter_mode == DEFAULT_DO_NOT_FILTER) + return true; - set_filter(); + if (filter_mode & DISKIO_FILTER) { + if ((type & P_DISKIO_MASK) == P_DISKIO) + return true; - set_enable(1); + if (type == Throttled) + return true; + } - init_arguments_buffer(); + if (filter_mode & EXEC_FILTER) { + if (type == BSC_execve || type == BSC_posix_spawn) + return true; } - getdivisor(); - init_tables(); + if (filter_mode & PATHNAME_FILTER) { + if (ti && ti->pathname[0]) + return true; - /* - * main loop - */ - while (stop_at_time == 0 || last_time < stop_at_time) { - if (!RAW_flag) - usleep(1000 * usleep_ms); + if (type == BSC_close || type == BSC_close_nocancel || + type == BSC_guarded_close_np) + return true; + } - sample_sc(); + if (!ti) { + if (filter_mode & FILESYS_FILTER) + return true; - last_time = time((long *)0); + return 0; } -} - -void -find_proc_names() -{ - size_t bufSize = 0; - struct kinfo_proc *kp; + switch (type) { + case BSC_close: + case BSC_close_nocancel: + case BSC_guarded_close_np: + fd = ti->arg1; + network_fd_isset = fd_is_network(pid, fd); + + if (error == 0) + fd_set_is_network(pid, fd, false); + + if (network_fd_isset) { + if (filter_mode & NETWORK_FILTER) + ret = true; + } else { + if (filter_mode & FILESYS_FILTER) + ret = true; + } - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ALL; - mib[3] = 0; + break; - if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) - quit("trace facility failure, KERN_PROC_ALL\n"); + case BSC_read: + case BSC_write: + case BSC_read_nocancel: + case BSC_write_nocancel: + /* + * we don't care about error in these cases + */ + fd = ti->arg1; - if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0) - quit("can't allocate memory for proc buffer\n"); - - if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0) - quit("trace facility failure, KERN_PROC_ALL\n"); + if (fd_is_network(pid, fd)) { + if (filter_mode & NETWORK_FILTER) + ret = true; + } else if (filter_mode & FILESYS_FILTER) { + ret = true; + } - kp_nentries = bufSize/ sizeof(struct kinfo_proc); - kp_buffer = kp; -} + break; + case BSC_accept: + case BSC_accept_nocancel: + case BSC_socket: + fd = retval; -void -set_enable(int val) -{ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDENABLE; /* protocol */ - mib[3] = val; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDENABLE\n"); - - if (val) - trace_enabled = 1; - else - trace_enabled = 0; -} + if (error == 0) + fd_set_is_network(pid, fd, true); -void -set_numbufs(int nbufs) -{ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETBUF; - mib[3] = nbufs; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETBUF\n"); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETUP\n"); -} + if (filter_mode & NETWORK_FILTER) + ret = true; -#define ENCODE_CSC_LOW(class, subclass) \ - ( (uint16_t) ( ((class) & 0xff) << 8 ) | ((subclass) & 0xff) ) + break; -void -set_filter(void) -{ - uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE]; - bzero(type_filter_bitmap, sizeof(type_filter_bitmap)); + case BSC_recvfrom: + case BSC_sendto: + case BSC_recvmsg: + case BSC_sendmsg: + case BSC_connect: + case BSC_bind: + case BSC_listen: + case BSC_sendto_nocancel: + case BSC_recvfrom_nocancel: + case BSC_recvmsg_nocancel: + case BSC_sendmsg_nocancel: + case BSC_connect_nocancel: + fd = ti->arg1; + + if (error == 0) + fd_set_is_network(pid, fd, true); + + if (filter_mode & NETWORK_FILTER) + ret = true; - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_DATA)); - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_STRING)); + break; - 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 + case BSC_select: + case BSC_select_nocancel: + case BSC_socketpair: + /* + * Cannot determine info about file descriptors + */ + if (filter_mode & NETWORK_FILTER) + ret = true; - if (include_waited_flag) - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140 + break; - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_FSRW)); //0x0301 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_DKRW)); //0x0302 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_IOCTL)); //0x0306 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_BOOTCACHE)); //0x0307 + case BSC_dup: + case BSC_dup2: + /* + * We track these cases for fd state only + */ + fd = ti->arg1; - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_EXCP_SC)); //0x040c - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_PROC)); //0x0401 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO)); //0x040e - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO2)); //0x040f + if (error == 0 && fd_is_network(pid, fd)) { + /* + * then we are duping a socket descriptor + */ + fd = retval; /* the new fd */ + fd_set_is_network(pid, fd, true); + } - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE,DBG_CS_IO)); //0x0a00 - setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE, 1)); //0x0a01 for P_SCCS_SYNC_DIS + break; - setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 0)); //Carbon File Manager - setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 1)); //Carbon File Manager + default: + if (filter_mode & FILESYS_FILTER) + ret = true; - errno = 0; - int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSET_TYPEFILTER }; - size_t needed = KDBG_TYPEFILTER_BITMAP_SIZE; - if(sysctl(mib, 3, type_filter_bitmap, &needed, NULL, 0)) { - quit("trace facility failure, KERN_KDSET_TYPEFILTER\n"); + break; } -} -void -set_pidcheck(int pid, int on_off) -{ - kd_regtype kr; - - kr.type = KDBG_TYPENONE; - kr.value1 = pid; - kr.value2 = on_off; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDPIDTR; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; - - if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) { - if (on_off == 1) - fprintf(stderr, "pid %d does not exist\n", pid); - } else - one_good_pid++; + return ret; } -/* - * on_off == 0 turns off pid exclusion - * on_off == 1 turns on pid exclusion +/* + * called from: + * + * exit_event() (syscalls etc.) + * print_diskio() (disk I/Os) + * block callback for TrimExtent */ void -set_pidexclude(int pid, int on_off) +format_print(th_info_t ti, char *sc_name, ktrace_event_t event, + unsigned long type, int format, uint64_t now, uint64_t stime, + int waited, const char *pathname, struct diskio *dio) { - kd_regtype kr; - - one_good_pid++; - - kr.type = KDBG_TYPENONE; - kr.value1 = pid; - kr.value2 = on_off; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDPIDEX; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; - - if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) { - if (on_off == 1) - fprintf(stderr, "pid %d does not exist\n", pid); - } -} + uint64_t secs, usecs; + int nopadding = 0; + static time_t last_walltime_secs = -1; + const char *command_name; + pid_t pid; + int len = 0; + int clen = 0; + size_t tlen = 0; + unsigned long class; + uint64_t user_addr; + uint64_t user_size; + char *framework_name; + char *framework_type; + char *p1; + char *p2; + char buf[MAXWIDTH]; + char cs_diskname[32]; + unsigned long threadid; + struct timeval now_walltime; -void -get_bufinfo(kbufinfo_t *val) -{ - needed = sizeof (*val); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDGETBUF; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ + static char timestamp[32]; + static size_t timestamp_len = 0; - if (sysctl(mib, 3, val, &needed, 0, 0) < 0) - quit("trace facility failure, KERN_KDGETBUF\n"); + if (!mach_time_of_first_event) + mach_time_of_first_event = now; -} + if (format == FMT_DISKIO || format == FMT_DISKIO_CS) { + assert(dio); + } else { + assert(event); -void -set_remove() -{ - errno = 0; + if (format != FMT_UNMAP_INFO) + assert(ti); + } + + /* Filter out WindowServer/xcpm ioctls in fs_usage */ + if (type == BSC_ioctl && ti->arg2 == 0xffffffffc030581dUL) + return; - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREMOVE; /* protocol */ - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ + /* honor -S and -E */ + if (RAW_flag) { + uint64_t relative_time_ns; - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) { - set_remove_flag = 0; + relative_time_ns = mach_to_nano(now - mach_time_of_first_event); - if (errno == EBUSY) - quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); - else - quit("trace facility failure, KERN_KDREMOVE\n"); + if (relative_time_ns < start_time_ns || relative_time_ns > end_time_ns) + return; } -} -void -set_init() -{ kd_regtype kr; - - kr.type = KDBG_RANGETYPE; - kr.value1 = 0; - kr.value2 = -1; - needed = sizeof(kd_regtype); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETREG; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETREG\n"); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETUP\n"); -} + class = KDBG_EXTRACT_CLASS(type); + if (dio) { + command_name = dio->issuing_command; + threadid = dio->issuing_thread; + pid = dio->issuing_pid; + now_walltime = dio->completed_walltime; + } else { + if (ti && ti->command[0] != '\0') { + command_name = ti->command; + threadid = ti->thread; + pid = ti->pid; + } else { + command_name = ktrace_get_execname_for_thread(s, event->threadid); + threadid = event->threadid; + pid = ktrace_get_pid_for_thread(s, event->threadid); + } -void -sample_sc() -{ - kd_buf *kd; - int i, count; - size_t needed; - uint32_t my_buffer_size = 0; + now_walltime = event->walltime; + } - if (!RAW_flag) - get_bufinfo(&bufinfo); - else - my_buffer_size = num_events * sizeof(kd_buf); + if (!want_kernel_task && pid == 0) + return; - if (need_new_map) { - read_command_map(); - need_new_map = 0; + if (!command_name) + command_name = ""; + + assert(now_walltime.tv_sec || now_walltime.tv_usec); + + /* try and reuse the timestamp string */ + if (last_walltime_secs != now_walltime.tv_sec) { + timestamp_len = strftime(timestamp, sizeof (timestamp), "%H:%M:%S", localtime(&now_walltime.tv_sec)); + last_walltime_secs = now_walltime.tv_sec; } - if (!RAW_flag) { - needed = bufinfo.nkdbufs * sizeof(kd_buf); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDREADTR\n"); - count = needed; - - if (count > (num_events / 8)) { - if (usleep_ms > USLEEP_BEHIND) - usleep_ms = USLEEP_BEHIND; - else if (usleep_ms > USLEEP_MIN) - usleep_ms /= 2; - - } else if (count < (num_events / 16)) { - if (usleep_ms < USLEEP_MAX) - usleep_ms *= 2; - } - if (bufinfo.flags & KDBG_WRAPPED) { - fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count); + if (columns > MAXCOLS || wideflag) { + tlen = timestamp_len; + nopadding = 0; - delete_all_events(); + sprintf(×tamp[tlen], ".%06d", now_walltime.tv_usec); + tlen += 7; - need_new_map = 1; - - set_enable(0); - set_enable(1); - } + timestamp[tlen] = '\0'; } else { - int bytes_read; - - if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf)) - exit(0); - count = bytes_read / sizeof(kd_buf); + nopadding = 1; } - kd = (kd_buf *)my_buffer; -#if 0 - fprintf(stderr, "READTR returned %d items\n", count); -#endif - for (i = 0; i < count; i++) { - uint32_t debugid; - uintptr_t thread; - int type; - int index; - uintptr_t *sargptr; - uint64_t now; - long long l_usecs; - int secs; - long curr_time; - th_info_t ti; - struct diskio *dio; + clen = printf("%s %-17.17s", timestamp, sc_name); - thread = kd[i].arg5; - debugid = kd[i].debugid; - type = kd[i].debugid & DBG_FUNC_MASK; + framework_name = NULL; - now = kdbg_get_timestamp(&kd[i]); + if (columns > MAXCOLS || wideflag) { + off_t offset_reassembled = 0LL; - if (i == 0 && !RAW_flag) { + switch (format) { + case FMT_NOTHING: + clen += printf(" "); + break; - curr_time = time((long *)0); - /* - * Compute bias seconds after each trace buffer read. - * This helps resync timestamps with the system clock - * in the event of a system sleep. - */ - if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) { - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - bias_secs = curr_time - secs; - } - } - if (RAW_flag && bias_now == 0.0) - bias_now = now; - - if ((type & P_DISKIO_MASK) == P_DISKIO) { - insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now); - continue; - } - if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) { - if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) { - dio->vnodeid = kd[i].arg2; - print_diskio(dio); - free_diskio(dio); - } - continue; - } - - if ((type & CLASS_MASK) == P_CS_Class) { - - // the usual DBG_FUNC_START/END does not work for i/o since it will - // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit - // instead. the trace command doesn't know how handle either method - // (unmatched start/end or 0x4) but works a little better this way. - - int cs_type = type & P_CS_Type_Mask; // strip out the done bit - bool start = (type & P_CS_IO_Done) != P_CS_IO_Done; - - switch (cs_type) { - - case P_CS_ReadChunk: - case P_CS_WriteChunk: - case P_CS_MetaRead: - case P_CS_MetaWrite: - if (start) { - insert_diskio(cs_type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now); - } else { - if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) { - print_diskio(dio); - free_diskio(dio); - } - } - continue; + case FMT_AT: + case FMT_RENAMEAT: + case FMT_DEFAULT: + /* + * pathname based system calls or + * calls with no fd or pathname (i.e. sync) + */ + if (event->arg1) + clen += printf(" [%3d] ", (int)event->arg1); + else + clen += printf(" "); - case P_CS_TransformRead: - case P_CS_TransformWrite: - case P_CS_MigrationRead: - case P_CS_MigrationWrite: - if (start) { - insert_diskio(cs_type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now); - } else { - if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) { - print_diskio(dio); - free_diskio(dio); - } - } - continue; - - case P_CS_SYNC_DISK: - if (start) { - enter_event(thread, cs_type, &kd[i], NULL, (double)now); - } else { - exit_event(" SyncCacheCS", thread, cs_type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now); - } - continue; - } - - continue; // ignore other cs timestamps - } - - switch (type) { - - case TRACE_DATA_NEWTHREAD: - if (kd[i].arg1) { - if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL) - continue; - ti->child_thread = kd[i].arg1; - ti->pid = kd[i].arg2; - } - continue; - - case TRACE_STRING_NEWTHREAD: - if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0) - continue; - - create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1); - - delete_event(ti); - continue; - - case TRACE_DATA_EXEC: - if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL) - continue; - - ti->pid = kd[i].arg1; - continue; - - case TRACE_STRING_EXEC: - if ((ti = find_event(thread, BSC_execve))) { - if (ti->lookups[0].pathname[0]) - exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now); - - } else if ((ti = find_event(thread, BSC_posix_spawn))) { - if (ti->lookups[0].pathname[0]) - exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now); - } - if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0) - continue; - - create_map_entry(thread, ti->pid, (char *)&kd[i].arg1); - - delete_event(ti); - continue; - - case BSC_thread_terminate: - delete_map_entry(thread); - continue; - - case BSC_exit: - continue; - - case proc_exit: - kd[i].arg1 = kd[i].arg2 >> 8; - type = BSC_exit; - break; - - case BSC_mmap: - if (kd[i].arg4 & MAP_ANON) - continue; - break; - - case MACH_idle: - case MACH_sched: - case MACH_stkhandoff: - mark_thread_waited(thread); - continue; - - case BC_IO_HIT: - case BC_IO_HIT_STALLED: - case BC_IO_MISS: - case BC_IO_MISS_CUT_THROUGH: - case BC_PLAYBACK_IO: - if ((dio = find_diskio(kd[i].arg1)) != NULL) - dio->bc_info = type; - continue; + break; - case HFS_modify_block_end: - if ((ti = find_event(thread, 0))) { - if (ti->nameptr) - add_meta_name(kd[i].arg2, ti->nameptr); - } - continue; - - case VFS_ALIAS_VP: - add_vnode_name(kd[i].arg2, find_vnode_name(kd[i].arg1)); - continue; - - case VFS_LOOKUP: - if ((ti = find_event(thread, 0)) == (struct th_info *)0) - continue; - - if (debugid & DBG_FUNC_START) { - - if (ti->in_hfs_update) { - ti->pn_work_index = (MAX_PATHNAMES - 1); - } else { - if (ti->pn_scall_index < MAX_SCALL_PATHNAMES) - ti->pn_work_index = ti->pn_scall_index; - else - continue; - } - sargptr = &ti->lookups[ti->pn_work_index].pathname[0]; - - ti->vnodeid = kd[i].arg1; - - *sargptr++ = kd[i].arg2; - *sargptr++ = kd[i].arg3; - *sargptr++ = kd[i].arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; - - ti->pathptr = sargptr; - } else { - sargptr = ti->pathptr; - - /* - * We don't want to overrun our pathname buffer if the - * kernel sends us more VFS_LOOKUP entries than we can - * handle and we only handle 2 pathname lookups for - * a given system call - */ - if (sargptr == 0) - continue; - - if ((uintptr_t)sargptr < (uintptr_t)&ti->lookups[ti->pn_work_index].pathname[NUMPARMS]) { - - *sargptr++ = kd[i].arg1; - *sargptr++ = kd[i].arg2; - *sargptr++ = kd[i].arg3; - *sargptr++ = kd[i].arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; - } - } - if (debugid & DBG_FUNC_END) { - - ti->nameptr = add_vnode_name(ti->vnodeid, &ti->lookups[ti->pn_work_index].pathname[0]); - - if (ti->pn_work_index == ti->pn_scall_index) { - - ti->pn_scall_index++; - - if (ti->pn_scall_index < MAX_SCALL_PATHNAMES) - ti->pathptr = &ti->lookups[ti->pn_scall_index].pathname[0]; - else - ti->pathptr = 0; - } - } else - ti->pathptr = sargptr; - - continue; - } + case FMT_FD: + /* + * fd based system call... no I/O + */ + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d", (int)ti->arg1); - if (debugid & DBG_FUNC_START) { - char * p; + break; - if ((type & CLASS_MASK) == FILEMGR_BASE) { + case FMT_FD_2: + /* + * accept, dup, dup2 + */ + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d F=%-3d", (int)ti->arg1, (int)event->arg2); - index = filemgr_index(type); + break; - if (index >= MAX_FILEMGR) - continue; + case FMT_FD_IO: + /* + * system calls with fd's that return an I/O completion count + */ + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d B=0x%-6lx", (int)ti->arg1, event->arg2); - if ((p = filemgr_calls[index].fm_name) == NULL) - continue; - } else - p = NULL; + break; - enter_event(thread, type, &kd[i], p, (double)now); - continue; - } + case FMT_PGIN: + /* + * pagein + */ + user_addr = ((uint64_t)event->arg1 << 32) | (uint32_t)event->arg2; - switch (type) { + lookup_name(user_addr, &framework_type, &framework_name); + clen += clip_64bit(" A=", user_addr); + break; - case Throttled: - exit_event(" THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now); - continue; + case FMT_CACHEHIT: + /* + * cache hit + */ + user_addr = ((uint64_t)event->arg1 << 32) | (uint32_t)event->arg2; - case HFS_update: - exit_event(" HFS_update", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_HFS_update, (double)now); - continue; + lookup_name(user_addr, &framework_type, &framework_name); + clen += clip_64bit(" A=", user_addr); + break; - case SPEC_unmap_info: - if (check_filter_mode(NULL, SPEC_unmap_info, 0, 0, "SPEC_unmap_info")) - format_print(NULL, " TrimExtent", thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, 0, FMT_UNMAP_INFO, now, now, 0, "", NULL); - continue; + case FMT_PGOUT: + /* + * pageout + */ + clen += printf(" B=0x%-8lx", event->arg1); + break; - case SPEC_ioctl: - if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE) - 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); - } - continue; + case FMT_HFS_update: + { + static const struct { + int flag; + char ch; + } hfsflags[] = { + { DBG_HFS_UPDATE_SKIPPED, 'S' }, + { DBG_HFS_UPDATE_FORCE, 'F' }, + { DBG_HFS_UPDATE_MODIFIED, 'M' }, + { DBG_HFS_UPDATE_MINOR, 'N' }, + { DBG_HFS_UPDATE_DATEADDED, 'd' }, + { DBG_HFS_UPDATE_CHGTIME, 'c' }, + { DBG_HFS_UPDATE_ACCTIME, 'a' }, + { DBG_HFS_UPDATE_MODTIME, 'm' }, + }; + size_t i; + int flagcount; + char *sbuf; + int sflag = (int)event->arg2; + + flagcount = sizeof (hfsflags) / sizeof (*hfsflags); + sbuf = malloc(flagcount + 1); + + for (i = 0; i < flagcount; i++) { + if (sflag & hfsflags[i].flag) { + sbuf[i] = hfsflags[i].ch; + } else { + sbuf[i] = '_'; + } + } - case MACH_pageout: - if (kd[i].arg2) - exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); - else - exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); - continue; + sbuf[flagcount] = '\0'; - case MACH_vmfault: - if (kd[i].arg4 == DBG_PAGEIN_FAULT) - exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_PAGEINV_FAULT) - exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_PAGEIND_FAULT) - exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT) - exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now); - else { - if ((ti = find_event(thread, type))) - delete_event(ti); - } - continue; + clen += printf(" %*s(%s) ", 17 - flagcount, "", sbuf); - case MSC_map_fd: - exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now); - continue; - - case BSC_mmap_extended: - case BSC_mmap_extended2: - case BSC_msync_extended: - case BSC_pread_extended: - case BSC_pwrite_extended: - extend_syscall(thread, type, &kd[i]); - continue; - } + free(sbuf); - if ((type & CSC_MASK) == BSC_BASE) { + pathname = ktrace_get_path_for_vp(s, event->arg1); - if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL) - continue; + if (!pathname) + pathname = ""; - if (bsd_syscalls[index].sc_name) { - exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, - bsd_syscalls[index].sc_format, (double)now); + nopadding = 1; - if (type == BSC_exit) - delete_map_entry(thread); - } - } else if ((type & CLASS_MASK) == FILEMGR_BASE) { - - if ((index = filemgr_index(type)) >= MAX_FILEMGR) - continue; - - if (filemgr_calls[index].fm_name) { - exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, - FMT_DEFAULT, (double)now); + break; } - } - } - fflush(0); -} - - -void -enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now) -{ - th_info_t ti; - threadmap_t tme; - int secs; - int usecs; - long long l_usecs; - long curr_time; - int clen = 0; - int tsclen = 0; - int nmclen = 0; - int argsclen = 0; - char buf[MAXWIDTH]; - - if ((ti = add_event(thread, type)) == NULL) - return; - - ti->stime = now; - ti->arg1 = kd->arg1; - ti->arg2 = kd->arg2; - ti->arg3 = kd->arg3; - ti->arg4 = kd->arg4; - - switch (type) { - case HFS_update: - ti->in_hfs_update = 1; - break; - } - - if ((type & CLASS_MASK) == FILEMGR_BASE && - (!RAW_flag || (now >= start_time && now <= end_time))) { - - filemgr_in_progress++; - ti->in_filemgr = 1; - - if (RAW_flag) { - l_usecs = (long long)((now - bias_now) / divisor); - l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs; - } else - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - curr_time = bias_secs + secs; - - sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11])); - tsclen = strlen(buf); - - if (columns > MAXCOLS || wideflag) { - usecs = l_usecs - (long long)((long long)secs * 1000000); - sprintf(&buf[tsclen], ".%06ld", (long)usecs); - tsclen = strlen(buf); - } - - /* - * Print timestamp column - */ - printf("%s", buf); - - tme = find_map_entry(thread); - if (tme) { - sprintf(buf, " %-25.25s ", name); - nmclen = strlen(buf); - printf("%s", buf); - - sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); - argsclen = strlen(buf); - - /* - * Calculate white space out to command - */ - if (columns > MAXCOLS || wideflag) { - clen = columns - (tsclen + nmclen + argsclen + 20 + 11); - } else - clen = columns - (tsclen + nmclen + argsclen + 12); - - if (clen > 0) { - printf("%s", buf); /* print the kdargs */ - memset(buf, ' ', clen); - buf[clen] = '\0'; - printf("%s", buf); - } - else if ((argsclen + clen) > 0) { + case FMT_DISKIO: /* - * no room so wipe out the kdargs + * physical disk I/O */ - memset(buf, ' ', (argsclen + clen)); - buf[argsclen + clen] = '\0'; - printf("%s", buf); - } - if (columns > MAXCOLS || wideflag) - printf("%s.%d\n", tme->tm_command, (int)thread); - else - printf("%-12.12s\n", tme->tm_command); - } else - printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); - } -} - - -void -enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now) -{ - int index; - - switch (type) { - - case P_CS_SYNC_DISK: - case MACH_pageout: - case MACH_vmfault: - case MSC_map_fd: - case SPEC_ioctl: - case Throttled: - case HFS_update: - enter_event_now(thread, type, kd, name, now); - return; - - } - if ((type & CSC_MASK) == BSC_BASE) { - - if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL) - return; - - if (bsd_syscalls[index].sc_name) - enter_event_now(thread, type, kd, name, now); - return; - } - if ((type & CLASS_MASK) == FILEMGR_BASE) { - - if ((index = filemgr_index(type)) >= MAX_FILEMGR) - return; - - if (filemgr_calls[index].fm_name) - enter_event_now(thread, type, kd, name, now); - return; - } -} - -/* - * Handle system call extended trace data. - * pread and pwrite: - * Wipe out the kd args that were collected upon syscall_entry - * because it is the extended info that we really want, and it - * is all we really need. -*/ - -void -extend_syscall(uintptr_t thread, int type, kd_buf *kd) -{ - th_info_t ti; - - switch (type) { - case BSC_mmap_extended: - if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0) - return; - ti->arg8 = ti->arg3; /* save protection */ - ti->arg1 = kd->arg1; /* the fd */ - ti->arg3 = kd->arg2; /* bottom half address */ - ti->arg5 = kd->arg3; /* bottom half size */ - break; - case BSC_mmap_extended2: - if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0) - return; - ti->arg2 = kd->arg1; /* top half address */ - ti->arg4 = kd->arg2; /* top half size */ - ti->arg6 = kd->arg3; /* top half file offset */ - ti->arg7 = kd->arg4; /* bottom half file offset */ - break; - case BSC_msync_extended: - if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) { - if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0) - return; - } - ti->arg4 = kd->arg1; /* top half address */ - ti->arg5 = kd->arg2; /* top half size */ - break; - case BSC_pread_extended: - if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) { - if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0) - return; - } - ti->arg1 = kd->arg1; /* the fd */ - ti->arg2 = kd->arg2; /* nbytes */ - ti->arg3 = kd->arg3; /* top half offset */ - ti->arg4 = kd->arg4; /* bottom half offset */ - break; - case BSC_pwrite_extended: - if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) { - if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0) - return; - } - ti->arg1 = kd->arg1; /* the fd */ - ti->arg2 = kd->arg2; /* nbytes */ - ti->arg3 = kd->arg3; /* top half offset */ - ti->arg4 = kd->arg4; /* bottom half offset */ - break; - default: - return; - } -} - - -void -exit_event(char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, - int format, double now) -{ - th_info_t ti; - - if ((ti = find_event(thread, type)) == (struct th_info *)0) - return; - - ti->nameptr = 0; - - if (check_filter_mode(ti, type, arg1, arg2, sc_name)) - format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)&ti->lookups[0].pathname[0], NULL); - - switch (type) { - - case HFS_update: - ti->in_hfs_update = 0; - break; - } - if ((type & CLASS_MASK) == FILEMGR_BASE) { - ti->in_filemgr = 0; - - if (filemgr_in_progress > 0) - filemgr_in_progress--; - } - delete_event(ti); -} + if (dio->io_errno) { + clen += printf(" D=0x%8.8lx [%3d]", dio->blkno, (int)dio->io_errno); + } else { + if (BC_flag) + clen += printf(" D=0x%8.8lx B=0x%-6lx BC:%s /dev/%s ", dio->blkno, dio->iosize, BC_STR(dio->bc_info), find_disk_name(dio->dev)); + else + clen += printf(" D=0x%8.8lx B=0x%-6lx /dev/%s ", dio->blkno, dio->iosize, find_disk_name(dio->dev)); + + if (dio->is_meta) { + if (!(type & P_DISKIO_READ)) { + pathname = meta_find_name(dio->blkno); + } + } else { + pathname = ktrace_get_path_for_vp(s, dio->vnodeid); + + if (!pathname) + pathname = ""; + } + + nopadding = 1; + } + break; -void -get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off) -{ - if (smode & 04) - buf[0] = 'r'; - if (smode & 02) - buf[1] = 'w'; - if (smode & 01) { - if (special) - buf[2] = x_on; - else - buf[2] = 'x'; - } else { - if (special) - buf[2] = x_off; - } -} + case FMT_DISKIO_CS: + /* + * physical disk I/O + */ + if (dio->io_errno) + clen += printf(" D=0x%8.8lx [%3lu]", dio->blkno, dio->io_errno); + else + clen += printf(" D=0x%8.8lx B=0x%-6lx /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, cs_diskname)); + break; -void -get_mode_string(int mode, char *buf) -{ - memset(buf, '-', 9); - buf[9] = '\0'; + case FMT_SYNC_DISK_CS: + /* + * physical disk sync cache + */ + clen += printf(" /dev/%s", generate_cs_disk_name(event->arg1, cs_diskname)); - get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T'); - get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S'); - get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S'); -} + break; + case FMT_MSYNC: + { + /* + * msync + */ + int mlen = 0; -int clip_64bit(char *s, uint64_t value) -{ - int clen = 0; + buf[0] = '\0'; - if ( (value & 0xff00000000000000LL) ) - clen = printf("%s0x%16.16qx", s, value); - else if ( (value & 0x00ff000000000000LL) ) - clen = printf("%s0x%14.14qx ", s, value); - else if ( (value & 0x0000ff0000000000LL) ) - clen = printf("%s0x%12.12qx ", s, value); - else if ( (value & 0x000000ff00000000LL) ) - clen = printf("%s0x%10.10qx ", s, value); - else - clen = printf("%s0x%8.8qx ", s, value); - - return (clen); -} + if (ti->arg3 & MS_ASYNC) + mlen += sprintf(&buf[mlen], "MS_ASYNC | "); + else + mlen += sprintf(&buf[mlen], "MS_SYNC | "); + if (ti->arg3 & MS_INVALIDATE) + mlen += sprintf(&buf[mlen], "MS_INVALIDATE | "); + if (ti->arg3 & MS_KILLPAGES) + mlen += sprintf(&buf[mlen], "MS_KILLPAGES | "); + if (ti->arg3 & MS_DEACTIVATE) + mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | "); -void -format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, - int format, double now, double stime, int waited, char *pathname, struct diskio *dio) -{ - int secs; - int usecs; - int nopadding = 0; - long long l_usecs; - long curr_time; - char *command_name; - int in_filemgr = 0; - int len = 0; - int clen = 0; - int tlen = 0; - int class; - uint64_t user_addr; - uint64_t user_size; - char *framework_name; - char *framework_type; - char *p1; - char *p2; - char buf[MAXWIDTH]; - char cs_diskname[32]; + if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE)) + mlen += sprintf(&buf[mlen], "UNKNOWN | "); - static char timestamp[32]; - static int last_timestamp = -1; - static int timestamp_len = 0; + if (mlen) + buf[mlen - 3] = '\0'; - command_name = ""; + if (event->arg1) + clen += printf(" [%3d]", (int)event->arg1); - // Filter out WindowServer/xcpm iocts in fs_usage - if (format == FMT_IOCTL && ti->arg2 == 0xc030581d) - return; + user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1); + clen += clip_64bit(" A=", user_addr); - if (RAW_flag) { - l_usecs = (long long)((now - bias_now) / divisor); + user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2); - if ((double)l_usecs < start_time || (double)l_usecs > end_time) - return; + clen += printf(" B=0x%-16qx <%s>", user_size, buf); - l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs; - } - else - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - curr_time = bias_secs + secs; + break; + } - class = type >> 24; + case FMT_FLOCK: + { + /* + * flock + */ + int mlen = 0; - if (dio) - command_name = dio->issuing_command; - else { - threadmap_t tme; + buf[0] = '\0'; - if ((tme = find_map_entry(thread))) - command_name = tme->tm_command; - } - if (last_timestamp != curr_time) { - timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11])); - last_timestamp = curr_time; - } - if (columns > MAXCOLS || wideflag) { - int usec; + if (ti->arg2 & LOCK_SH) + mlen += sprintf(&buf[mlen], "LOCK_SH | "); + if (ti->arg2 & LOCK_EX) + mlen += sprintf(&buf[mlen], "LOCK_EX | "); + if (ti->arg2 & LOCK_NB) + mlen += sprintf(&buf[mlen], "LOCK_NB | "); + if (ti->arg2 & LOCK_UN) + mlen += sprintf(&buf[mlen], "LOCK_UN | "); - tlen = timestamp_len; - nopadding = 0; - usec = (l_usecs - (long long)((long long)secs * 1000000)); + if (ti->arg2 & ~(LOCK_SH | LOCK_EX | LOCK_NB | LOCK_UN)) + mlen += sprintf(&buf[mlen], "UNKNOWN | "); - sprintf(×tamp[tlen], ".%06ld", (long)usec); - tlen += 7; + if (mlen) + buf[mlen - 3] = '\0'; - timestamp[tlen] = '\0'; + if (event->arg1) + clen += printf(" F=%-3d[%3d] <%s>", (int)ti->arg1, (int)event->arg1, buf); + else + clen += printf(" F=%-3d <%s>", (int)ti->arg1, buf); - if (filemgr_in_progress) { - if (class != FILEMGR_CLASS) { - if (find_event(thread, -1)) - in_filemgr = 1; + break; } - } - } else - nopadding = 1; - - if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag)) - clen = printf("%s %-20.20s", timestamp, sc_name); - else if (in_filemgr) - clen = printf("%s %-15.15s", timestamp, sc_name); - else - clen = printf("%s %-17.17s", timestamp, sc_name); - - framework_name = NULL; - - if (columns > MAXCOLS || wideflag) { + case FMT_FCNTL: + { + /* + * fcntl + */ + char *p = NULL; + int fd = -1; - off_t offset_reassembled = 0LL; - - switch (format) { + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d", (int)ti->arg1); + + switch(ti->arg2) { + case F_DUPFD: + p = "DUPFD"; + break; + + case F_GETFD: + p = "GETFD"; + break; + + case F_SETFD: + p = "SETFD"; + break; + + case F_GETFL: + p = "GETFL"; + break; + + case F_SETFL: + p = "SETFL"; + break; + + case F_GETOWN: + p = "GETOWN"; + break; + + case F_SETOWN: + p = "SETOWN"; + break; + + case F_GETLK: + p = "GETLK"; + break; + + case F_SETLK: + p = "SETLK"; + break; + + case F_SETLKW: + p = "SETLKW"; + break; + + case F_PREALLOCATE: + p = "PREALLOCATE"; + break; + + case F_SETSIZE: + p = "SETSIZE"; + break; + + case F_RDADVISE: + p = "RDADVISE"; + break; + + case F_GETPATH: + p = "GETPATH"; + break; + + case F_FULLFSYNC: + p = "FULLFSYNC"; + break; + + case F_PATHPKG_CHECK: + p = "PATHPKG_CHECK"; + break; + + case F_OPENFROM: + p = "OPENFROM"; + + if (event->arg1 == 0) + fd = (int)event->arg2; + break; + + case F_UNLINKFROM: + p = "UNLINKFROM"; + break; + + case F_CHECK_OPENEVT: + p = "CHECK_OPENEVT"; + break; + + case F_NOCACHE: + if (ti->arg3) + p = "CACHING OFF"; + else + p = "CACHING ON"; + break; + + case F_GLOBAL_NOCACHE: + if (ti->arg3) + p = "CACHING OFF (GLOBAL)"; + else + p = "CACHING ON (GLOBAL)"; + break; - case FMT_AT: - case FMT_RENAMEAT: - case FMT_DEFAULT: - /* - * pathname based system calls or - * calls with no fd or pathname (i.e. sync) - */ - if (arg1) - clen += printf(" [%3d] ", arg1); - else - clen += printf(" "); - break; + } - case FMT_FD: - /* - * fd based system call... no I/O - */ - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); - else - clen += printf(" F=%-3d", ti->arg1); - break; + if (p) { + if (fd == -1) + clen += printf(" <%s>", p); + else + clen += printf(" <%s> F=%d", p, fd); + } else { + clen += printf(" ", (int)ti->arg2); + } - case FMT_FD_2: - /* - * accept, dup, dup2 - */ - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); - else - clen += printf(" F=%-3d F=%-3d", ti->arg1, arg2); - break; + break; + } - case FMT_FD_IO: - /* - * system calls with fd's that return an I/O completion count - */ - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); - else - clen += printf(" F=%-3d B=0x%-6x", ti->arg1, arg2); - break; + case FMT_IOCTL: + { + /* + * ioctl + */ + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d", (int)ti->arg1); - case FMT_PGIN: - /* - * pagein - */ - user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3; + clen += printf(" ", (int)ti->arg2); - lookup_name(user_addr, &framework_type, &framework_name); - clen += clip_64bit(" A=", user_addr); - break; + break; + } - case FMT_CACHEHIT: - /* - * cache hit - */ - user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3; + case FMT_IOCTL_SYNC: + { + /* + * ioctl + */ + clen += printf(" B=%lu /dev/%s", event->arg3, find_disk_name(event->arg1)); - lookup_name(user_addr, &framework_type, &framework_name); - clen += clip_64bit(" A=", user_addr); - break; + break; + } - case FMT_PGOUT: - /* - * pageout - */ - clen += printf(" B=0x%-8x", arg2); - break; + case FMT_IOCTL_SYNCCACHE: + { + /* + * ioctl + */ + clen += printf(" /dev/%s", find_disk_name(event->arg1)); - case FMT_HFS_update: - { - char sbuf[7]; - int sflag = (int)arg2; - - memset(sbuf, '_', 6); - sbuf[6] = '\0'; - - - if (sflag & 0x10) - sbuf[0] = 'F'; - if (sflag & 0x08) - sbuf[1] = 'M'; - if (sflag & 0x20) - sbuf[2] = 'D'; - if (sflag & 0x04) - sbuf[3] = 'c'; - if (sflag & 0x01) - sbuf[4] = 'a'; - if (sflag & 0x02) - sbuf[5] = 'm'; - - clen += printf(" (%s) ", sbuf); - - pathname = find_vnode_name(arg1); - nopadding = 1; + break; + } - break; - } + case FMT_IOCTL_UNMAP: + { + /* + * ioctl + */ + clen += printf(" /dev/%s", find_disk_name(event->arg1)); - case FMT_DISKIO: - /* - * physical disk I/O - */ - if (dio->io_errno) - clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno); - else { - if (BC_flag) - clen += printf(" D=0x%8.8x B=0x%-6x BC:%s /dev/%s ", dio->blkno, dio->iosize, BC_STR(dio->bc_info), find_disk_name(dio->dev)); - else - clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s ", dio->blkno, dio->iosize, find_disk_name(dio->dev)); - - if (dio->is_meta) { - if (!(type & P_DISKIO_READ)) - pathname = find_meta_name(dio->blkno); - } else - pathname = find_vnode_name(dio->vnodeid); - nopadding = 1; + break; } - break; - case FMT_DISKIO_CS: - /* - * physical disk I/O - */ - if (dio->io_errno) - clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno); - else - clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0])); - break; + case FMT_UNMAP_INFO: + { + clen += printf(" D=0x%8.8lx B=0x%-6lx /dev/%s", event->arg2, event->arg3, find_disk_name(event->arg1)); - case FMT_SYNC_DISK_CS: - /* - * physical disk sync cache - */ - clen += printf(" /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0])); + break; + } - break; + case FMT_SELECT: + /* + * select + */ + if (event->arg1) + clen += printf(" [%3d]", (int)event->arg1); + else + clen += printf(" S=%-3d", (int)event->arg2); - case FMT_MSYNC: - { - /* - * msync - */ - int mlen = 0; + break; - buf[0] = '\0'; + case FMT_LSEEK: + case FMT_PREAD: + /* + * pread, pwrite, lseek + */ + clen += printf(" F=%-3d", (int)ti->arg1); + + if (event->arg1) { + clen += printf("[%3d] ", (int)event->arg1); + } else { + if (format == FMT_PREAD) + clen += printf(" B=0x%-8lx ", event->arg2); + else + clen += printf(" "); + } - if (ti->arg3 & MS_ASYNC) - mlen += sprintf(&buf[mlen], "MS_ASYNC | "); - else - mlen += sprintf(&buf[mlen], "MS_SYNC | "); + if (format == FMT_PREAD) + offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4); + else +#ifdef __ppc__ + offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3); +#else + offset_reassembled = (((off_t)(unsigned int)(event->arg3)) << 32) | (unsigned int)(event->arg2); +#endif - if (ti->arg3 & MS_INVALIDATE) - mlen += sprintf(&buf[mlen], "MS_INVALIDATE | "); - if (ti->arg3 & MS_KILLPAGES) - mlen += sprintf(&buf[mlen], "MS_KILLPAGES | "); - if (ti->arg3 & MS_DEACTIVATE) - mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | "); + clen += clip_64bit("O=", offset_reassembled); - if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE)) - mlen += sprintf(&buf[mlen], "UNKNOWN | "); - - if (mlen) - buf[mlen - 3] = '\0'; + if (format == FMT_LSEEK) { + char *mode; - if (arg1) - clen += printf(" [%3d]", arg1); + if (ti->arg4 == SEEK_SET) + mode = "SEEK_SET"; + else if (ti->arg4 == SEEK_CUR) + mode = "SEEK_CUR"; + else if (ti->arg4 == SEEK_END) + mode = "SEEK_END"; + else + mode = "UNKNOWN"; - user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1); - clen += clip_64bit(" A=", user_addr); + clen += printf(" <%s>", mode); + } - user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2); + break; - clen += printf(" B=0x%-16qx <%s>", user_size, buf); + case FMT_MMAP: + /* + * mmap + */ + clen += printf(" F=%-3d ", (int)ti->arg1); - break; - } + if (event->arg1) { + clen += printf("[%3d] ", (int)event->arg1); + } else { + user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3); - case FMT_FLOCK: - { - /* - * flock - */ - int mlen = 0; - - buf[0] = '\0'; - - if (ti->arg2 & LOCK_SH) - mlen += sprintf(&buf[mlen], "LOCK_SH | "); - if (ti->arg2 & LOCK_EX) - mlen += sprintf(&buf[mlen], "LOCK_EX | "); - if (ti->arg2 & LOCK_NB) - mlen += sprintf(&buf[mlen], "LOCK_NB | "); - if (ti->arg2 & LOCK_UN) - mlen += sprintf(&buf[mlen], "LOCK_UN | "); - - if (ti->arg2 & ~(LOCK_SH | LOCK_EX | LOCK_NB | LOCK_UN)) - mlen += sprintf(&buf[mlen], "UNKNOWN | "); - - if (mlen) - buf[mlen - 3] = '\0'; - - if (arg1) - clen += printf(" F=%-3d[%3d] <%s>", ti->arg1, arg1, buf); - else - clen += printf(" F=%-3d <%s>", ti->arg1, buf); + clen += clip_64bit("A=", user_addr); - break; - } + offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7); - case FMT_FCNTL: - { - /* - * fcntl - */ - char *p = NULL; - int fd = -1; + clen += clip_64bit("O=", offset_reassembled); - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); - else - clen += printf(" F=%-3d", ti->arg1); - - switch(ti->arg2) { - - case F_DUPFD: - p = "DUPFD"; - break; - - case F_GETFD: - p = "GETFD"; - break; - - case F_SETFD: - p = "SETFD"; - break; - - case F_GETFL: - p = "GETFL"; - break; - - case F_SETFL: - p = "SETFL"; - break; - - case F_GETOWN: - p = "GETOWN"; - break; - - case F_SETOWN: - p = "SETOWN"; - break; - - case F_GETLK: - p = "GETLK"; - break; - - case F_SETLK: - p = "SETLK"; - break; - - case F_SETLKW: - p = "SETLKW"; - break; - - case F_PREALLOCATE: - p = "PREALLOCATE"; - break; - - case F_SETSIZE: - p = "SETSIZE"; - break; - - case F_RDADVISE: - p = "RDADVISE"; - break; - - case F_GETPATH: - p = "GETPATH"; - break; - - case F_FULLFSYNC: - p = "FULLFSYNC"; - break; - - case F_PATHPKG_CHECK: - p = "PATHPKG_CHECK"; - break; - - case F_OPENFROM: - p = "OPENFROM"; - - if (arg1 == 0) - fd = arg2; - break; - - case F_UNLINKFROM: - p = "UNLINKFROM"; - break; - - case F_CHECK_OPENEVT: - p = "CHECK_OPENEVT"; - break; - - case F_NOCACHE: - if (ti->arg3) - p = "CACHING OFF"; - else - p = "CACHING ON"; - break; - - case F_GLOBAL_NOCACHE: - if (ti->arg3) - p = "CACHING OFF (GLOBAL)"; - else - p = "CACHING ON (GLOBAL)"; - break; + user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5); - } - if (p) { - if (fd == -1) - clen += printf(" <%s>", p); - else - clen += printf(" <%s> F=%d", p, fd); - } else - clen += printf(" ", ti->arg2); + clen += printf("B=0x%-16qx", user_size); - break; - } + clen += printf(" <"); - case FMT_IOCTL: - { - /* - * ioctl - */ - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); - else - clen += printf(" F=%-3d", ti->arg1); + if (ti->arg8 & PROT_READ) + clen += printf("READ"); - clen += printf(" ", ti->arg2); + if (ti->arg8 & PROT_WRITE) + clen += printf("|WRITE"); - break; - } + if (ti->arg8 & PROT_EXEC) + clen += printf("|EXEC"); - case FMT_IOCTL_SYNC: - { - /* - * ioctl - */ - clen += printf(" B=%d /dev/%s", arg3, find_disk_name(arg1)); + clen += printf(">"); + } - break; - } + break; - case FMT_IOCTL_SYNCCACHE: - { - /* - * ioctl - */ - clen += printf(" /dev/%s", find_disk_name(arg1)); + case FMT_TRUNC: + case FMT_FTRUNC: + /* + * ftruncate, truncate + */ + if (format == FMT_FTRUNC) + clen += printf(" F=%-3d", (int)ti->arg1); + else + clen += printf(" "); - break; - } + if (event->arg1) + clen += printf("[%3d]", (int)event->arg1); - case FMT_IOCTL_UNMAP: - { - /* - * ioctl - */ - clen += printf(" /dev/%s", find_disk_name(arg1)); +#ifdef __ppc__ + offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3); +#else + offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2); +#endif + clen += clip_64bit(" O=", offset_reassembled); - break; - } + nopadding = 1; + break; - case FMT_UNMAP_INFO: - { - clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", arg2, arg3, find_disk_name(arg1)); + case FMT_FCHFLAGS: + case FMT_CHFLAGS: + { + /* + * fchflags, chflags + */ + int mlen = 0; + + if (format == FMT_FCHFLAGS) { + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d", (int)ti->arg1); + } else { + if (event->arg1) + clen += printf(" [%3d] ", (int)event->arg1); + } - break; - } + buf[mlen++] = ' '; + buf[mlen++] = '<'; + + if (ti->arg2 & UF_NODUMP) + mlen += sprintf(&buf[mlen], "UF_NODUMP | "); + if (ti->arg2 & UF_IMMUTABLE) + mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | "); + if (ti->arg2 & UF_APPEND) + mlen += sprintf(&buf[mlen], "UF_APPEND | "); + if (ti->arg2 & UF_OPAQUE) + mlen += sprintf(&buf[mlen], "UF_OPAQUE | "); + if (ti->arg2 & SF_ARCHIVED) + mlen += sprintf(&buf[mlen], "SF_ARCHIVED | "); + if (ti->arg2 & SF_IMMUTABLE) + mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | "); + if (ti->arg2 & SF_APPEND) + mlen += sprintf(&buf[mlen], "SF_APPEND | "); + + if (ti->arg2 == 0) + mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | "); + else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND)) + mlen += sprintf(&buf[mlen], "UNKNOWN | "); + + if (mlen >= 3) + mlen -= 3; + + buf[mlen++] = '>'; + buf[mlen] = '\0'; + + if (mlen < 19) { + memset(&buf[mlen], ' ', 19 - mlen); + mlen = 19; + buf[mlen] = '\0'; + } - case FMT_SELECT: - /* - * select - */ - if (arg1) - clen += printf(" [%3d]", arg1); - else - clen += printf(" S=%-3d", arg2); + clen += printf("%s", buf); - break; + nopadding = 1; + break; + } - case FMT_LSEEK: - case FMT_PREAD: - /* - * pread, pwrite, lseek - */ - clen += printf(" F=%-3d", ti->arg1); + case FMT_UMASK: + case FMT_FCHMOD: + case FMT_FCHMOD_EXT: + case FMT_CHMOD: + case FMT_CHMOD_EXT: + case FMT_CHMODAT: + { + /* + * fchmod, fchmod_extended, chmod, chmod_extended + */ + unsigned long mode; + + if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) { + if (event->arg1) + clen += printf(" F=%-3d[%3d] ", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d ", (int)ti->arg1); + } else { + if (event->arg1) + clen += printf(" [%3d] ", (int)event->arg1); + else + clen += printf(" "); + } - if (arg1) - clen += printf("[%3d] ", arg1); - else { - if (format == FMT_PREAD) - clen += printf(" B=0x%-8x ", arg2); + if (format == FMT_UMASK) + mode = ti->arg1; + else if (format == FMT_FCHMOD || format == FMT_CHMOD || format == FMT_CHMODAT) + mode = ti->arg2; else - clen += printf(" "); - } - if (format == FMT_PREAD) - offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4); - else -#ifdef __ppc__ - offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3); -#else - offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2); -#endif - clen += clip_64bit("O=", offset_reassembled); + mode = ti->arg4; - if (format == FMT_LSEEK) { - char *mode; + get_mode_string(mode, &buf[0]); - if (ti->arg4 == SEEK_SET) - mode = "SEEK_SET"; - else if (ti->arg4 == SEEK_CUR) - mode = "SEEK_CUR"; - else if (ti->arg4 == SEEK_END) - mode = "SEEK_END"; + if (event->arg1 == 0) + clen += printf("<%s> ", buf); else - mode = "UNKNOWN"; - - clen += printf(" <%s>", mode); + clen += printf("<%s>", buf); + break; } - break; - - case FMT_MMAP: - /* - * mmap - */ - clen += printf(" F=%-3d ", ti->arg1); - - if (arg1) - clen += printf("[%3d] ", arg1); - else { - user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3); - - clen += clip_64bit("A=", user_addr); - - offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7); + case FMT_ACCESS: + { + /* + * access + */ + char mode[5]; + + memset(mode, '_', 4); + mode[4] = '\0'; + + if (ti->arg2 & R_OK) + mode[0] = 'R'; + if (ti->arg2 & W_OK) + mode[1] = 'W'; + if (ti->arg2 & X_OK) + mode[2] = 'X'; + if (ti->arg2 == F_OK) + mode[3] = 'F'; + + if (event->arg1) + clen += printf(" [%3d] (%s) ", (int)event->arg1, mode); + else + clen += printf(" (%s) ", mode); - clen += clip_64bit("O=", offset_reassembled); + nopadding = 1; + break; + } - user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5); + case FMT_MOUNT: + { + if (event->arg1) + clen += printf(" [%3d] ", (int)event->arg1, ti->arg3); + else + clen += printf(" ", ti->arg3); - clen += printf("B=0x%-16qx", user_size); - - clen += printf(" <"); + nopadding = 1; + break; + } - if (ti->arg8 & PROT_READ) - clen += printf("READ"); + case FMT_UNMOUNT: + { + char *mountflag; - if (ti->arg8 & PROT_WRITE) - clen += printf("|WRITE"); + if (ti->arg2 & MNT_FORCE) + mountflag = ""; + else + mountflag = ""; - if (ti->arg8 & PROT_EXEC) - clen += printf("|EXEC"); + if (event->arg1) + clen += printf(" [%3d] %s ", (int)event->arg1, mountflag); + else + clen += printf(" %s ", mountflag); - clen += printf(">"); + nopadding = 1; + break; } - break; - case FMT_TRUNC: - case FMT_FTRUNC: - /* - * ftruncate, truncate - */ - if (format == FMT_FTRUNC) - clen += printf(" F=%-3d", ti->arg1); - else - clen += printf(" "); + case FMT_OPENAT: + case FMT_OPEN: + { + /* + * open + */ + char mode[7]; + + memset(mode, '_', 6); + mode[6] = '\0'; + + if (ti->arg2 & O_RDWR) { + mode[0] = 'R'; + mode[1] = 'W'; + } else if (ti->arg2 & O_WRONLY) { + mode[1] = 'W'; + } else { + mode[0] = 'R'; + } - if (arg1) - clen += printf("[%3d]", arg1); + if (ti->arg2 & O_CREAT) + mode[2] = 'C'; -#ifdef __ppc__ - offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3); -#else - offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2); -#endif - clen += clip_64bit(" O=", offset_reassembled); + if (ti->arg2 & O_APPEND) + mode[3] = 'A'; - nopadding = 1; - break; + if (ti->arg2 & O_TRUNC) + mode[4] = 'T'; - case FMT_FCHFLAGS: - case FMT_CHFLAGS: - { - /* - * fchflags, chflags - */ - int mlen = 0; + if (ti->arg2 & O_EXCL) + mode[5] = 'E'; - if (format == FMT_FCHFLAGS) { - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); + if (event->arg1) + clen += printf(" [%3d] (%s) ", (int)event->arg1, mode); else - clen += printf(" F=%-3d", ti->arg1); - } else { - if (arg1) - clen += printf(" [%3d] ", arg1); - } - buf[mlen++] = ' '; - buf[mlen++] = '<'; - - if (ti->arg2 & UF_NODUMP) - mlen += sprintf(&buf[mlen], "UF_NODUMP | "); - if (ti->arg2 & UF_IMMUTABLE) - mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | "); - if (ti->arg2 & UF_APPEND) - mlen += sprintf(&buf[mlen], "UF_APPEND | "); - if (ti->arg2 & UF_OPAQUE) - mlen += sprintf(&buf[mlen], "UF_OPAQUE | "); - if (ti->arg2 & SF_ARCHIVED) - mlen += sprintf(&buf[mlen], "SF_ARCHIVED | "); - if (ti->arg2 & SF_IMMUTABLE) - mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | "); - if (ti->arg2 & SF_APPEND) - mlen += sprintf(&buf[mlen], "SF_APPEND | "); - - if (ti->arg2 == 0) - mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | "); - else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND)) - mlen += sprintf(&buf[mlen], "UNKNOWN | "); - - if (mlen >= 3) - mlen -= 3; - - buf[mlen++] = '>'; - buf[mlen] = '\0'; - - if (mlen < 19) { - memset(&buf[mlen], ' ', 19 - mlen); - mlen = 19; - } - clen += printf("%s", buf); - - nopadding = 1; - break; - } - - case FMT_UMASK: - case FMT_FCHMOD: - case FMT_FCHMOD_EXT: - case FMT_CHMOD: - case FMT_CHMOD_EXT: - case FMT_CHMODAT: - { - /* - * fchmod, fchmod_extended, chmod, chmod_extended - */ - int mode; + clen += printf(" F=%-3d (%s) ", (int)event->arg2, mode); - if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) { - if (arg1) - clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1); - else - clen += printf(" F=%-3d ", ti->arg1); - } else { - if (arg1) - clen += printf(" [%3d] ", arg1); - else - clen += printf(" "); + nopadding = 1; + break; } - if (format == FMT_UMASK) - mode = ti->arg1; - else if (format == FMT_FCHMOD || format == FMT_CHMOD || format == FMT_CHMODAT) - mode = ti->arg2; - else - mode = ti->arg4; - - get_mode_string(mode, &buf[0]); - if (arg1 == 0) - clen += printf("<%s> ", buf); - else - clen += printf("<%s>", buf); - break; - } + case FMT_SOCKET: + { + /* + * socket + * + */ + char *domain; + char *type; - case FMT_ACCESS: - { - /* - * access - */ - char mode[5]; - - memset(mode, '_', 4); - mode[4] = '\0'; - - if (ti->arg2 & R_OK) - mode[0] = 'R'; - if (ti->arg2 & W_OK) - mode[1] = 'W'; - if (ti->arg2 & X_OK) - mode[2] = 'X'; - if (ti->arg2 == F_OK) - mode[3] = 'F'; - - if (arg1) - clen += printf(" [%3d] (%s) ", arg1, mode); - else - clen += printf(" (%s) ", mode); + switch (ti->arg1) { + case AF_UNIX: + domain = "AF_UNIX"; + break; - nopadding = 1; - break; - } - - case FMT_MOUNT: - { - if (arg1) - clen += printf(" [%3d] ", arg1, ti->arg3); - else - clen += printf(" ", ti->arg3); - - nopadding = 1; - break; - } - - case FMT_UNMOUNT: - { - char *mountflag; - - if (ti->arg2 & MNT_FORCE) - mountflag = ""; - else - mountflag = ""; - - if (arg1) - clen += printf(" [%3d] %s ", arg1, mountflag); - else - clen += printf(" %s ", mountflag); - - nopadding = 1; - break; - } - - case FMT_OPENAT: - case FMT_OPEN: - { - /* - * open - */ - char mode[7]; - - memset(mode, '_', 6); - mode[6] = '\0'; - - if (ti->arg2 & O_RDWR) { - mode[0] = 'R'; - mode[1] = 'W'; - } else if (ti->arg2 & O_WRONLY) - mode[1] = 'W'; - else - mode[0] = 'R'; - - if (ti->arg2 & O_CREAT) - mode[2] = 'C'; - - if (ti->arg2 & O_APPEND) - mode[3] = 'A'; - - if (ti->arg2 & O_TRUNC) - mode[4] = 'T'; - - if (ti->arg2 & O_EXCL) - mode[5] = 'E'; - - if (arg1) - clen += printf(" [%3d] (%s) ", arg1, mode); - else - clen += printf(" F=%-3d (%s) ", arg2, mode); + case AF_INET: + domain = "AF_INET"; + break; - nopadding = 1; - break; - } + case AF_ISO: + domain = "AF_ISO"; + break; - case FMT_SOCKET: - { - /* - * socket - * - */ - char *domain; - char *type; - - switch (ti->arg1) { + case AF_NS: + domain = "AF_NS"; + break; - case AF_UNIX: - domain = "AF_UNIX"; - break; + case AF_IMPLINK: + domain = "AF_IMPLINK"; + break; - case AF_INET: - domain = "AF_INET"; - break; - - case AF_ISO: - domain = "AF_ISO"; - break; + default: + domain = "UNKNOWN"; + break; + } - case AF_NS: - domain = "AF_NS"; - break; + switch (ti->arg2) { + case SOCK_STREAM: + type = "SOCK_STREAM"; + break; + case SOCK_DGRAM: + type = "SOCK_DGRAM"; + break; + case SOCK_RAW: + type = "SOCK_RAW"; + break; + default: + type = "UNKNOWN"; + break; + } - case AF_IMPLINK: - domain = "AF_IMPLINK"; - break; + if (event->arg1) + clen += printf(" [%3d] <%s, %s, 0x%lx>", (int)event->arg1, domain, type, ti->arg3); + else + clen += printf(" F=%-3d <%s, %s, 0x%lx>", (int)event->arg2, domain, type, ti->arg3); - default: - domain = "UNKNOWN"; - break; + break; } - switch (ti->arg2) { - - case SOCK_STREAM: - type = "SOCK_STREAM"; - break; - - case SOCK_DGRAM: - type = "SOCK_DGRAM"; - break; + case FMT_AIO_FSYNC: + { + /* + * aio_fsync [errno] AIOCBP OP + */ + char *op; - case SOCK_RAW: - type = "SOCK_RAW"; - break; + if (ti->arg1 == O_SYNC || ti->arg1 == 0) + op = "AIO_FSYNC"; +#if O_DSYNC + else if (ti->arg1 == O_DSYNC) + op = "AIO_DSYNC"; +#endif + else + op = "UNKNOWN"; - case SOCK_SEQPACKET: - type = "SOCK_SEQPACKET"; - break; + if (event->arg1) + clen += printf(" [%3d] P=0x%8.8lx <%s>", (int)event->arg1, ti->arg2, op); + else + clen += printf(" P=0x%8.8lx <%s>", ti->arg2, op); - case SOCK_RDM: - type = "SOCK_RDM"; - break; - - default: - type = "UNKNOWN"; - break; + break; } - if (arg1) - clen += printf(" [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3); - else - clen += printf(" F=%-3d <%s, %s, 0x%x>", arg2, domain, type, ti->arg3); - break; - } + case FMT_AIO_RETURN: + /* + * aio_return [errno] AIOCBP IOSIZE + */ + if (event->arg1) + clen += printf(" [%3d] P=0x%8.8lx", (int)event->arg1, ti->arg1); + else + clen += printf(" P=0x%8.8lx B=0x%-8lx", ti->arg1, event->arg2); - case FMT_AIO_FSYNC: - { - /* - * aio_fsync [errno] AIOCBP OP - */ - char *op; + break; - if (ti->arg1 == O_SYNC || ti->arg1 == 0) - op = "AIO_FSYNC"; -#if O_DSYNC - else if (ti->arg1 == O_DSYNC) - op = "AIO_DSYNC"; -#endif - else - op = "UNKNOWN"; + case FMT_AIO_SUSPEND: + /* + * aio_suspend [errno] NENTS + */ + if (event->arg1) + clen += printf(" [%3d] N=%d", (int)event->arg1, (int)ti->arg2); + else + clen += printf(" N=%d", (int)ti->arg2); - if (arg1) - clen += printf(" [%3d] P=0x%8.8x <%s>", arg1, ti->arg2, op); - else - clen += printf(" P=0x%8.8x <%s>", ti->arg2, op); - break; - } + break; - case FMT_AIO_RETURN: - /* - * aio_return [errno] AIOCBP IOSIZE - */ - if (arg1) - clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1); - else - clen += printf(" P=0x%8.8x B=0x%-8x", ti->arg1, arg2); - break; + case FMT_AIO_CANCEL: + /* + * aio_cancel [errno] FD or AIOCBP (if non-null) + */ + if (ti->arg2) { + if (event->arg1) + clen += printf(" [%3d] P=0x%8.8lx", (int)event->arg1, ti->arg2); + else + clen += printf(" P=0x%8.8lx", ti->arg2); + } else { + if (event->arg1) + clen += printf(" F=%-3d[%3d]", (int)ti->arg1, (int)event->arg1); + else + clen += printf(" F=%-3d", (int)ti->arg1); + } - case FMT_AIO_SUSPEND: - /* - * aio_suspend [errno] NENTS - */ - if (arg1) - clen += printf(" [%3d] N=%d", arg1, ti->arg2); - else - clen += printf(" N=%d", ti->arg2); - break; + break; - case FMT_AIO_CANCEL: - /* - * aio_cancel [errno] FD or AIOCBP (if non-null) - */ - if (ti->arg2) { - if (arg1) - clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg2); - else - clen += printf(" P=0x%8.8x", ti->arg2); - } else { - if (arg1) - clen += printf(" F=%-3d[%3d]", ti->arg1, arg1); + case FMT_AIO: + /* + * aio_error, aio_read, aio_write [errno] AIOCBP + */ + if (event->arg1) + clen += printf(" [%3d] P=0x%8.8lx", (int)event->arg1, ti->arg1); else - clen += printf(" F=%-3d", ti->arg1); - } - break; + clen += printf(" P=0x%8.8lx", ti->arg1); - case FMT_AIO: - /* - * aio_error, aio_read, aio_write [errno] AIOCBP - */ - if (arg1) - clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1); - else - clen += printf(" P=0x%8.8x", ti->arg1); - break; + break; - case FMT_LIO_LISTIO: - { - /* - * lio_listio [errno] NENTS MODE - */ - char *op; + case FMT_LIO_LISTIO: { + /* + * lio_listio [errno] NENTS MODE + */ + char *op; - if (ti->arg1 == LIO_NOWAIT) - op = "LIO_NOWAIT"; - else if (ti->arg1 == LIO_WAIT) - op = "LIO_WAIT"; - else - op = "UNKNOWN"; + if (ti->arg1 == LIO_NOWAIT) + op = "LIO_NOWAIT"; + else if (ti->arg1 == LIO_WAIT) + op = "LIO_WAIT"; + else + op = "UNKNOWN"; - if (arg1) - clen += printf(" [%3d] N=%d <%s>", arg1, ti->arg3, op); - else - clen += printf(" N=%d <%s>", ti->arg3, op); - break; - } + if (event->arg1) + clen += printf(" [%3d] N=%d <%s>", (int)event->arg1, (int)ti->arg3, op); + else + clen += printf(" N=%d <%s>", (int)ti->arg3, op); + break; + } } } @@ -4262,96 +2554,110 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uint * Calculate space available to print pathname */ if (columns > MAXCOLS || wideflag) - clen = columns - (clen + 14 + 20 + 11); + clen = columns - (clen + 14 + 20 + 11); else - clen = columns - (clen + 14 + 12); + clen = columns - (clen + 14 + 12); - if (class != FILEMGR_CLASS && !nopadding) - clen -= 3; + if (!nopadding) + clen -= 3; - if (framework_name) - len = sprintf(&buf[0], " %s %s ", framework_type, framework_name); - else if (*pathname != '\0') { + if (framework_name) { + len = sprintf(&buf[0], " %s %s ", framework_type, framework_name); + } else if (*pathname != '\0') { switch(format) { case FMT_AT: case FMT_OPENAT: case FMT_CHMODAT: - len = sprintf(&buf[0], " [%d]/%s ", ti->arg1, pathname); + len = sprintf(&buf[0], " [%d]/%s ", (int)ti->arg1, pathname); break; case FMT_RENAMEAT: - len = sprintf(&buf[0], " [%d]/%s ", ti->arg3, pathname); + len = sprintf(&buf[0], " [%d]/%s ", (int)ti->arg3, pathname); break; default: len = sprintf(&buf[0], " %s ", pathname); } - if (format == FMT_MOUNT && ti->lookups[1].pathname[0]) { + if (format == FMT_MOUNT && ti->pathname2[0] != '\0') { int len2; memset(&buf[len], ' ', 2); - len2 = sprintf(&buf[len+2], " %s ", (char *)&ti->lookups[1].pathname[0]); + len2 = sprintf(&buf[len+2], " %s ", ti->pathname2); len = len + 2 + len2; } - } else - len = 0; + } else { + len = 0; + } if (clen > len) { - /* + /* * Add null padding if column length * is wider than the pathname length. */ - memset(&buf[len], ' ', clen - len); + memset(&buf[len], ' ', clen - len); buf[clen] = '\0'; pathname = buf; - } else if (clen == len) { - pathname = buf; - + pathname = buf; } else if ((clen > 0) && (clen < len)) { - /* + /* * This prints the tail end of the pathname */ - buf[len-clen] = ' '; + buf[len-clen] = ' '; pathname = &buf[len - clen]; - } else { - pathname = ""; + pathname = ""; } - + /* - * fudge some additional system call overhead + * fudge some additional system call overhead * that currently isn't tracked... this also - * insures that we see a minimum of 1 us for + * insures that we see a minimum of 1 us for * an elapsed time */ - usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor); - secs = usecs / 1000000; - usecs -= secs * 1000000; + usecs = (mach_to_nano(now - stime) + (NSEC_PER_USEC - 1)) / NSEC_PER_USEC; + secs = usecs / USEC_PER_SEC; + usecs -= secs * USEC_PER_SEC; - if (class != FILEMGR_CLASS && !nopadding) - p1 = " "; + if (!nopadding) + p1 = " "; else - p1 = ""; - + p1 = ""; + if (waited) - p2 = " W"; + p2 = " W"; else - p2 = " "; + p2 = " "; if (columns > MAXCOLS || wideflag) - printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread); + printf("%s%s %3llu.%06llu%s %s.%lu\n", p1, pathname, secs, usecs, p2, command_name, threadid); else - printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name); + printf("%s%s %3llu.%06llu%s %-12.12s\n", p1, pathname, secs, usecs, p2, command_name); + + if (!RAW_flag) + fflush(stdout); } +#pragma mark metadata info hash routines + +#define VN_HASH_SIZE 16384 +#define VN_HASH_MASK (VN_HASH_SIZE - 1) + +typedef struct meta_info { + struct meta_info *m_next; + uint64_t m_blkno; + char m_name[MAXPATHLEN]; +} *meta_info_t; + +meta_info_t m_info_hash[VN_HASH_SIZE]; void -add_meta_name(uint64_t blockno, char *pathname) { +meta_add_name(uint64_t blockno, const char *pathname) +{ meta_info_t mi; - int hashid; + int hashid; hashid = blockno & VN_HASH_MASK; @@ -4359,18 +2665,21 @@ add_meta_name(uint64_t blockno, char *pathname) { if (mi->m_blkno == blockno) break; } + if (mi == NULL) { - mi = (meta_info_t)malloc(sizeof(struct meta_info)); - + mi = malloc(sizeof (struct meta_info)); + mi->m_next = m_info_hash[hashid]; m_info_hash[hashid] = mi; mi->m_blkno = blockno; } - mi->m_nameptr = pathname; + + strncpy(mi->m_name, pathname, sizeof (mi->m_name)); } -char * -find_meta_name(uint64_t blockno) { +const char * +meta_find_name(uint64_t blockno) +{ meta_info_t mi; int hashid; @@ -4378,532 +2687,432 @@ find_meta_name(uint64_t blockno) { for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) { if (mi->m_blkno == blockno) - return (mi->m_nameptr); + return mi->m_name; } - return (""); -} - - -char * -add_vnode_name(uint64_t vn_id, char *pathname) { - vnode_info_t vn; - int hashid; - - hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK; - - for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) { - if (vn->vn_id == vn_id) - break; - } - if (vn == NULL) { - vn = (vnode_info_t)malloc(sizeof(struct vnode_info)); - - vn->vn_next = vn_info_hash[hashid]; - vn_info_hash[hashid] = vn; - vn->vn_id = vn_id; - } - strcpy(vn->vn_pathname, pathname); - return (&vn->vn_pathname); + return ""; } +void +meta_delete_all(void) +{ + meta_info_t mi, next; + int i; -char * -find_vnode_name(uint64_t vn_id) { - vnode_info_t vn; - int hashid; + for (i = 0; i < HASH_MASK; i++) { + for (mi = m_info_hash[i]; mi; mi = next) { + next = mi->m_next; - hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK; + free(mi); + } - for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) { - if (vn->vn_id == vn_id) - return (vn->vn_pathname); + m_info_hash[i] = NULL; } - return (""); } +#pragma mark event ("thread info") routines -void -delete_event(th_info_t ti_to_delete) { - th_info_t ti; - th_info_t ti_prev; - int hashid; - - hashid = ti_to_delete->thread & HASH_MASK; - - if ((ti = th_info_hash[hashid])) { - if (ti == ti_to_delete) - th_info_hash[hashid] = ti->next; - else { - ti_prev = ti; - - for (ti = ti->next; ti; ti = ti->next) { - if (ti == ti_to_delete) { - ti_prev->next = ti->next; - break; - } - ti_prev = ti; - } - } - if (ti) { - ti->next = th_info_freelist; - th_info_freelist = ti; - } - } -} +th_info_t th_info_hash[HASH_SIZE]; +th_info_t th_info_freelist; -th_info_t -add_event(uintptr_t thread, int type) { - th_info_t ti; - int i; - int hashid; +static th_info_t +add_event(ktrace_event_t event, int type) +{ + th_info_t ti; + int hashid; + unsigned long eventid; if ((ti = th_info_freelist)) th_info_freelist = ti->next; else - ti = (th_info_t)malloc(sizeof(struct th_info)); + ti = malloc(sizeof (struct th_info)); - hashid = thread & HASH_MASK; + bzero(ti, sizeof (struct th_info)); + + hashid = event->threadid & HASH_MASK; ti->next = th_info_hash[hashid]; th_info_hash[hashid] = ti; - ti->thread = thread; - ti->type = type; + eventid = event->debugid & KDBG_EVENTID_MASK; + + if (eventid == BSC_execve || eventid == BSC_posix_spawn) { + const char *command; + + command = ktrace_get_execname_for_thread(s, event->threadid); - ti->waited = 0; - ti->in_filemgr = 0; - ti->in_hfs_update = 0; + if (!command) + command = ""; - ti->pathptr = &ti->lookups[0].pathname[0]; - ti->pn_scall_index = 0; - ti->pn_work_index = 0; + strncpy(ti->command, command, sizeof (ti->command)); + ti->command[MAXCOMLEN] = '\0'; + } - for (i = 0; i < MAX_PATHNAMES; i++) - ti->lookups[i].pathname[0] = 0; + ti->thread = event->threadid; + ti->type = type; - return (ti); + return ti; } th_info_t -find_event(uintptr_t thread, int type) { - th_info_t ti; - int hashid; +event_find(uintptr_t thread, int type) +{ + th_info_t ti; + int hashid; hashid = thread & HASH_MASK; for (ti = th_info_hash[hashid]; ti; ti = ti->next) { if (ti->thread == thread) { - if (type == ti->type) - return (ti); - if (ti->in_filemgr) { - if (type == -1) - return (ti); - continue; - } + if (type == ti->type) + return ti; + if (type == 0) - return (ti); + return ti; } } - return ((th_info_t) 0); -} -void -delete_all_events() { - th_info_t ti = 0; - th_info_t ti_next = 0; - int i; - - for (i = 0; i < HASH_SIZE; i++) { - - for (ti = th_info_hash[i]; ti; ti = ti_next) { - ti_next = ti->next; - ti->next = th_info_freelist; - th_info_freelist = ti; - } - th_info_hash[i] = 0; - } + return NULL; } - void -mark_thread_waited(uintptr_t thread) { - th_info_t ti; - int hashid; - - hashid = thread & HASH_MASK; - - for (ti = th_info_hash[hashid]; ti; ti = ti->next) { - if (ti->thread == thread) - ti->waited = 1; - } -} - - -void read_command_map() +event_delete(th_info_t ti_to_delete) { - size_t size; - int i; - int total_threads = 0; - kd_threadmap *mapptr = 0; - - delete_all_map_entries(); - - if (!RAW_flag) { + th_info_t ti; + th_info_t ti_prev; + int hashid; - total_threads = bufinfo.nkdthreads; - size = bufinfo.nkdthreads * sizeof(kd_threadmap); + hashid = ti_to_delete->thread & HASH_MASK; - if (size) { - if ((mapptr = (kd_threadmap *) malloc(size))) { - int mib[6]; + if ((ti = th_info_hash[hashid])) { + if (ti == ti_to_delete) + th_info_hash[hashid] = ti->next; + else { + ti_prev = ti; - bzero (mapptr, size); - /* - * Now read the threadmap - */ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDTHRMAP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) { - /* - * This is not fatal -- just means I cant map command strings - */ - free(mapptr); - return; + for (ti = ti->next; ti; ti = ti->next) { + if (ti == ti_to_delete) { + ti_prev->next = ti->next; + break; } + ti_prev = ti; } } - } else { - RAW_header header; - off_t offset; - - RAW_fd = open(RAW_file, O_RDONLY); - - if (RAW_fd < 0) { - perror("Can't open RAW file"); - exit(1); - } - if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) { - perror("read failed"); - exit(2); + if (ti) { + ti->next = th_info_freelist; + th_info_freelist = ti; } - if (header.version_no != RAW_VERSION1) { - header.version_no = RAW_VERSION0; - header.TOD_secs = time((long *)0); - header.TOD_usecs = 0; + } +} + +void +event_delete_all(void) +{ + th_info_t ti = 0; + th_info_t ti_next = 0; + int i; - lseek(RAW_fd, (off_t)0, SEEK_SET); + for (i = 0; i < HASH_SIZE; i++) { - if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) { - perror("read failed"); - exit(2); - } + for (ti = th_info_hash[i]; ti; ti = ti_next) { + ti_next = ti->next; + ti->next = th_info_freelist; + th_info_freelist = ti; } - sample_TOD_secs = header.TOD_secs; - sample_TOD_usecs = header.TOD_usecs; + th_info_hash[i] = 0; + } +} - total_threads = header.thread_count; - size = total_threads * sizeof(kd_threadmap); +void +event_enter(int type, ktrace_event_t event) +{ + th_info_t ti; - if (size) { - if ((mapptr = (kd_threadmap *) malloc(size))) { - bzero (mapptr, size); +#if DEBUG + int index; + bool found; - if (read(RAW_fd, mapptr, size) != size) { - free(mapptr); - return; - } - } - } - if (header.version_no != RAW_VERSION0) { - offset = lseek(RAW_fd, (off_t)0, SEEK_CUR); - offset = (offset + (4095)) & ~4095; + found = false; - lseek(RAW_fd, offset, SEEK_SET); - } + switch (type) { + case P_CS_SYNC_DISK: + case MACH_pageout: + case MACH_vmfault: + case MSC_map_fd: + case SPEC_ioctl: + case Throttled: + case HFS_update: + found = true; } - for (i = 0; i < total_threads; i++) - create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]); - - free(mapptr); -} + if ((type & CSC_MASK) == BSC_BASE) { + if ((index = BSC_INDEX(type)) < MAX_BSD_SYSCALL && bsd_syscalls[index].sc_name) + found = true; + } -void delete_all_map_entries() -{ - threadmap_t tme = 0; - threadmap_t tme_next = 0; - int i; + assert(found); +#endif /* DEBUG */ - for (i = 0; i < HASH_SIZE; i++) { + if ((ti = add_event(event, type)) == NULL) + return; - for (tme = threadmap_hash[i]; tme; tme = tme_next) { - if (tme->tm_setptr) - free(tme->tm_setptr); - tme_next = tme->tm_next; - tme->tm_next = threadmap_freelist; - threadmap_freelist = tme; - } - threadmap_hash[i] = 0; - } + ti->stime = event->timestamp; + ti->arg1 = event->arg1; + ti->arg2 = event->arg2; + ti->arg3 = event->arg3; + ti->arg4 = event->arg4; } - -void create_map_entry(uintptr_t thread, int pid, char *command) +void +event_exit(char *sc_name, int type, ktrace_event_t event, int format) { - threadmap_t tme; - int hashid; + th_info_t ti; + pid_t pid; + + if ((ti = event_find(event->threadid, type)) == NULL) + return; - if ((tme = threadmap_freelist)) - threadmap_freelist = tme->tm_next; - else - tme = (threadmap_t)malloc(sizeof(struct threadmap)); + pid = ktrace_get_pid_for_thread(s, event->threadid); - tme->tm_thread = thread; - tme->tm_setsize = 0; - tme->tm_setptr = 0; + if (check_filter_mode(pid, ti, type, (int)event->arg1, (int)event->arg2, sc_name)) { + const char *pathname; - (void)strncpy (tme->tm_command, command, MAXCOMLEN); - tme->tm_command[MAXCOMLEN] = '\0'; + pathname = NULL; - hashid = thread & HASH_MASK; + /* most things are just interested in the first lookup */ + if (ti->pathname[0] != '\0') + pathname = ti->pathname; - tme->tm_next = threadmap_hash[hashid]; - threadmap_hash[hashid] = tme; + if (!pathname) + pathname = ""; - if (pid != 0 && pid != 1) { - if (!strncmp(command, "LaunchCFMA", 10)) - (void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN); + format_print(ti, sc_name, event, type, format, event->timestamp, ti->stime, ti->waited, pathname, NULL); } -} + event_delete(ti); +} -threadmap_t -find_map_entry(uintptr_t thread) +void +event_mark_thread_waited(uintptr_t thread) { - threadmap_t tme; - int hashid; + th_info_t ti; + int hashid; hashid = thread & HASH_MASK; - for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) { - if (tme->tm_thread == thread) - return (tme); + for (ti = th_info_hash[hashid]; ti; ti = ti->next) { + if (ti->thread == thread) + ti->waited = 1; } - return (0); } +#pragma mark network fd set routines -void -delete_map_entry(uintptr_t thread) +struct pid_fd_set { + struct pid_fd_set *next; + pid_t pid; + char *set; + size_t setsize; /* number of *bytes*, not bits */ +}; + +struct pid_fd_set *pfs_hash[HASH_SIZE]; + +static struct pid_fd_set * +pfs_get(pid_t pid) { - threadmap_t tme = 0; - threadmap_t tme_prev; - int hashid; - - hashid = thread & HASH_MASK; - - if ((tme = threadmap_hash[hashid])) { - if (tme->tm_thread == thread) - threadmap_hash[hashid] = tme->tm_next; - else { - tme_prev = tme; - - for (tme = tme->tm_next; tme; tme = tme->tm_next) { - if (tme->tm_thread == thread) { - tme_prev->tm_next = tme->tm_next; - break; - } - tme_prev = tme; - } - } - if (tme) { - if (tme->tm_setptr) - free(tme->tm_setptr); + struct pid_fd_set *pfs; + int hashid; - tme->tm_next = threadmap_freelist; - threadmap_freelist = tme; + assert(pid >= 0); + + hashid = pid & HASH_MASK; + + for (pfs = pfs_hash[hashid]; pfs; pfs = pfs->next) { + if (pfs->pid == pid) { + return pfs; } } -} + pfs = calloc(1, sizeof (struct pid_fd_set)); + + pfs->pid = pid; + pfs->set = NULL; + pfs->setsize = 0; + pfs->next = pfs_hash[hashid]; + pfs_hash[hashid] = pfs; + + return pfs; +} void -fs_usage_fd_set(uintptr_t thread, unsigned int fd) +fd_clear_pid(pid_t pid) { - threadmap_t tme; + struct pid_fd_set *pfs, *prev; + int hashid; - if ((tme = find_map_entry(thread)) == 0) + if (pid < 0) return; - /* - * If the map is not allocated, then now is the time - */ - if (tme->tm_setptr == (unsigned long *)0) { - if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0) - return; - - tme->tm_setsize = FS_USAGE_FD_SETSIZE; - bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))); - } - /* - * If the map is not big enough, then reallocate it - */ - while (tme->tm_setsize <= fd) { - int n; - n = tme->tm_setsize * 2; - tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n))); + hashid = pid & HASH_MASK; - bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize))); - tme->tm_setsize = n; - } - /* - * set the bit - */ - tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS)); -} + pfs = pfs_hash[hashid]; + prev = NULL; + while (pfs) { + if (pfs->pid == pid) { + if (prev) { + prev->next = pfs->next; + } else { + pfs_hash[hashid] = pfs->next; + } -/* - * Return values: - * 0 : File Descriptor bit is not set - * 1 : File Descriptor bit is set - */ -int -fs_usage_fd_isset(uintptr_t thread, unsigned int fd) -{ - threadmap_t tme; - int ret = 0; + free(pfs->set); + free(pfs); - if ((tme = find_map_entry(thread))) { - if (tme->tm_setptr && fd < tme->tm_setsize) - ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS)); + break; + } else { + prev = pfs; + pfs = pfs->next; + } } - return (ret); } - void -fs_usage_fd_clear(uintptr_t thread, unsigned int fd) +fd_clear_all(void) { - threadmap_t tme; + struct pid_fd_set *pfs, *next; + int i; - if ((tme = find_map_entry(thread))) { - if (tme->tm_setptr && fd < tme->tm_setsize) - tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS)); - } -} + for (i = 0; i < HASH_SIZE; i++) { + for (pfs = pfs_hash[i]; pfs; pfs = next) { + next = pfs->next; + free(pfs->set); + free(pfs); + } + pfs_hash[i] = NULL; + } +} void -argtopid(char *str) +fd_set_is_network(pid_t pid, unsigned long fd, bool set) { - char *cp; - int ret; - int i; + struct pid_fd_set *pfs; - ret = (int)strtol(str, &cp, 10); + if (pid < 0) + return; - if (cp == str || *cp) { - /* - * Assume this is a command string and find matching pids - */ - if (!kp_buffer) - find_proc_names(); + pfs = pfs_get(pid); - for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) { - if (kp_buffer[i].kp_proc.p_stat == 0) - continue; - else { - if (!strncmp(str, kp_buffer[i].kp_proc.p_comm, - sizeof(kp_buffer[i].kp_proc.p_comm) -1)) - pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid; - } - } - } - else if (num_of_pids < (MAX_PIDS - 1)) - pids[num_of_pids++] = ret; -} + if (fd >= pfs->setsize * CHAR_BIT) { + size_t newsize; + if (!set) return; + newsize = MAX((fd + CHAR_BIT) / CHAR_BIT, 2 * pfs->setsize); + pfs->set = reallocf(pfs->set, newsize); + assert(pfs->set); -void -lookup_name(uint64_t user_addr, char **type, char **name) -{ - int i; - int start, last; - - *name = NULL; - *type = NULL; + bzero(pfs->set + pfs->setsize, newsize - pfs->setsize); + pfs->setsize = newsize; + } - if (numFrameworks) { + if (set) + setbit(pfs->set, fd); + else + clrbit(pfs->set, fd); +} - if ((user_addr >= framework32.b_address && user_addr < framework32.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; +bool +fd_is_network(pid_t pid, unsigned long fd) +{ + struct pid_fd_set *pfs; - for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) { - if (user_addr > frameworkInfo[i].e_address) - start = i+1; - else - last = i; - } - if (start < numFrameworks && - user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) { - *type = frameworkType[frameworkInfo[start].r_type]; - *name = frameworkInfo[start].name; - } - } + if (pid < 0) + return false; + + pfs = pfs_get(pid); + + if (fd >= pfs->setsize * CHAR_BIT) { + return false; } + + return isset(pfs->set, fd); } +#pragma mark shared region address lookup routines + +#define MAXINDEX 2048 + +struct library_range { + uint64_t b_address; + uint64_t e_address; +}; + +struct library_info { + uint64_t b_address; + uint64_t e_address; + int r_type; + char *name; +}; + +struct library_range framework32 = {0, 0}; +struct library_range framework64 = {0, 0}; +struct library_range framework64h = {0, 0}; -/* - * Comparison routines for sorting - */ -static int compareFrameworkAddress(const void *aa, const void *bb) -{ - LibraryInfo *a = (LibraryInfo *)aa; - LibraryInfo *b = (LibraryInfo *)bb; +struct library_info library_infos[MAXINDEX]; +int num_libraries = 0; - if (a->b_address < b->b_address) return -1; - if (a->b_address == b->b_address) return 0; - return 1; -} +#define TEXT_R 0 +#define DATA_R 1 +#define OBJC_R 2 +#define IMPORT_R 3 +#define UNICODE_R 4 +#define IMAGE_R 5 +#define LINKEDIT_R 6 +static void +sort_library_addresses(void) +{ + library_infos[num_libraries].b_address = library_infos[num_libraries - 1].b_address + 0x800000; + library_infos[num_libraries].e_address = library_infos[num_libraries].b_address; + library_infos[num_libraries].name = NULL; + + qsort_b(library_infos, num_libraries, sizeof (struct library_info), ^int(const void *aa, const void *bb) { + struct library_info *a = (struct library_info *)aa; + struct library_info *b = (struct library_info *)bb; + + if (a->b_address < b->b_address) return -1; + if (a->b_address == b->b_address) return 0; + return 1; + }); +} -int scanline(char *inputstring, char **argv, int maxtokens) +static int +scanline(char *inputstring, char **argv, int maxtokens) { int n = 0; char **ap = argv, *p, *val; for (p = inputstring; n < maxtokens && p != NULL; ) { - - while ((val = strsep(&p, " \t")) != NULL && *val == '\0'); + while ((val = strsep(&p, " \t")) != NULL && *val == '\0') ; *ap++ = val; n++; } + *ap = 0; return n; } - -int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) +static int +read_shared_cache_map(const char *path, struct library_range *lr, char *linkedit_name) { uint64_t b_address, e_address; char buf[1024]; - char *fnp; + char *fnp, *fn_tofree; FILE *fd; char frameworkName[256]; char *tokens[64]; @@ -4925,21 +3134,22 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) if (strncmp(buf, "mapping", 7)) break; } + buf[strlen(buf)-1] = 0; - + frameworkName[0] = 0; for (;;) { /* * Extract lib name from path name */ - if ((substring = strrchr(buf, '.'))) - { + if ((substring = strrchr(buf, '.'))) { /* - * There is a ".": name is whatever is between the "/" around the "." + * There is a ".": name is whatever is between the "/" around the "." */ while ( *substring != '/') /* find "/" before "." */ substring--; + substring++; strncpy(frameworkName, substring, 256); /* copy path from "/" */ @@ -4948,10 +3158,9 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */ substring++; + *substring = 0; - } - else - { + } else { /* * No ".": take segment after last "/" */ @@ -4963,13 +3172,16 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) substring = ptr + 1; ptr++; } + strncpy(frameworkName, substring, 256); frameworkName[255] = 0; } - fnp = (char *)malloc(strlen(frameworkName) + 1); + + fnp = malloc(strlen(frameworkName) + 1); + fn_tofree = fnp; strcpy(fnp, frameworkName); - while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) { + while (fgets(buf, 1023, fd) && num_libraries < (MAXINDEX - 2)) { /* * Get rid of EOL */ @@ -5004,15 +3216,17 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) b_address = strtoull(tokens[1], 0, 16); e_address = strtoull(tokens[3], 0, 16); - frameworkInfo[numFrameworks].b_address = b_address; - frameworkInfo[numFrameworks].e_address = e_address; - frameworkInfo[numFrameworks].r_type = type; - + library_infos[num_libraries].b_address = b_address; + library_infos[num_libraries].e_address = e_address; + library_infos[num_libraries].r_type = type; + if (type == LINKEDIT_R) { - frameworkInfo[numFrameworks].name = linkedit_name; + library_infos[num_libraries].name = linkedit_name; linkedit_found = 1; - } else - frameworkInfo[numFrameworks].name = fnp; + } else { + library_infos[num_libraries].name = fnp; + fn_tofree = NULL; + } #if 0 printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address); #endif @@ -5022,16 +3236,21 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) if (lr->e_address == 0 || e_address > lr->e_address) lr->e_address = e_address; - numFrameworks++; + num_libraries++; } + if (type == LINKEDIT_R) break; } + + free(fn_tofree); + if (fgets(buf, 1023, fd) == 0) break; buf[strlen(buf)-1] = 0; } + fclose(fd); #if 0 @@ -5040,74 +3259,131 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) return 1; } +void +init_shared_cache_mapping(void) +{ + read_shared_cache_map("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386"); + + if (0 == read_shared_cache_map("/var/db/dyld/dyld_shared_cache_x86_64h.map", &framework64h, "/var/db/dyld/dyld_shared_cache_x86_64h")) { + read_shared_cache_map("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64"); + } + + sort_library_addresses(); +} void -SortFrameworkAddresses() +lookup_name(uint64_t user_addr, char **type, char **name) { + int i; + int start, last; + + static char *frameworkType[] = { + " ", + " ", + " ", + " ", + " ", + " ", + "", + }; + + *name = NULL; + *type = NULL; + + if (num_libraries) { + if ((user_addr >= framework32.b_address && user_addr < framework32.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 = num_libraries; - frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000; - frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address; - frameworkInfo[numFrameworks].name = (char *)0; + for (i = num_libraries / 2; start < last; i = start + ((last - start) / 2)) { + if (user_addr > library_infos[i].e_address) + start = i+1; + else + last = i; + } - qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress); + if (start < num_libraries && + user_addr >= library_infos[start].b_address && user_addr < library_infos[start].e_address) { + *type = frameworkType[library_infos[start].r_type]; + *name = library_infos[start].name; + } + } + } } +#pragma mark disk I/O tracking routines -struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime) +struct diskio *free_diskios = NULL; +struct diskio *busy_diskios = NULL; + +struct diskio * +diskio_start(unsigned long type, unsigned long bp, unsigned long dev, + unsigned long blkno, unsigned long iosize, ktrace_event_t event) { - struct diskio *dio; - threadmap_t tme; - - if ((dio = free_diskios)) + const char *command; + struct diskio *dio; + + if ((dio = free_diskios)) { free_diskios = dio->next; - else { - if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL) - return (NULL); + } else { + dio = malloc(sizeof (struct diskio)); } + dio->prev = NULL; - + dio->type = type; dio->bp = bp; dio->dev = dev; dio->blkno = blkno; - dio->iosize = io_size; - dio->issued_time = curtime; - dio->issuing_thread = thread; - + dio->iosize = iosize; + dio->issued_time = event->timestamp; + dio->issuing_thread = event->threadid; + dio->issuing_pid = ktrace_get_pid_for_thread(s, event->threadid); + dio->bc_info = 0x0; - - if ((tme = find_map_entry(thread))) { - strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN); - dio->issuing_command[MAXCOMLEN] = '\0'; - } else - strcpy(dio->issuing_command, ""); - + + command = ktrace_get_execname_for_thread(s, event->threadid); + + if (!command) + command = ""; + + strncpy(dio->issuing_command, command, MAXCOMLEN); + dio->issuing_command[MAXCOMLEN] = '\0'; + dio->next = busy_diskios; + if (dio->next) dio->next->prev = dio; + busy_diskios = dio; - return (dio); + return dio; } -struct diskio *find_diskio(int bp) { +struct diskio * +diskio_find(unsigned long bp) +{ struct diskio *dio; - + for (dio = busy_diskios; dio; dio = dio->next) { if (dio->bp == bp) - return (dio); + return dio; } - + return NULL; } - -struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime) +struct diskio * +diskio_complete(unsigned long bp, unsigned long io_errno, unsigned long resid, + uintptr_t thread, uint64_t curtime, struct timeval curtime_wall) { struct diskio *dio; - - if ((dio = find_diskio(bp)) == NULL) return NULL; - + + if ((dio = diskio_find(bp)) == NULL) return NULL; + if (dio == busy_diskios) { if ((busy_diskios = dio->next)) dio->next->prev = NULL; @@ -5120,24 +3396,25 @@ struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread dio->iosize -= resid; dio->io_errno = io_errno; dio->completed_time = curtime; + dio->completed_walltime = curtime_wall; dio->completion_thread = thread; - + return dio; } - -void free_diskio(struct diskio *dio) +void +diskio_free(struct diskio *dio) { dio->next = free_diskios; free_diskios = dio; } - -void print_diskio(struct diskio *dio) +void +diskio_print(struct diskio *dio) { char *p = NULL; int len = 0; - int type; + unsigned long type; int format = FMT_DISKIO; char buf[64]; @@ -5145,86 +3422,88 @@ void print_diskio(struct diskio *dio) dio->is_meta = 0; if ((type & P_CS_Class) == P_CS_Class) { - switch (type) { - - case P_CS_ReadChunk: - p = " RdChunkCS"; - len = 13; - format = FMT_DISKIO_CS; - break; - case P_CS_WriteChunk: - p = " WrChunkCS"; - len = 13; - format = FMT_DISKIO_CS; - break; - case P_CS_MetaRead: - p = " RdMetaCS"; - len = 10; - format = FMT_DISKIO_CS; - break; - case P_CS_MetaWrite: - p = " WrMetaCS"; - len = 10; - format = FMT_DISKIO_CS; - break; - case P_CS_TransformRead: - p = " RdBgTfCS"; - len = 10; - break; - case P_CS_TransformWrite: - p = " WrBgTfCS"; - len = 10; - break; - case P_CS_MigrationRead: - p = " RdBgMigrCS"; - len = 12; - break; - case P_CS_MigrationWrite: - p = " WrBgMigrCS"; - len = 12; - break; + case P_CS_ReadChunk: + p = " RdChunkCS"; + len = 13; + format = FMT_DISKIO_CS; + break; + case P_CS_WriteChunk: + p = " WrChunkCS"; + len = 13; + format = FMT_DISKIO_CS; + break; + case P_CS_MetaRead: + p = " RdMetaCS"; + len = 10; + format = FMT_DISKIO_CS; + break; + case P_CS_MetaWrite: + p = " WrMetaCS"; + len = 10; + format = FMT_DISKIO_CS; + break; + case P_CS_TransformRead: + p = " RdBgTfCS"; + len = 10; + break; + case P_CS_TransformWrite: + p = " WrBgTfCS"; + len = 10; + break; + case P_CS_MigrationRead: + p = " RdBgMigrCS"; + len = 12; + break; + case P_CS_MigrationWrite: + p = " WrBgMigrCS"; + len = 12; + break; + default: + p = " CS"; + len = 4; + break; } + strncpy(buf, p, len); } else { - switch (type & P_DISKIO_TYPE) { - - case P_RdMeta: - dio->is_meta = 1; - p = " RdMeta"; - len = 8; - break; - case P_WrMeta: - dio->is_meta = 1; - p = " WrMeta"; - len = 8; - break; - case P_RdData: - p = " RdData"; - len = 8; - break; - case P_WrData: - p = " WrData"; - len = 8; - break; - case P_PgIn: - p = " PgIn"; - len = 6; - break; - case P_PgOut: - p = " PgOut"; - len = 7; - break; - default: - p = " "; - len = 2; - break; + case P_RdMeta: + dio->is_meta = 1; + p = " RdMeta"; + len = 8; + break; + case P_WrMeta: + dio->is_meta = 1; + p = " WrMeta"; + len = 8; + break; + case P_RdData: + p = " RdData"; + len = 8; + break; + case P_WrData: + p = " WrData"; + len = 8; + break; + case P_PgIn: + p = " PgIn"; + len = 6; + break; + case P_PgOut: + p = " PgOut"; + len = 7; + break; + default: + p = " "; + len = 2; + break; } + strncpy(buf, p, len); buf[len++] = '['; - + if (type & P_DISKIO_ASYNC) buf[len++] = 'A'; else @@ -5234,6 +3513,7 @@ void print_diskio(struct diskio *dio) buf[len++] = 'N'; int tier = (type & P_DISKIO_TIER_MASK) >> P_DISKIO_TIER_SHIFT; + if (tier > 0) { buf[len++] = 'T'; if (tier > 0 && tier < 10) @@ -5243,57 +3523,67 @@ void print_diskio(struct diskio *dio) if (type & P_DISKIO_PASSIVE) buf[len++] = 'P'; - buf[len++] = ']'; } + buf[len] = 0; - if (check_filter_mode(NULL, type, 0, 0, buf)) - format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio); + if (check_filter_mode(-1, NULL, type, 0, 0, buf)) + format_print(NULL, buf, NULL, type, format, dio->completed_time, dio->issued_time, 1, "", dio); } +#pragma mark disk name routines + +struct diskrec { + struct diskrec *next; + char *diskname; + int dev; +}; + +struct diskrec *disk_list = NULL; -void cache_disk_names() +void +cache_disk_names(void) { struct stat st; DIR *dirp = NULL; struct dirent *dir; struct diskrec *dnp; - if ((dirp = opendir("/dev")) == NULL) return; - + while ((dir = readdir(dirp)) != NULL) { char nbuf[MAXPATHLEN]; - + if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4)) continue; snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name); - + if (stat(nbuf, &st) < 0) continue; - if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL) + if ((dnp = malloc(sizeof(struct diskrec))) == NULL) continue; - - if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) { + + if ((dnp->diskname = malloc(dir->d_namlen + 1)) == NULL) { free(dnp); continue; } strncpy(dnp->diskname, dir->d_name, dir->d_namlen); dnp->diskname[dir->d_namlen] = 0; dnp->dev = st.st_rdev; - + dnp->next = disk_list; disk_list = dnp; } - (void) closedir(dirp); -} + closedir(dirp); +} -void recache_disk_names() +static void +recache_disk_names(void) { struct diskrec *dnp, *next_dnp; @@ -5303,23 +3593,23 @@ void recache_disk_names() free(dnp->diskname); free(dnp); } - disk_list = NULL; + disk_list = NULL; cache_disk_names(); } - -char *find_disk_name(int dev) +char * +find_disk_name(unsigned long dev) { struct diskrec *dnp; int i; - + if (dev == NFS_DEV) return ("NFS"); - + if (dev == CS_DEV) return ("CS"); - + for (i = 0; i < 2; i++) { for (dnp = disk_list; dnp; dnp = dnp->next) { if (dnp->dev == dev) @@ -5327,300 +3617,17 @@ char *find_disk_name(int dev) } recache_disk_names(); } - return ("NOTFOUND"); -} - - -char *generate_cs_disk_name(int dev, char *s) -{ - if (dev == -1) - return ("UNKNOWN"); - - sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff); - - return (s); -} - - - -/* - * ret = 1 means print the entry - * ret = 0 means don't print the entry - */ - -/* - * meaning of filter flags: - * cachehit turn on display of CACHE_HIT events (which are filtered out by default) - * - * exec show exec/posix_spawn - * pathname show events with a pathname and close() - * diskio show disk I/Os - * filesys show filesystem events - * network show network events - * - * filters may be combined; default is all filters on (except cachehit) - */ -int -check_filter_mode(struct th_info *ti, int type, int error, int retval, char *sc_name) -{ - int ret = 0; - int network_fd_isset = 0; - unsigned int fd; - - /* cachehit is special -- it's not on by default */ - if (sc_name[0] == 'C' && !strcmp(sc_name, "CACHE_HIT")) { - if (show_cachehits) return 1; - else return 0; - } - - if (filter_mode == DEFAULT_DO_NOT_FILTER) - return(1); - - if (filter_mode & DISKIO_FILTER) { - if ((type & P_DISKIO_MASK) == P_DISKIO) - return 1; - } - - if (filter_mode & EXEC_FILTER) { - if (type == BSC_execve || type == BSC_posix_spawn) - return(1); - } - - if (filter_mode & PATHNAME_FILTER) { - if (ti && ti->lookups[0].pathname[0]) - return(1); - if (type == BSC_close || type == BSC_close_nocancel || - type == BSC_guarded_close_np) - return(1); - } - - if (ti == (struct th_info *)0) { - if (filter_mode & FILESYS_FILTER) - return(1); - return(0); - } - - switch (type) { - - case BSC_close: - case BSC_close_nocancel: - case BSC_guarded_close_np: - fd = ti->arg1; - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - - if (error == 0) - fs_usage_fd_clear(ti->thread,fd); - - if (network_fd_isset) { - if (filter_mode & NETWORK_FILTER) - ret = 1; - } else - if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - - case BSC_read: - case BSC_write: - case BSC_read_nocancel: - case BSC_write_nocancel: - /* - * we don't care about error in these cases - */ - fd = ti->arg1; - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - - if (network_fd_isset) { - if (filter_mode & NETWORK_FILTER) - ret = 1; - } else - if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - - case BSC_accept: - case BSC_accept_nocancel: - case BSC_socket: - fd = retval; - - if (error == 0) - fs_usage_fd_set(ti->thread, fd); - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - - case BSC_recvfrom: - case BSC_sendto: - case BSC_recvmsg: - case BSC_sendmsg: - case BSC_connect: - case BSC_bind: - case BSC_listen: - case BSC_sendto_nocancel: - case BSC_recvfrom_nocancel: - case BSC_recvmsg_nocancel: - case BSC_sendmsg_nocancel: - case BSC_connect_nocancel: - fd = ti->arg1; - - if (error == 0) - fs_usage_fd_set(ti->thread, fd); - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - - case BSC_select: - case BSC_select_nocancel: - case BSC_socketpair: - /* - * Cannot determine info about file descriptors - */ - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - - case BSC_dup: - case BSC_dup2: - /* - * We track these cases for fd state only - */ - fd = ti->arg1; - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - - if (error == 0 && network_fd_isset) { - /* - * then we are duping a socket descriptor - */ - fd = retval; /* the new fd */ - fs_usage_fd_set(ti->thread, fd); - } - break; - - default: - if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - } - - return(ret); -} - -/* - * Allocate a buffer that is large enough to hold the maximum arguments - * to execve(). This is used when getting the arguments to programs - * when we see LaunchCFMApps. If this fails, it is not fatal, we will - * simply not resolve the command name. - */ - -void -init_arguments_buffer() -{ - int mib[2]; - size_t size; - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - size = sizeof(argmax); - - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) - return; -#if 1 - /* Hack to avoid kernel bug. */ - if (argmax > 8192) { - argmax = 8192; - } -#endif - arguments = (char *)malloc(argmax); + return "NOTFOUND"; } - -int -get_real_command_name(int pid, char *cbuf, int csize) +char * +generate_cs_disk_name(unsigned long dev, char *s) { - /* - * Get command and arguments. - */ - char *cp; - int mib[4]; - char *command_beg, *command, *command_end; - - if (cbuf == NULL) - return(0); - - if (arguments) - bzero(arguments, argmax); - else - return(0); - - /* - * A sysctl() is made to find out the full path that the command - * was called with. - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - mib[3] = 0; - - if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) - return(0); - - /* - * Skip the saved exec_path - */ - for (cp = arguments; cp < &arguments[argmax]; cp++) { - if (*cp == '\0') { - /* - * End of exec_path reached - */ - break; - } - } - if (cp == &arguments[argmax]) - return(0); - - /* - * Skip trailing '\0' characters - */ - for (; cp < &arguments[argmax]; cp++) { - if (*cp != '\0') { - /* - * Beginning of first argument reached - */ - break; - } - } - if (cp == &arguments[argmax]) - return(0); - - command_beg = cp; - /* - * Make sure that the command is '\0'-terminated. This protects - * against malicious programs; under normal operation this never - * ends up being a problem.. - */ - for (; cp < &arguments[argmax]; cp++) { - if (*cp == '\0') { - /* - * End of first argument reached - */ - break; - } - } - if (cp == &arguments[argmax]) - return(0); - - command_end = command = cp; + if (dev == -1) + return "UNKNOWN"; - /* - * Get the basename of command - */ - for (command--; command >= command_beg; command--) { - if (*command == '/') { - command++; - break; - } - } - (void) strncpy(cbuf, (char *)command, csize); - cbuf[csize-1] = '\0'; + sprintf(s, "disk%lus%lu", (dev >> 16) & 0xffff, dev & 0xffff); - return(1); + return (s); } diff --git a/gcore.tproj/corefile.c b/gcore.tproj/corefile.c new file mode 100644 index 0000000..addcda4 --- /dev/null +++ b/gcore.tproj/corefile.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "corefile.h" +#include "sparse.h" +#include "utils.h" +#include "vm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +native_mach_header_t * +make_corefile_mach_header(void *data) +{ + native_mach_header_t *mh = data; + mh->magic = NATIVE_MH_MAGIC; + mh->filetype = MH_CORE; +#if defined(__LP64__) + const int is64 = 1; +#else + const int is64 = 0; +#endif +#if defined(__i386__) || defined(__x86_64__) + mh->cputype = is64 ? CPU_TYPE_X86_64 : CPU_TYPE_I386; + mh->cpusubtype = is64 ? CPU_SUBTYPE_X86_64_ALL : CPU_SUBTYPE_I386_ALL; +#elif defined(__arm__) || defined(__arm64__) + mh->cputype = is64 ? CPU_TYPE_ARM64 : CPU_TYPE_ARM; + mh->cpusubtype = is64 ? CPU_SUBTYPE_ARM64_ALL : CPU_SUBTYPE_ARM_ALL; +#else +#error undefined +#endif + return mh; +} + +struct proto_coreinfo_command * +make_coreinfo_command(native_mach_header_t *mh, void *data, const uuid_t aoutid, uint64_t address, uint64_t dyninfo) +{ + struct proto_coreinfo_command *cc = data; + cc->cmd = proto_LC_COREINFO; + cc->cmdsize = sizeof (*cc); + cc->version = 1; + cc->type = proto_CORETYPE_USER; + cc->address = address; + uuid_copy(cc->uuid, aoutid); + cc->dyninfo = dyninfo; + mach_header_inc_ncmds(mh, 1); + mach_header_inc_sizeofcmds(mh, cc->cmdsize); + return cc; +} + +static native_segment_command_t * +make_native_segment_command(void *data, mach_vm_offset_t vmaddr, mach_vm_size_t vmsize, off_t fileoff, size_t filesize, unsigned maxprot, unsigned initprot, unsigned comptype) +{ + native_segment_command_t *sc = data; + sc->cmd = NATIVE_LC_SEGMENT; + sc->cmdsize = sizeof (*sc); + assert(vmsize); +#if defined(__LP64__) + sc->vmaddr = vmaddr; + sc->vmsize = vmsize; + sc->fileoff = fileoff; +#else + sc->vmaddr = (uintptr_t)vmaddr; + sc->vmsize = (size_t)vmsize; + sc->fileoff = (long)fileoff; +#endif + sc->filesize = filesize; + sc->maxprot = maxprot; + sc->initprot = initprot; + sc->nsects = 0; + sc->flags = proto_SG_COMP_MAKE_FLAGS(comptype); + return sc; +} + +/* + * Increment the mach-o header data when we succeed + */ +static void +commit_load_command(struct write_segment_data *wsd, const struct load_command *lc) +{ + wsd->wsd_lc = (caddr_t)lc + lc->cmdsize; + native_mach_header_t *mh = wsd->wsd_mh; + mach_header_inc_ncmds(mh, 1); + mach_header_inc_sizeofcmds(mh, lc->cmdsize); +} + +#pragma mark -- Regions written as "file references" -- + +static size_t +cmdsize_fileref_command(const char *nm) +{ + size_t cmdsize = sizeof (struct proto_fileref_command); + size_t len; + if (0 != (len = strlen(nm))) { + len++; // NUL-terminated for mmap sanity + cmdsize += roundup(len, sizeof (long)); + } + return cmdsize; +} + +static void +size_fileref_subregion(const struct subregion *s, struct size_core *sc) +{ + assert(S_LIBENT(s)); + + size_t cmdsize = cmdsize_fileref_command(S_PATHNAME(s)); + sc->headersize += cmdsize; + sc->count++; + sc->memsize += S_SIZE(s); +} + +#ifdef CONFIG_REFSC +static void +size_fileref_region(const struct region *r, struct size_core *sc) +{ + assert(0 == r->r_nsubregions); + assert(!r->r_inzfodregion); + + size_t cmdsize = cmdsize_fileref_command(r->r_fileref->fr_libent->le_pathname); + sc->headersize += cmdsize; + sc->count++; + sc->memsize += R_SIZE(r); +} +#endif + +static struct proto_fileref_command * +make_fileref_command(void *data, const struct libent *le, mach_vm_offset_t vmaddr, mach_vm_size_t vmsize, off_t fileoff, off_t filesize, unsigned maxprot, unsigned initprot) +{ + struct proto_fileref_command *fr = data; + size_t len; + + fr->cmd = proto_LC_FILEREF; + fr->cmdsize = sizeof (*fr); + if (0 != (len = strlen(le->le_pathname))) { + /* + * Strings live immediately after the + * command, and are included in the cmdsize + */ + fr->filename.offset = sizeof (*fr); + void *s = fr + 1; + strlcpy(s, le->le_pathname, ++len); // NUL-terminated for mmap sanity + fr->cmdsize += roundup(len, sizeof (long)); + assert(cmdsize_fileref_command(le->le_pathname) == fr->cmdsize); + } + uuid_copy(fr->uuid, le->le_uuid); + + fr->vmaddr = vmaddr; + + assert(vmsize); + fr->vmsize = vmsize; + assert(fileoff >= 0); + fr->fileoff = fileoff; + fr->filesize = filesize; + + assert(maxprot & VM_PROT_READ); + fr->maxprot = maxprot; + fr->initprot = initprot; + return fr; +} + +/* + * It's almost always more efficient to write out a reference to the + * data than write out the data itself. + */ +static walk_return_t +write_fileref_subregion(const struct region *r, const struct subregion *s, struct write_segment_data *wsd) +{ + assert(S_LIBENT(s)); + if (opt->debug && !issubregiontype(s, SEG_TEXT) && !issubregiontype(s, SEG_LINKEDIT)) + printf("%s: unusual segment type %s from %s\n", __func__, S_MACHO_TYPE(s), S_FILENAME(s)); + assert((r->r_info.max_protection & VM_PROT_READ) == VM_PROT_READ); + assert((r->r_info.protection & VM_PROT_WRITE) == 0); + + const struct libent *le = S_LIBENT(s); + const struct proto_fileref_command *fc = make_fileref_command(wsd->wsd_lc, le, S_ADDR(s), S_SIZE(s), S_MACHO_FILEOFF(s), S_SIZE(s), r->r_info.max_protection, r->r_info.protection); + commit_load_command(wsd, (const void *)fc); + if (opt->debug > 1) { + hsize_str_t hstr; + printr(r, "ref '%s' %s (vm %llx-%llx, file offset %lld for %s)\n", S_FILENAME(s), S_MACHO_TYPE(s), (uint64_t)fc->vmaddr, (uint64_t)fc->vmaddr + fc->vmsize, (int64_t)fc->fileoff, str_hsize(hstr, fc->filesize)); + } + return WALK_CONTINUE; +} + +#ifdef CONFIG_REFSC + +/* + * Note that we may be asked to write reference segments whose protections + * are rw- -- this -should- be ok as we don't convert the region to a file + * reference unless we know it hasn't been modified. + */ +static walk_return_t +write_fileref_region(const struct region *r, struct write_segment_data *wsd) +{ + assert(0 == r->r_nsubregions); + assert(r->r_info.user_tag != VM_MEMORY_IOKIT); + assert((r->r_info.max_protection & VM_PROT_READ) == VM_PROT_READ); + assert(!r->r_inzfodregion); + + const struct libent *le = r->r_fileref->fr_libent; + const struct proto_fileref_command *fc = make_fileref_command(wsd->wsd_lc, le, R_ADDR(r), R_SIZE(r), r->r_fileref->fr_offset, (size_t)R_SIZE(r), r->r_info.max_protection, r->r_info.protection); + commit_load_command(wsd, (const void *)fc); + if (opt->debug > 1) { + hsize_str_t hstr; + printr(r, "ref '%s' %s (vm %llx-%llx, file offset %lld for %s)\n", le->le_filename, "(type?)", (uint64_t)fc->vmaddr, (uint64_t)fc->vmaddr + fc->vmsize, (int64_t)fc->fileoff, str_hsize(hstr, fc->filesize)); + } + return WALK_CONTINUE; +} + +const struct regionop fileref_ops = { + print_memory_region, + write_fileref_region, + del_fileref_region, +}; + +#endif /* CONFIG_REFSC */ + +#pragma mark -- ZFOD segments written only to the header -- + +static void +size_zfod_region(const struct region *r, struct size_core *sc) +{ + assert(0 == r->r_nsubregions); + assert(r->r_inzfodregion); + sc->headersize += sizeof (native_segment_command_t); + sc->count++; + sc->memsize += R_SIZE(r); +} + +static walk_return_t +write_zfod_region(const struct region *r, struct write_segment_data *wsd) +{ + assert(r->r_info.user_tag != VM_MEMORY_IOKIT); + assert((r->r_info.max_protection & VM_PROT_READ) == VM_PROT_READ); + + const void *sc = make_native_segment_command(wsd->wsd_lc, R_ADDR(r), R_SIZE(r), wsd->wsd_foffset, 0, r->r_info.max_protection, r->r_info.protection, 0); + commit_load_command(wsd, sc); + return WALK_CONTINUE; +} + +const struct regionop zfod_ops = { + print_memory_region, + write_zfod_region, + del_zfod_region, +}; + +#pragma mark -- Regions containing data -- + +static walk_return_t +pwrite_memory(struct write_segment_data *wsd, const void *addr, size_t size, mach_vm_offset_t memaddr, size_t memsize) +{ + assert(size); + + int error = 0; + ssize_t nwritten = 0; + + if (opt->sizebound > 0 && + wsd->wsd_foffset + (off_t)size > opt->sizebound) { + error = EFBIG; + } else { + nwritten = pwrite(wsd->wsd_fd, addr, size, wsd->wsd_foffset); + if (nwritten < 0) + error = errno; + } + + if (error || opt->debug > 1) { + hsize_str_t hsz; + printf("%llx-%llx writing %ld bytes at offset %lld -> ", + memaddr, memaddr+memsize, size, wsd->wsd_foffset); + if (error) + printf("err #%d - %s ", error, strerror(error)); + else { + printf("%s ", str_hsize(hsz, nwritten)); + if (size != (size_t)nwritten) + printf("[%zd - incomplete write!] ", nwritten); + else if (size != memsize) + printf("(%s in memory) ", + str_hsize(hsz, memsize)); + } + printf("\n"); + } + + walk_return_t step = WALK_CONTINUE; + switch (error) { + case 0: + if (size != (size_t)nwritten) + step = WALK_ERROR; + else { + wsd->wsd_foffset += nwritten; + wsd->wsd_nwritten += nwritten; + } + break; + case EFAULT: // transient mapping failure? + break; + default: // EROFS, ENOSPC, EFBIG etc. */ + step = WALK_ERROR; + break; + } + return step; +} + + +/* + * Write a contiguous range of memory into the core file. + * Apply compression, and chunk if necessary. + */ +static int +segment_compflags(compression_algorithm ca, unsigned *algnum) +{ + switch (ca) { + case COMPRESSION_LZ4: + *algnum = proto_SG_COMP_LZ4; + break; + case COMPRESSION_ZLIB: + *algnum = proto_SG_COMP_ZLIB; + break; + case COMPRESSION_LZMA: + *algnum = proto_SG_COMP_LZMA; + break; + case COMPRESSION_LZFSE: + *algnum = proto_SG_COMP_LZFSE; + break; + default: + err(EX_SOFTWARE, "unsupported compression algorithm %x", ca); + } + return 0; +} + +static walk_return_t +write_memory_range(struct write_segment_data *wsd, const struct region *r, mach_vm_offset_t vmaddr, mach_vm_offset_t vmsize) +{ + assert(R_ADDR(r) <= vmaddr && R_ENDADDR(r) >= vmaddr + vmsize); + + mach_vm_offset_t resid = vmsize; + walk_return_t step = WALK_CONTINUE; + + do { + unsigned algorithm = 0; + void *dstbuf = NULL; + size_t filesize; + + vmsize = resid; + + /* + * Since some regions can be inconveniently large, + * chop them into multiple chunks as we compress them. + * (mach_vm_read has 32-bit limitations too). + */ + vmsize = vmsize > INT32_MAX ? INT32_MAX : vmsize; + if (opt->chunksize > 0 && vmsize > opt->chunksize) + vmsize = opt->chunksize; + assert(vmsize <= INT32_MAX); + + mach_vm_offset_t data; + mach_vm_offset_t data_count; + + kern_return_t kr; + const void *srcaddr; + + if (r->r_incommregion) { + /* + * For commpage access, we just copy from our own address space. + */ + data = 0; + data_count = vmsize; + kr = mach_vm_allocate(mach_task_self(), &data, data_count, VM_FLAGS_ANYWHERE); + if (KERN_SUCCESS != kr || data == 0) { + err_mach(kr, r, "subregion %llx-%llx, mach_vm_allocate()", vmaddr, vmaddr + vmsize); + if (opt->debug) { + print_memory_region_header(); + ROP_PRINT(r); + } + break; + } + if (opt->debug) + printr(r, "subregion %llx-%llx, copying from self\n", vmaddr, vmaddr+vmsize); + srcaddr = (const void *)memcpy((void *)data, (void *)vmaddr, vmsize); + } else { + /* + * Most segments with data are mapped here + */ + vm_offset_t data32 = 0; + mach_msg_type_number_t data32_count; + kr = mach_vm_read(wsd->wsd_task, vmaddr, vmsize, &data32, &data32_count); + if (KERN_SUCCESS != kr || data32 == 0 || data32_count < vmsize) { + err_mach(kr, r, "subregion %llx-%llx, mach_vm_read()", vmaddr, vmaddr + vmsize); + if (opt->debug) { + print_memory_region_header(); + ROP_PRINT(r); + } + break; + } + data = data32; + data_count = data32_count; + mach_vm_behavior_set(mach_task_self(), data, data_count, VM_BEHAVIOR_SEQUENTIAL); + srcaddr = (const void *)data; + } + + assert(vmsize); + + if (opt->compress) { + dstbuf = malloc((size_t)vmsize); + if (dstbuf) { + + filesize = compression_encode_buffer(dstbuf, (size_t)vmsize, srcaddr, (size_t)vmsize, NULL, opt->calgorithm); + + if (filesize > 0 && filesize < vmsize) { + srcaddr = dstbuf; + if (segment_compflags(opt->calgorithm, &algorithm) != 0) { + free(dstbuf); + mach_vm_deallocate(mach_task_self(), data, data_count); + return WALK_ERROR; + } + } else { + free(dstbuf); + dstbuf = NULL; + filesize = (size_t)vmsize; + } + } else + filesize = (size_t)vmsize; + } else + filesize = (size_t)vmsize; + + assert(filesize); + + native_segment_command_t *sc = make_native_segment_command(wsd->wsd_lc, vmaddr, vmsize, wsd->wsd_foffset, filesize, r->r_info.max_protection, r->r_info.protection, algorithm); + + assert((sc->flags == 0) ^ (sc->filesize < sc->vmsize)); + + step = pwrite_memory(wsd, srcaddr, sc->filesize, vmaddr, sc->vmsize); + if (dstbuf) + free(dstbuf); + mach_vm_deallocate(mach_task_self(), data, data_count); + + if (WALK_ERROR == step) + break; + commit_load_command(wsd, (const void *)sc); + resid -= vmsize; + vmaddr += vmsize; + } while (resid); + + return step; +} + +#ifdef RDAR_23744374 +/* + * Sigh. This is a workaround. + * Find the vmsize as if the VM system manages ranges in host pagesize units + * rather than application pagesize units. + */ +static mach_vm_size_t +getvmsize_host(const task_t task, const struct region *r) +{ + mach_vm_size_t vmsize_host = R_SIZE(r); + + if (pageshift_host != pageshift_app) { + is_actual_size(task, r, &vmsize_host); + if (opt->debug && R_SIZE(r) != vmsize_host) + printr(r, "(region size tweak: was %llx, is %llx)\n", R_SIZE(r), vmsize_host); + } + return vmsize_host; +} +#else +static __inline mach_vm_size_t +getvmsize_host(__unused const task_t task, const struct region *r) +{ + return R_SIZE(r); +} +#endif + +static walk_return_t +write_sparse_region(const struct region *r, struct write_segment_data *wsd) +{ + assert(r->r_nsubregions); + assert(!r->r_inzfodregion); +#ifdef CONFIG_REFSC + assert(NULL == r->r_fileref); +#endif + + const mach_vm_size_t vmsize_host = getvmsize_host(wsd->wsd_task, r); + walk_return_t step = WALK_CONTINUE; + + for (unsigned i = 0; i < r->r_nsubregions; i++) { + const struct subregion *s = r->r_subregions[i]; + + if (s->s_isfileref) + step = write_fileref_subregion(r, s, wsd); + else { + /* Write this one out as real data */ + mach_vm_size_t vmsize = S_SIZE(s); + if (R_SIZE(r) != vmsize_host) { + if (S_ADDR(s) + vmsize > R_ADDR(r) + vmsize_host) { + vmsize = R_ADDR(r) + vmsize_host - S_ADDR(s); + if (opt->debug) + printr(r, "(subregion size tweak: was %llx, is %llx)\n", + S_SIZE(s), vmsize); + } + } + step = write_memory_range(wsd, r, S_ADDR(s), vmsize); + } + if (WALK_ERROR == step) + break; + } + return step; +} + +static walk_return_t +write_vanilla_region(const struct region *r, struct write_segment_data *wsd) +{ + assert(0 == r->r_nsubregions); + assert(!r->r_inzfodregion); +#ifdef CONFIG_REFSC + assert(NULL == r->r_fileref); +#endif + + const mach_vm_size_t vmsize_host = getvmsize_host(wsd->wsd_task, r); + return write_memory_range(wsd, r, R_ADDR(r), vmsize_host); +} + +walk_return_t +region_write_memory(struct region *r, void *arg) +{ + assert(r->r_info.user_tag != VM_MEMORY_IOKIT); // elided in walk_regions() + assert((r->r_info.max_protection & VM_PROT_READ) == VM_PROT_READ); + return ROP_WRITE(r, arg); +} + +/* + * Handles the cases where segments are broken into chunks i.e. when + * writing compressed segments. + */ +static unsigned long +count_memory_range(mach_vm_offset_t vmsize) +{ + unsigned long count; + if (opt->compress && opt->chunksize > 0) { + count = (size_t)vmsize / opt->chunksize; + if (vmsize != (mach_vm_offset_t)count * opt->chunksize) + count++; + } else + count = 1; + return count; +} + +/* + * A sparse region is likely a writable data segment described by + * native_segment_command_t somewhere in the address space. + */ +static void +size_sparse_subregion(const struct subregion *s, struct size_core *sc) +{ + const unsigned long count = count_memory_range(S_SIZE(s)); + sc->headersize += sizeof (native_segment_command_t) * count; + sc->count += count; + sc->memsize += S_SIZE(s); +} + +static void +size_sparse_region(const struct region *r, struct size_core *sc_sparse, struct size_core *sc_fileref) +{ + assert(0 != r->r_nsubregions); + + unsigned long entry_total = sc_sparse->count + sc_fileref->count; + for (unsigned i = 0; i < r->r_nsubregions; i++) { + const struct subregion *s = r->r_subregions[i]; + if (s->s_isfileref) + size_fileref_subregion(s, sc_fileref); + else + size_sparse_subregion(s, sc_sparse); + } + if (opt->debug) { + /* caused by compression breaking a large region into chunks */ + entry_total = (sc_fileref->count + sc_sparse->count) - entry_total; + if (entry_total > r->r_nsubregions) + printr(r, "range contains %u subregions requires %lu segment commands\n", + r->r_nsubregions, entry_total); + } +} + +const struct regionop sparse_ops = { + print_memory_region, + write_sparse_region, + del_sparse_region, +}; + +static void +size_vanilla_region(const struct region *r, struct size_core *sc) +{ + assert(0 == r->r_nsubregions); + + const unsigned long count = count_memory_range(R_SIZE(r)); + sc->headersize += sizeof (native_segment_command_t) * count; + sc->count += count; + sc->memsize += R_SIZE(r); + + if (opt->debug && count > 1) + printr(r, "range with 1 region, but requires %lu segment commands\n", count); +} + +const struct regionop vanilla_ops = { + print_memory_region, + write_vanilla_region, + del_vanilla_region, +}; + +walk_return_t +region_size_memory(struct region *r, void *arg) +{ + struct size_segment_data *ssd = arg; + + if (&zfod_ops == r->r_op) + size_zfod_region(r, &ssd->ssd_zfod); +#ifdef CONFIG_REFSC + else if (&fileref_ops == r->r_op) + size_fileref_region(r, &ssd->ssd_fileref); +#endif + else if (&sparse_ops == r->r_op) + size_sparse_region(r, &ssd->ssd_sparse, &ssd->ssd_fileref); + else if (&vanilla_ops == r->r_op) + size_vanilla_region(r, &ssd->ssd_vanilla); + else + errx(EX_SOFTWARE, "%s: bad op", __func__); + + return WALK_CONTINUE; +} diff --git a/gcore.tproj/corefile.h b/gcore.tproj/corefile.h new file mode 100644 index 0000000..d455d7e --- /dev/null +++ b/gcore.tproj/corefile.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include "loader_additions.h" +#include "dyld_shared_cache.h" +#include "region.h" + +#include +#include +#include +#include + +#ifndef _COREFILE_H +#define _COREFILE_H + +#if defined(__LP64__) +typedef struct mach_header_64 native_mach_header_t; +typedef struct segment_command_64 native_segment_command_t; +#define NATIVE_MH_MAGIC MH_MAGIC_64 +#define NATIVE_LC_SEGMENT LC_SEGMENT_64 +#else +typedef struct mach_header native_mach_header_t; +typedef struct segment_command native_segment_command_t; +#define NATIVE_MH_MAGIC MH_MAGIC +#define NATIVE_LC_SEGMENT LC_SEGMENT +#endif + +extern native_mach_header_t *make_corefile_mach_header(void *); +extern struct proto_coreinfo_command *make_coreinfo_command(native_mach_header_t *, void *, const uuid_t, uint64_t, uint64_t); + +static __inline void +mach_header_inc_ncmds(native_mach_header_t *mh, uint32_t inc) { + mh->ncmds += inc; +} + +static __inline void +mach_header_inc_sizeofcmds(native_mach_header_t *mh, uint32_t inc) { + mh->sizeofcmds += inc; +} + +struct size_core { + unsigned long count; /* number-of-objects */ + size_t headersize; /* size in mach header */ + mach_vm_offset_t memsize; /* size in memory */ +}; + +struct size_segment_data { + struct size_core ssd_vanilla; /* full segments with data */ + struct size_core ssd_sparse; /* sparse segments with data */ + struct size_core ssd_fileref; /* full & sparse segments with file references */ + struct size_core ssd_zfod; /* full segments with zfod pages */ +}; + +struct write_segment_data { + task_t wsd_task; + native_mach_header_t *wsd_mh; + void *wsd_lc; + int wsd_fd; + off_t wsd_foffset; + off_t wsd_nwritten; +}; + +#endif /* _COREFILE_H */ diff --git a/gcore.tproj/dyld.c b/gcore.tproj/dyld.c new file mode 100644 index 0000000..c8235b5 --- /dev/null +++ b/gcore.tproj/dyld.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "dyld.h" +#include "utils.h" +#include "corefile.h" +#include "vm.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * WARNING WARNING WARNING + * + * Do not trust any of the data from the target task. + * + * A broken program may have damaged it, or a malicious + * program may have deliberately constructed something to + * cause us harm. + */ + +static const char warn_dyld_info[] = "dyld information is incomplete or damaged"; + +dyld_process_info +get_task_dyld_info(const task_t task) +{ + kern_return_t kret; + dyld_process_info dpi = _dyld_process_info_create(task, 0, &kret); + if (NULL == dpi) { + err_mach(kret, NULL, "_dlyd_process_info_create"); + } else { + dyld_process_state_info stateInfo; + + _dyld_process_info_get_state(dpi, &stateInfo); + switch (stateInfo.dyldState) { + case dyld_process_state_not_started: + warnx("%s: dyld state %d", warn_dyld_info, stateInfo.dyldState); + _dyld_process_info_release(dpi); + dpi = NULL; + break; + default: + break; + } + } + return dpi; +} + +/* + * Get the shared cache UUID iff it's in use and is the system one + */ +bool +get_sc_uuid(dyld_process_info dpi, uuid_t uu) +{ + dyld_process_cache_info cacheInfo; + + _dyld_process_info_get_cache(dpi, &cacheInfo); + if (!cacheInfo.noCache && !cacheInfo.privateCache) { + uuid_copy(uu, cacheInfo.cacheUUID); + return true; + } + return false; +} + +void +free_task_dyld_info(dyld_process_info dpi) +{ + _dyld_process_info_release(dpi); +} + +/* + * This routine collects both the Mach-O header and the commands + * "below" it, assuming they're in contiguous memory. + */ +static native_mach_header_t * +copy_dyld_image_mh(task_t task, mach_vm_address_t targetmh, const char *path) +{ + vm_offset_t mhaddr = 0; + mach_msg_type_number_t mhlen = sizeof (native_mach_header_t); + + for (int attempts = 0; attempts < 2; attempts++) { + + const kern_return_t ret = mach_vm_read(task, targetmh, mhlen, &mhaddr, &mhlen); + if (KERN_SUCCESS != ret) { + err_mach(ret, NULL, "mach_vm_read() at 0x%llx for image %s\n", targetmh, path); + mhaddr = 0; + break; + } + const native_mach_header_t *mh = (void *)mhaddr; + if (mhlen < mh->sizeofcmds + sizeof (*mh)) { + const mach_msg_type_number_t newmhlen = sizeof (*mh) + mh->sizeofcmds; + mach_vm_deallocate(mach_task_self(), mhaddr, mhlen); + mhlen = newmhlen; + } else + break; + } + + native_mach_header_t *result = NULL; + + if (mhaddr) { + if (NULL != (result = malloc(mhlen))) + memcpy(result, (void *)mhaddr, mhlen); + mach_vm_deallocate(mach_task_self(), mhaddr, mhlen); + } + return result; +} + +/* + * This table (list) describes libraries and the executable in the address space + */ +struct liblist { + STAILQ_ENTRY(liblist) ll_linkage; + unsigned long ll_namehash; + struct libent ll_entry; +}; +static STAILQ_HEAD(, liblist) libhead = STAILQ_HEAD_INITIALIZER(libhead); + +static unsigned long +namehash(const char *nm) +{ + unsigned long result = 5381; + int c; + while (0 != (c = *nm++)) + result = (result * 33) ^ c; + return result; /* modified djb2 */ +} + +static const struct libent * +libent_lookup_bypathname_withhash(const char *nm, const unsigned long hash) +{ + struct liblist *ll; + STAILQ_FOREACH(ll, &libhead, ll_linkage) { + if (hash != ll->ll_namehash) + continue; + struct libent *le = &ll->ll_entry; + if (strcmp(nm, le->le_pathname) == 0) + return le; + } + return NULL; +} + +const struct libent * +libent_lookup_byuuid(const uuid_t uuid) +{ + struct liblist *ll; + STAILQ_FOREACH(ll, &libhead, ll_linkage) { + struct libent *le = &ll->ll_entry; + if (uuid_compare(uuid, le->le_uuid) == 0) + return le; + } + return NULL; +} + +const struct libent * +libent_lookup_first_bytype(uint32_t mhtype) +{ + struct liblist *ll; + STAILQ_FOREACH(ll, &libhead, ll_linkage) { + struct libent *le = &ll->ll_entry; + if (mhtype == le->le_mh->filetype) + return le; + } + return NULL; +} + +const struct libent * +libent_insert(const char *nm, const uuid_t uuid, uint64_t mhaddr, const native_mach_header_t *mh) +{ + const struct libent *le = libent_lookup_byuuid(uuid); + if (NULL != le) + return le; // disallow multiple names for the same uuid + + unsigned long nmhash = namehash(nm); + le = libent_lookup_bypathname_withhash(nm, nmhash); + if (NULL != le) + return le; + + if (opt->debug > 3) { + uuid_string_t uustr; + uuid_unparse_lower(uuid, uustr); + printf("[adding <'%s', %s, 0x%llx, %p>]\n", nm, uustr, mhaddr, mh); + } + struct liblist *ll = malloc(sizeof (*ll)); + ll->ll_namehash = nmhash; + ll->ll_entry.le_pathname = strdup(nm); + ll->ll_entry.le_filename = strrchr(ll->ll_entry.le_pathname, '/'); + if (NULL == ll->ll_entry.le_filename) + ll->ll_entry.le_filename = ll->ll_entry.le_pathname; + else + ll->ll_entry.le_filename++; + uuid_copy(ll->ll_entry.le_uuid, uuid); + ll->ll_entry.le_mhaddr = mhaddr; + ll->ll_entry.le_mh = mh; + + STAILQ_INSERT_HEAD(&libhead, ll, ll_linkage); + + return &ll->ll_entry; +} + +bool +libent_build_nametable(task_t task, dyld_process_info dpi) +{ + __block bool valid = true; + + _dyld_process_info_for_each_image(dpi, ^(uint64_t mhaddr, const uuid_t uuid, const char *path) { + if (valid) { + native_mach_header_t *mh = copy_dyld_image_mh(task, mhaddr, path); + if (mh) { + /* + * Validate the rest of the mach information in the header before attempting optimizations + */ + const size_t mhlen = sizeof (*mh) + mh->sizeofcmds; + const struct load_command *lc = (const void *)(mh + 1); + + for (unsigned n = 0; n < mh->ncmds; n++) { + if (((uintptr_t)lc & 0x3) != 0 || + (uintptr_t)lc < (uintptr_t)mh || (uintptr_t)lc > (uintptr_t)mh + mhlen) { + warnx("%s, %d", warn_dyld_info, __LINE__); + valid = false; + break; + } + if (lc->cmdsize) + lc = (const void *)((caddr_t)lc + lc->cmdsize); + else + break; + } + if (valid) + (void) libent_insert(path, uuid, mhaddr, mh); + } + } + }); + if (opt->debug) + printf("nametable %sconstructed\n", valid ? "" : "NOT "); + return valid; +} diff --git a/gcore.tproj/dyld.h b/gcore.tproj/dyld.h new file mode 100644 index 0000000..cac1409 --- /dev/null +++ b/gcore.tproj/dyld.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "corefile.h" + +#include +#include +#include + +#ifndef _DYLD_H +#define _DYLD_H + +struct libent { + const char *le_filename; // (points into le_pathname!) + char *le_pathname; + uuid_t le_uuid; + uint64_t le_mhaddr; // address in target process + const native_mach_header_t *le_mh; // cached copy in this address space +}; + +extern const struct libent *libent_lookup_byuuid(const uuid_t); +extern const struct libent *libent_lookup_first_bytype(uint32_t); +extern const struct libent *libent_insert(const char *, const uuid_t, uint64_t, const native_mach_header_t *); +extern bool libent_build_nametable(task_t, dyld_process_info); + +extern dyld_process_info get_task_dyld_info(task_t); +extern bool get_sc_uuid(dyld_process_info, uuid_t); +extern void free_task_dyld_info(dyld_process_info); + + +#endif /* _DYLD_H */ diff --git a/gcore.tproj/dyld_shared_cache.c b/gcore.tproj/dyld_shared_cache.c new file mode 100644 index 0000000..91aefa5 --- /dev/null +++ b/gcore.tproj/dyld_shared_cache.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "dyld_shared_cache.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const size_t dyld_cache_header_size = sizeof (struct copied_dyld_cache_header); + +/* + * The shared cache must both contain the magic ID and + * match the uuid we discovered via dyld's information. + */ +bool +get_uuid_from_shared_cache_mapping(const void *addr, size_t size, uuid_t out) +{ + const struct copied_dyld_cache_header *ch = addr; + if (size < sizeof (*ch)) + return false; + static const char prefix[] = "dyld_v1 "; + if (strncmp(ch->magic, prefix, strlen(prefix)) != 0) + return false; + uuid_copy(out, ch->uuid); + return true; +} + +/* + * Look in the known places to see if we can find this one .. + */ +char * +shared_cache_filename(const uuid_t uu) +{ + assert(!uuid_is_null(uu)); + static char *sc_argv[] = { +#if defined(__i386__) || defined(__x86_64__) + "/var/db/dyld", +#elif defined(__arm__) || defined(__arm64__) + "/System/Library/Caches/com.apple.dyld", +#else +#error undefined +#endif + NULL + }; + char *nm = NULL; + FTS *fts = fts_open(sc_argv, FTS_NOCHDIR | FTS_LOGICAL | FTS_XDEV, NULL); + if (NULL != fts) { + FTSENT *fe; + while (NULL != (fe = fts_read(fts))) { + if ((fe->fts_info & FTS_F) == 0 || + (fe->fts_info & FTS_ERR) != 0) + continue; + + static const char prefix[] = "dyld_shared_cache_"; + if (strncmp(fe->fts_name, prefix, strlen(prefix)) != 0) + continue; + + if (fe->fts_statp->st_size < (off_t)dyld_cache_header_size) + continue; + + int d = open(fe->fts_accpath, O_RDONLY); + if (-1 == d) { + if (opt->debug) + printf("%s: cannot open - %s\n", fe->fts_accpath, strerror(errno)); + continue; + } + void *addr = mmap(NULL, dyld_cache_header_size, PROT_READ, MAP_PRIVATE, d, 0); + close(d); + if ((void *)-1 == addr) { + if (opt->debug) + printf("%s: cannot mmap - %s\n", fe->fts_accpath, strerror(errno)); + continue; + } + uuid_t scuuid; + uuid_clear(scuuid); + if (get_uuid_from_shared_cache_mapping(addr, dyld_cache_header_size, scuuid)) { + if (uuid_compare(uu, scuuid) == 0) + nm = strdup(fe->fts_accpath); + else if (opt->debug) { + uuid_string_t scstr; + uuid_unparse_lower(scuuid, scstr); + printf("%s: shared cache mismatch (%s)\n", fe->fts_accpath, scstr); + } + } + munmap(addr, dyld_cache_header_size); + if (NULL != nm) + break; + } + } + if (fts) + fts_close(fts); + return nm; +} diff --git a/gcore.tproj/dyld_shared_cache.h b/gcore.tproj/dyld_shared_cache.h new file mode 100644 index 0000000..1fe0fac --- /dev/null +++ b/gcore.tproj/dyld_shared_cache.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#ifndef _DYLD_SHARED_CACHE_H +#define _DYLD_SHARED_CACHE_H + +/* + * Guilty knowledge of dyld shared cache internals, used to verify shared cache + */ +struct copied_dyld_cache_header { + char magic[16]; // e.g. "dyld_v0 i386" + uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info + uint32_t mappingCount; // number of dyld_cache_mapping_info entries + uint32_t imagesOffset; // file offset to first dyld_cache_image_info + uint32_t imagesCount; // number of dyld_cache_image_info entries + uint64_t dyldBaseAddress; // base address of dyld when cache was built + uint64_t codeSignatureOffset; // file offset of code signature blob + uint64_t codeSignatureSize; // size of code signature blob (zero means to end of file) + uint64_t slideInfoOffset; // file offset of kernel slid info + uint64_t slideInfoSize; // size of kernel slid info + uint64_t localSymbolsOffset; // file offset of where local symbols are stored + uint64_t localSymbolsSize; // size of local symbols information + uint8_t uuid[16]; // unique value for each shared cache file + uint64_t cacheType; // 1 for development, 0 for optimized +}; + +extern bool get_uuid_from_shared_cache_mapping(const void *, size_t, uuid_t); +extern char *shared_cache_filename(const uuid_t); + +#endif /* _DYLD_SHARED_CACHE_H */ diff --git a/gcore.tproj/gcore.1 b/gcore.tproj/gcore.1 new file mode 100644 index 0000000..48b360d --- /dev/null +++ b/gcore.tproj/gcore.1 @@ -0,0 +1,105 @@ +.Dd 2/10/16 +.Dt gcore 1 +.Os Darwin +.Sh NAME +.Nm gcore +.Nd get core images of running processes +.Sh SYNOPSIS +.Nm +.Op Fl s +.Op Fl v +.Op Fl b Ar size +.Op Fl o Ar path | Fl c Ar pathformat +.Ar pid +.Sh DESCRIPTION +The +.Nm gcore +program creates a core file image of the process specified by +.Ar pid . +The resulting core file can be used with a debugger, e.g. +.Xr lldb(1) , +to examine the state of the process. +.Pp +The following options are available: +.Bl -tag -width Fl +.It Fl s +Suspend the process while the core file is captured. +.It Fl v +Report progress on the dump as it proceeds. +.It Fl b Ar size +Limit the size of the core file to +.Ar size +MiBytes. +.El +.Pp +The following options control the name of the core file: +.Bl -tag -width flag +.It Fl o Ar path +Write the core file to +.Ar path . +.It Fl c Ar pathformat +Write the core file to +.Ar pathformat . +The +.Ar pathformat +string is treated as a pathname that may contain various special +characters which cause the interpolation of strings representing +specific attributes of the process into the name. +.Pp +Each special character is introduced by the +.Cm % +character. The format characters and their meanings are: +.Bl -tag -width Fl +.It Cm N +The name of the program being dumped, as reported by +.Xr ps 1 . +.It Cm U +The uid of the process being dumped, converted to a string. +.It Cm P +The pid of the process being dumped, converted to a string. +.It Cm T +The time when the core file was taken, converted to ISO 8601 format. +.It Cm % +Output a percent character. +.El +.El +.Pp +The default file name used by +.Nm gcore +is +.Ar %N-%P-%T . +By default, the core file will be written to a directory whose +name is determined from the +.Ar kern.corefile +MIB. This can be printed or modified using +.Xr sysctl 8 . +.Pp +The directory where the core file is to be written must be +accessible to the owner of the target process. +.Pp +.Nm gcore +will not overwrite an existing file, +nor will it create missing directories in the path. +.Sh EXIT_STATUS +.Ex -std +.Pp +.Sh FILES +.Bl -tag -width "/cores/%N-%P-%T plus" -compact +.It Pa /cores/%N-%P-%T +default pathname for the corefile. +.El +.Sh BUGS +With the +.Fl b +flag, +.Nm gcore +writes out as much data as it can up to the specified limit, +even if that results in an incomplete core image. +Such a partial core dump may confuse subsequent +programs that attempt to parse the contents of such files. +.Sh SEE ALSO +.Xr lldb 1 , +.Xr core 5 , +.Xr Mach-O 5 , +.Xr sysctl 8 , +.Xr sudo 8 . diff --git a/gcore.tproj/loader_additions.h b/gcore.tproj/loader_additions.h new file mode 100644 index 0000000..47e3054 --- /dev/null +++ b/gcore.tproj/loader_additions.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include + +#ifndef _LOADER_ADDITIONS_H +#define _LOADER_ADDITIONS_H + +/* + * Something like this should end up in + */ +#define proto_LC_COREINFO 0x40 /* unofficial value!! */ + +#define proto_CORETYPE_KERNEL 1 +#define proto_CORETYPE_USER 2 +#define proto_CORETYPE_IBOOT 3 + +struct proto_coreinfo_command { + uint32_t cmd; /* LC_COREINFO */ + uint32_t cmdsize; /* total size of this command */ + uint32_t version; /* currently 1 */ + /* + * 'type' determines the content of the corefile; interpretation + * of the address and uuid fields are specific to the type. + */ + uint32_t type; /* CORETYPE_KERNEL, CORETYPE_USER etc. */ + uint64_t address; /* load address of "main binary" */ + uint8_t uuid[16]; /* uuid of "main binary" */ + uint64_t dyninfo; /* dynamic modules info */ +}; + +/* + * These are flag bits for the segment_command 'flags' field. + */ + +#define proto_SG_COMP_ALG_MASK 0x7 +/* carve out 3 bits for an enum i.e. allow for 7 flavors */ +#define proto_SG_COMP_ALG_SHIFT 4 /* (bottom 4 bits taken) */ + +/* zero -> no compression */ +#define proto_SG_COMP_LZ4 1 /* 0x100 */ +#define proto_SG_COMP_ZLIB 2 /* 0x205 */ +#define proto_SG_COMP_LZMA 3 /* 0x306 */ +#define proto_SG_COMP_LZFSE 4 /* 0x801 */ + +#define proto_SG_COMP_ALG_TYPE(flags) (((flags) >> proto_SG_COMP_ALG_SHIFT) & proto_SG_COMP_ALG_MASK) +#define proto_SG_COMP_MAKE_FLAGS(type) (((type) & proto_SG_COMP_ALG_MASK) << proto_SG_COMP_ALG_SHIFT) + +#define proto_LC_FILEREF 0x41 /* unofficial value! */ + +struct proto_fileref_command { + uint32_t cmd; /* LC_FILEREF */ + uint32_t cmdsize; + union lc_str filename; /* filename these bits come from */ + uint8_t uuid[16]; /* uuid if known */ + uint64_t vmaddr; /* memory address of this segment */ + uint64_t vmsize; /* memory size of this segment */ + uint64_t fileoff; /* file offset of this segment */ + uint64_t filesize; /* amount to map from the file */ + vm_prot_t maxprot; /* maximum VM protection */ + vm_prot_t initprot; /* initial VM protection */ +}; + +#endif /* _LOADER_ADDITIONS_H */ diff --git a/gcore.tproj/main.c b/gcore.tproj/main.c new file mode 100644 index 0000000..d434468 --- /dev/null +++ b/gcore.tproj/main.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "utils.h" +#include "corefile.h" +#include "vanilla.h" +#include "sparse.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static char * +kern_corefile(void) +{ + char *(^sysc_string)(const char *name) = ^(const char *name) { + char *p = NULL; + size_t len = 0; + + if (-1 == sysctlbyname(name, NULL, &len, NULL, 0)) { + warnc(errno, "sysctl: %s", name); + } else if (0 != len) { + p = malloc(len); + if (-1 == sysctlbyname(name, p, &len, NULL, 0)) { + warnc(errno, "sysctl: %s", name); + free(p); + p = NULL; + } + } + return p; + }; + + char *s = sysc_string("kern.corefile"); + if (NULL == s) + s = strdup("/cores/core.%P"); + return s; +} + +static const struct proc_bsdinfo * +get_bsdinfo(pid_t pid) +{ + if (0 == pid) + return NULL; + struct proc_bsdinfo *pbi = calloc(1, sizeof (*pbi)); + if (0 != proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, pbi, sizeof (*pbi))) + return pbi; + free(pbi); + return NULL; +} + +static char * +format_gcore_name(const char *fmt, const struct proc_bsdinfo *pbi) +{ + __block size_t resid = MAXPATHLEN; + __block char *p = calloc(1, resid); + char *out = p; + + int (^outchar)(int c) = ^(int c) { + if (resid > 1) { + *p++ = (char)c; + resid--; + return 1; + } else + return 0; + }; + + ptrdiff_t (^outstr)(const char *str) = ^(const char *str) { + const char *s = str; + while (*s && 0 != outchar(*s++)) + ; + return s - str; + }; + + ptrdiff_t (^outint)(int value)= ^(int value) { + char id[11]; + snprintf(id, sizeof (id), "%u", value); + return outstr(id); + }; + + ptrdiff_t (^outtstamp)(void) = ^(void) { + time_t now; + time(&now); + struct tm tm; + gmtime_r(&now, &tm); + char tstamp[50]; + strftime(tstamp, sizeof (tstamp), "%Y%m%dT%H%M%SZ", &tm); + return outstr(tstamp); + }; + + int c; + + for (int i = 0; resid > 0; i++) + switch (c = fmt[i]) { + default: + outchar(c); + break; + case '%': + i++; + switch (c = fmt[i]) { + case '%': + outchar(c); + break; + case 'P': + outint(pbi->pbi_pid); + break; + case 'U': + outint(pbi->pbi_uid); + break; + case 'N': + outstr(pbi->pbi_name[0] ? + pbi->pbi_name : pbi->pbi_comm); + break; + case 'T': + outtstamp(); // ISO 8601 format + break; + default: + if (isprint(c)) + err(EX_DATAERR, "unknown format char: %%%c", c); + else if (c != 0) + err(EX_DATAERR, "bad format char %%\\%03o", c); + else + err(EX_DATAERR, "bad format specifier"); + } + break; + case 0: + outchar(c); + goto done; + } +done: + return out; +} + +const char *pgm; +const struct options *opt; + +int +main(int argc, char *const *argv) +{ + if (NULL == (pgm = strrchr(*argv, '/'))) + pgm = *argv; + else + pgm++; + +#define ZOPT_ALG (0) +#define ZOPT_CHSIZE (ZOPT_ALG + 1) + + static char *const zoptkeys[] = { + [ZOPT_ALG] = "algorithm", + [ZOPT_CHSIZE] = "chunksize", + NULL + }; + + err_set_exit_b(^(int eval) { + if (EX_USAGE == eval) { + fprintf(stderr, + "usage:\n\t%s [-s] [-v] [[-o file] | [-c pathfmt ]] [-b size] " +#if DEBUG + "[-d] [-n] [-i] [-p] [-S] [-z] [-C] " + "[-Z compression-options] " +#ifdef CONFIG_REFSC + "[-R] " +#endif +#endif + "pid\n", pgm); +#if DEBUG + fprintf(stderr, "where compression-options:\n"); + const char zvalfmt[] = "\t%s=%s\t\t%s\n"; + fprintf(stderr, zvalfmt, zoptkeys[ZOPT_ALG], "alg", + "set compression algorithm"); + fprintf(stderr, zvalfmt, zoptkeys[ZOPT_CHSIZE], "size", + "set compression chunksize, Mib"); +#endif + } + }); + + char *corefmt = NULL; + char *corefname = NULL; + const size_t oneM = 1024 * 1024; + +#define LARGEST_CHUNKSIZE INT32_MAX +#define DEFAULT_COMPRESSION_CHUNKSIZE (16 * oneM) + + struct options options = { + .corpse = 0, + .suspend = 0, + .preserve = 0, + .verbose = 0, + .debug = 0, + .dryrun = 0, + .sparse = 0, + .sizebound = 0, + .coreinfo = 0, +#ifdef OPTIONS_REFSC + .scfileref = 0, +#endif + .compress = 0, + .chunksize = LARGEST_CHUNKSIZE, + .calgorithm = COMPRESSION_LZFSE, + }; + + int c; + char *sopts, *value; + + while ((c = getopt(argc, argv, "inmvdszpCSRZ:o:c:b:")) != -1) { + switch (c) { + + /* + * documented options + */ + case 's': /* FreeBSD compat: stop while gathering */ + options.suspend = 1; + break; + case 'o': /* Linux (& SunOS) compat: basic name */ + corefname = strdup(optarg); + break; + case 'c': /* FreeBSD compat: basic name */ + /* (also allows pattern-based naming) */ + corefmt = strdup(optarg); + break; + + case 'b': /* bound the size of the core file */ + if (NULL != optarg) { + off_t bsize = atoi(optarg) * oneM; + if (bsize > 0) + options.sizebound = bsize; + else + errx(EX_USAGE, "invalid bound"); + } else + errx(EX_USAGE, "no bound specified"); + break; + case 'v': /* verbose output */ + options.verbose++; + break; + + /* + * dev and debugging help + */ + case 'n': /* write the core file to /dev/null */ + options.dryrun++; + break; + case 'd': /* debugging */ + options.debug++; + options.verbose++; + options.preserve++; + break; + case 'p': /* preserve partial core file (even if errors) */ + options.preserve++; + break; + + /* + * Remaining options are experimental and/or + * affect the content of the core file + */ + case 'i': /* include LC_COREINFO data */ + options.coreinfo++; + break; + case 'C': /* corpsify rather than suspend */ + options.corpse++; + break; +#ifdef CONFIG_REFSC + case 'R': /* include the shared cache by reference */ + options.scfileref++; + options.coreinfo++; + break; +#endif + case 'S': /* use dyld info to control the content */ + options.sparse++; + options.coreinfo++; + break; + case 'z': /* create compressed LC_SEGMENT* segments */ + if (0 == options.compress) { + options.compress++; + options.chunksize = DEFAULT_COMPRESSION_CHUNKSIZE; + } + options.coreinfo++; + break; + case 'Z': /* control compression options */ + /* + * Only LZFSE and LZ4 seem practical. + * (Default to LZ4 compression when the + * process is suspended, LZFSE when corpsed?) + */ + if (0 == options.compress) { + options.compress++; + options.chunksize = DEFAULT_COMPRESSION_CHUNKSIZE; + } + sopts = optarg; + while (*sopts) { + size_t chsize; + + switch (getsubopt(&sopts, zoptkeys, &value)) { + case ZOPT_ALG: /* change the algorithm */ + if (NULL == value) + errx(EX_USAGE, "missing algorithm for " + "%s suboption", + zoptkeys[ZOPT_ALG]); + if (strcmp(value, "lz4") == 0) + options.calgorithm = + COMPRESSION_LZ4; + else if (strcmp(value, "zlib") == 0) + options.calgorithm = + COMPRESSION_ZLIB; + else if (strcmp(value, "lzma") == 0) + options.calgorithm = + COMPRESSION_LZMA; + else if (strcmp(value, "lzfse") == 0) + options.calgorithm = + COMPRESSION_LZFSE; + else + errx(EX_USAGE, "unknown algorithm '%s'" + " for %s suboption", + value, + zoptkeys[ZOPT_ALG]); + break; + case ZOPT_CHSIZE: /* set the chunksize */ + if (NULL == value) + errx(EX_USAGE, "no value specified for " + "%s suboption", + zoptkeys[ZOPT_CHSIZE]); + if ((chsize = atoi(value)) < 1) + errx(EX_USAGE, "chunksize %lu too small", chsize); + if (chsize > (LARGEST_CHUNKSIZE / oneM)) + errx(EX_USAGE, "chunksize %lu too large", chsize); + options.chunksize = chsize * oneM; + break; + default: + if (suboptarg) + errx(EX_USAGE, "illegal suboption '%s'", + suboptarg); + else + errx(EX_USAGE, "missing suboption"); + } + } + break; + default: + errx(EX_USAGE, "unknown flag"); + } + } + if (optind == argc) + errx(EX_USAGE, "no pid specified"); + + opt = &options; + + if ((opt->dryrun ? 1 : 0) + + (NULL != corefname ? 1 : 0) + + (NULL != corefmt ? 1 : 0) > 1) + errx(EX_USAGE, "specify only one of -n, -o and -c"); + + setpageshift(); + + const pid_t pid = atoi(argv[optind]); + if (pid < 1 || getpid() == pid) + errx(EX_DATAERR, "invalid pid: %d", pid); + if (-1 == kill(pid, 0)) { + switch (errno) { + case ESRCH: + errc(EX_DATAERR, errno, "no process with pid %d", pid); + default: + errc(EX_DATAERR, errno, "pid %d", pid); + } + } + + const struct proc_bsdinfo *pbi = get_bsdinfo(pid); + if (NULL == pbi) + errx(EX_OSERR, "cannot get bsdinfo about %d", pid); + + /* + * make our data model match the data model of the target + */ + if (-1 == reexec_to_match_lp64ness(pbi->pbi_flags & PROC_FLAG_LP64)) + errc(1, errno, "cannot match data model of %d", pid); + +#if defined(__LP64__) + if ((pbi->pbi_flags & PROC_FLAG_LP64) == 0) +#else + if ((pbi->pbi_flags & PROC_FLAG_LP64) != 0) +#endif + errx(EX_OSERR, "cannot match data model of %d", pid); + + /* + * These are experimental options for the moment. + * These will likely change. + * Some may become defaults, some may be removed altogether. + */ + if (opt->sparse || +#ifdef CONFIG_REFSC + opt->scfileref || +#endif + opt->compress || + opt->corpse || + opt->coreinfo) + warnx("experimental option(s) used, " + "resulting corefile may be unusable."); + + if (pbi->pbi_ruid != pbi->pbi_svuid || + pbi->pbi_rgid != pbi->pbi_svgid) + errx(EX_NOPERM, "pid %d - not dumping a set-id process", pid); + + if (NULL == corefname) { + if (NULL == corefmt) { + const char defcore[] = "%N-%P-%T"; + if (NULL == (corefmt = kern_corefile())) + corefmt = strdup(defcore); + else { + // use the same directory as kern.corefile + char *p = strrchr(corefmt, '/'); + if (NULL != p) { + *p = '\0'; + size_t len = strlen(corefmt) + + strlen(defcore) + 2; + char *buf = malloc(len); + snprintf(buf, len, "%s/%s", corefmt, defcore); + free(corefmt); + corefmt = buf; + } + if (opt->debug) + printf("corefmt '%s'\n", corefmt); + } + } + corefname = format_gcore_name(corefmt, pbi); + free(corefmt); + } + + task_t task; + kern_return_t ret = task_for_pid(mach_task_self(), pid, &task); + if (KERN_SUCCESS != ret) { + if (KERN_FAILURE == ret) + errx(EX_NOPERM, "insufficient privilege"); + else + errx(EX_NOPERM, "task_for_pid: %s", mach_error_string(ret)); + } + + /* + * Now that we have the task port, we adopt the credentials of + * the target process, *before* opening the core file, and + * analyzing the address space. + * + * If we are unable to match the target credentials, bail out. + */ + if (getgid() != pbi->pbi_gid && + setgid(pbi->pbi_gid) == -1) + errc(EX_NOPERM, errno, "insufficient privilege"); + + if (getuid() != pbi->pbi_uid && + setuid(pbi->pbi_uid) == -1) + errc(EX_NOPERM, errno, "insufficient privilege"); + + int fd; + + if (opt->dryrun) { + free(corefname); + corefname = strdup("/dev/null"); + fd = open(corefname, O_RDWR); + } else { + fd = open(corefname, O_RDWR | O_CREAT | O_EXCL, 0400); + + struct stat st; + + if (-1 == fd || -1 == fstat(fd, &st)) + errc(EX_CANTCREAT, errno, "%s", corefname); + if ((st.st_mode & S_IFMT) != S_IFREG || 1 != st.st_nlink) { + close(fd); + errx(EX_CANTCREAT, "%s: invalid file", corefname); + } + } + + if (opt->verbose) { + printf("Dumping core "); + if (opt->debug) { + printf("(%s%s%s", + opt->sparse ? "sparse" : "normal", + opt->compress ? ", compressed" : "", +#ifdef CONFIG_REFSC + opt->scfileref ? ", scfilerefs" : +#endif + ""); + if (0 != opt->sizebound) { + hsize_str_t hstr; + printf(", %s", str_hsize(hstr, opt->sizebound)); + } + printf(") "); + } + printf("for pid %d to %s\n", pid, corefname); + } + int ecode; + + /* + * The traditional way to capture a consistent core dump is to + * suspend the process while processing it and writing it out. + * Yet suspending a large process for a long time can have + * unpleasant side-effects. Alternatively dumping from the live + * process can lead to an inconsistent state in the core file. + * + * Instead we can ask xnu to create a 'corpse' - the process is transiently + * suspended while a COW snapshot of the address space is constructed + * in the kernel and dump from that. This vastly reduces the suspend + * time, but it is more resource hungry and thus may fail. + * + * The -s flag (opt->suspend) causes a task_suspend/task_resume + * The -C flag (opt->corpse) causes a corpse be taken, exiting if that fails. + * Both flags can be specified, in which case corpse errors are ignored. + * + * With no flags, we imitate traditional behavior though more + * efficiently: we try to take a corpse-based dump, in the event that + * fails, dump the live process. + */ + + int trycorpse = 1; /* default: use corpses */ + int badcorpse_is_fatal = 1; /* default: failure to create a corpse is an error */ + + if (!opt->suspend && !opt->corpse) { + /* try a corpse dump, else dump the live process */ + badcorpse_is_fatal = 0; + } else if (opt->suspend) { + trycorpse = opt->corpse; + /* if suspended anyway, ignore corpse-creation errors */ + badcorpse_is_fatal = 0; + } + + if (opt->suspend) + task_suspend(task); + + if (trycorpse) { + /* + * Create a corpse from the image before dumping it + */ + mach_port_t corpse = MACH_PORT_NULL; + ret = task_generate_corpse(task, &corpse); + switch (ret) { + case KERN_SUCCESS: + if (opt->debug) + printf("corpse generated on port %x, task %x\n", + corpse, task); + ecode = coredump(corpse, fd); + mach_port_deallocate(mach_task_self(), corpse); + break; + default: + if (badcorpse_is_fatal || opt->debug) { + warnx("failed to snapshot pid %d: %s\n", + pid, mach_error_string(ret)); + if (badcorpse_is_fatal) { + ecode = KERN_RESOURCE_SHORTAGE == ret ? EX_TEMPFAIL : EX_OSERR; + goto out; + } + } + ecode = coredump(task, fd); + break; + } + } else { + /* + * Examine the task directly + */ + ecode = coredump(task, fd); + } + +out: + if (opt->suspend) + task_resume(task); + + if (0 != ecode && !opt->preserve && !opt->dryrun) { + /* + * try not to leave a half-written mess occupying + * blocks on the filesystem + */ + ftruncate(fd, 0); + unlink(corefname); + } + if (-1 == close(fd)) + ecode = EX_OSERR; + if (ecode) + errx(ecode, "failed to dump core for pid %d", pid); + free(corefname); + + return 0; +} diff --git a/gcore.tproj/options.h b/gcore.tproj/options.h new file mode 100644 index 0000000..051be4a --- /dev/null +++ b/gcore.tproj/options.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include +#include + +#include + +#ifndef _OPTIONS_H +#define _OPTIONS_H + +#if defined(__arm__) || defined(__arm64__) +#define RDAR_23744374 1 /* 'true' while not fixed i.e. enable workarounds */ +#endif + +#define CONFIG_REFSC 1 /* create shared cache reference segment (-R) */ +//#define CONFIG_PURGABLE 1 /* record purgability */ +//#define CONFIG_SUBMAP 1 /* include submaps (debugging) */ + +#ifdef NDEBUG +#define poison(a, p, s) /* do nothing */ +#else +#define poison(a, p, s) memset(a, p, s) /* scribble on dying memory */ +#endif + +struct options { + int corpse; // dump from a corpse + int suspend; // suspend while dumping + int preserve; // preserve the core file, even if there are errors + int verbose; // be chatty + int debug; // internal debugging: options accumulate. very noisy. + int dryrun; // do all the work, but throw the dump away + int sparse; // use dyld's data about dylibs to reduce the size of the dump + off_t sizebound; // maximum size of the dump + int coreinfo; // create a (currently experimental) 'coreinfo' section +#ifdef CONFIG_REFSC + int scfileref; // create "reference" segments that point at the shared cache +#endif + int compress; // compress the dump + size_t chunksize; // max size of the compressed segment + compression_algorithm calgorithm; // algorithm in use +}; + +extern const struct options *opt; + +#endif /* _OPTIONS_H */ diff --git a/gcore.tproj/region.h b/gcore.tproj/region.h new file mode 100644 index 0000000..a4f0afb --- /dev/null +++ b/gcore.tproj/region.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#ifndef _REGION_H +#define _REGION_H + +struct regionop; +struct subregion; + +struct region { + STAILQ_ENTRY(region) r_linkage; + + mach_vm_offset_t r_address; + mach_vm_offset_t r_size; + +#define _R_ADDR(r) ((r)->r_address) +#define _R_SIZE(r) ((r)->r_size) +#define R_SETADDR(r, a) ((r)->r_address = (a)) +#define R_SETSIZE(r, z) ((r)->r_size = (z)) +#define R_ENDADDR(r) (_R_ADDR(r) + _R_SIZE(r)) + + vm_region_submap_info_data_64_t r_info; + vm_page_info_basic_data_t r_pageinfo; + +#ifdef CONFIG_PURGABLE + int r_purgable; +#endif +#ifdef CONFIG_SUBMAP + int r_depth; +#endif + boolean_t + r_insharedregion, + r_inzfodregion, + r_incommregion; + +#ifdef CONFIG_REFSC + /* + * This field may be non-NULL if the region is a read-only part + * of a mapped file (i.e. the shared cache) and thus + * doesn't need to be copied. + */ + struct { + const struct libent *fr_libent; + off_t fr_offset; + } *r_fileref; +#endif + + /* + * These (optional) fields are filled in after we parse the information + * about the dylibs we've mapped, as provided by dyld. + */ + struct subregion **r_subregions; + unsigned r_nsubregions; + + const struct regionop *r_op; +}; + +static __inline const mach_vm_offset_t R_ADDR(const struct region *r) { + return _R_ADDR(r); +} + +static __inline const mach_vm_offset_t R_SIZE(const struct region *r) { + return _R_SIZE(r); +} + +/* + * Describes the disposition of the region after a walker returns + */ +typedef enum { + WALK_CONTINUE, // press on .. + WALK_DELETE_REGION, // discard this region, then continue + WALK_TERMINATE, // early termination, no error + WALK_ERROR, // early termination, error +} walk_return_t; + +struct size_core; +struct write_segment_data; + +typedef walk_return_t walk_region_cbfn_t(struct region *, void *); + +struct regionop { + void (*rop_print)(const struct region *); + walk_return_t (*rop_write)(const struct region *, struct write_segment_data *); + void (*rop_delete)(struct region *); +}; + +#define ROP_PRINT(r) (((r)->r_op->rop_print)(r)) +#define ROP_WRITE(r, w) (((r)->r_op->rop_write)(r, w)) +#define ROP_DELETE(r) (((r)->r_op->rop_delete)(r)) + +extern const struct regionop vanilla_ops, sparse_ops, zfod_ops; +#ifdef CONFIG_REFSC +extern const struct regionop fileref_ops; +#endif + +struct regionhead; + +#endif /* _REGION_H */ diff --git a/gcore.tproj/sparse.c b/gcore.tproj/sparse.c new file mode 100644 index 0000000..26d4dc7 --- /dev/null +++ b/gcore.tproj/sparse.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "vm.h" +#include "region.h" +#include "utils.h" +#include "dyld.h" +#include "threads.h" +#include "sparse.h" +#include "vanilla.h" +#include "corefile.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct subregion * +new_subregion( + const mach_vm_offset_t vmaddr, + const mach_vm_offset_t vmsize, + const native_segment_command_t *sc, + const struct libent *le) +{ + struct subregion *s = malloc(sizeof (*s)); + + assert(vmaddr != 0 && vmsize != 0); + assert(vmaddr < vmaddr + vmsize); + s->s_segcmd = *sc; + + S_SETADDR(s, vmaddr); + S_SETSIZE(s, vmsize); + + s->s_libent = le; + s->s_isfileref = false; + return s; +} + +static void +del_subregion(struct subregion *s) +{ + poison(s, 0xfacefac1, sizeof (*s)); + free(s); +} + +static walk_return_t +clean_subregions(struct region *r) +{ + for (unsigned i = 0; i < r->r_nsubregions; i++) + del_subregion(r->r_subregions[i]); + poison(r->r_subregions, 0xfac1fac1, sizeof (r->r_subregions[0]) * r->r_nsubregions); + free(r->r_subregions); + r->r_nsubregions = 0; + return WALK_CONTINUE; +} + +void +del_sparse_region(struct region *r) +{ + clean_subregions(r); + poison(r, 0xcafecaff, sizeof (*r)); + free(r); +} + +#define NULLsc ((native_segment_command_t *)0) + +static bool +issamesubregiontype(const struct subregion *s0, const struct subregion *s1) { + return 0 == strncmp(S_MACHO_TYPE(s0), S_MACHO_TYPE(s1), sizeof (NULLsc->segname)); +} + +bool +issubregiontype(const struct subregion *s, const char *sctype) { + return 0 == strncmp(S_MACHO_TYPE(s), sctype, sizeof (NULLsc->segname)); +} + +static void +elide_subregion(struct region *r, unsigned ind) +{ + del_subregion(r->r_subregions[ind]); + for (unsigned j = ind; j < r->r_nsubregions - 1; j++) + r->r_subregions[j] = r->r_subregions[j+1]; + assert(r->r_nsubregions != 0); + r->r_subregions[--r->r_nsubregions] = NULL; +} + +struct subregionlist { + STAILQ_ENTRY(subregionlist) srl_linkage; + struct subregion *srl_s; +}; +typedef STAILQ_HEAD(, subregionlist) subregionlisthead_t; + +static walk_return_t +add_subregions_for_libent( + subregionlisthead_t *srlh, + const struct region *r, + const native_mach_header_t *mh, + const mach_vm_offset_t mh_taddr, + const struct libent *le) +{ + const struct load_command *lc = (const void *)(mh + 1); + mach_vm_offset_t scoffset = MACH_VM_MAX_ADDRESS; + + for (unsigned n = 0; n < mh->ncmds; n++) { + + const native_segment_command_t *sc; + + switch (lc->cmd) { + case NATIVE_LC_SEGMENT: + sc = (const void *)lc; + + char scsegname[17]; + strlcpy(scsegname, sc->segname, sizeof (scsegname)); + + if (0 == sc->vmaddr && + strcmp(scsegname, SEG_PAGEZERO) == 0) + break; + + /* -Depends- on finding a __TEXT segment first! */ + + if (MACH_VM_MAX_ADDRESS == scoffset) { + if (strcmp(scsegname, SEG_TEXT) == 0) + scoffset = mh_taddr - sc->vmaddr; + else { + /* + * Treat as error - don't want a partial description + * to cause something to be omitted from the dump. + */ + printr(r, "expected %s segment, found %s segment\n", SEG_TEXT, scsegname); + return WALK_ERROR; + } + } + + /* Eliminate non-overlapping sections first */ + + if (R_ENDADDR(r) - 1 < sc->vmaddr + scoffset) + break; + if (sc->vmaddr + scoffset + sc->vmsize - 1 < R_ADDR(r)) + break; + /* + * Some part of this segment is in the region. + * Trim the edges in the case where we span regions. + */ + mach_vm_offset_t loaddr = sc->vmaddr + scoffset; + mach_vm_offset_t hiaddr = loaddr + sc->vmsize; + if (loaddr < R_ADDR(r)) + loaddr = R_ADDR(r); + if (hiaddr > R_ENDADDR(r)) + hiaddr = R_ENDADDR(r); + + struct subregionlist *srl = calloc(1, sizeof (*srl)); + struct subregion *s = new_subregion(loaddr, hiaddr - loaddr, sc, le); + assert(sc->fileoff >= 0); + srl->srl_s = s; + STAILQ_INSERT_HEAD(srlh, srl, srl_linkage); + + if (opt->debug > 3) { + hsize_str_t hstr; + printr(r, "subregion %llx-%llx %7s %12s\t%s [%x/%x off %zd for %zd nsects %u flags %x]\n", + S_ADDR(s), S_ENDADDR(s), + str_hsize(hstr, S_SIZE(s)), + scsegname, + S_FILENAME(s), + sc->initprot, sc->maxprot, + sc->fileoff, sc->filesize, + sc->nsects, sc->flags); + } + break; + default: + break; + } + if (lc->cmdsize) + lc = (const void *)((caddr_t)lc + lc->cmdsize); + else + break; + } + return WALK_CONTINUE; +} + +/* + * Because we aggregate information from multiple sources, there may + * be duplicate subregions. Eliminate them here. + * + * Note that the each library in the shared cache points + * separately at a single, unified (large!) __LINKEDIT section; these + * get removed here too. + * + * Assumes the subregion array is sorted by address! + */ +static void +eliminate_duplicate_subregions(struct region *r) +{ + unsigned i = 1; + while (i < r->r_nsubregions) { + struct subregion *s0 = r->r_subregions[i-1]; + struct subregion *s1 = r->r_subregions[i]; + + if (S_ADDR(s0) != S_ADDR(s1) || S_SIZE(s0) != S_SIZE(s1)) { + i++; + continue; + } + if (memcmp(&s0->s_segcmd, &s1->s_segcmd, sizeof (s0->s_segcmd)) != 0) { + i++; + continue; + } + if (opt->debug) + printr(r, "eliding duplicate %s subregion (%llx-%llx) file %s\n", + S_MACHO_TYPE(s1), S_ADDR(s1), S_ENDADDR(s1), S_FILENAME(s1)); + /* If the duplicate subregions aren't mapping the same file (?), forget the name */ + if (s0->s_libent != s1->s_libent) + s0->s_libent = s1->s_libent = NULL; + elide_subregion(r, i); + } +} + +/* + * See if any of the dyld information we have can better describe this + * region of the target address space. + */ +walk_return_t +decorate_memory_region(struct region *r, void *arg) +{ + const dyld_process_info dpi = arg; + + __block walk_return_t retval = WALK_CONTINUE; + __block subregionlisthead_t srlhead = STAILQ_HEAD_INITIALIZER(srlhead); + + _dyld_process_info_for_each_image(dpi, ^(uint64_t mhaddr, const uuid_t uuid, __unused const char *path) { + if (WALK_CONTINUE == retval) { + const struct libent *le = libent_lookup_byuuid(uuid); + assert(le->le_mhaddr == mhaddr); + /* + * Core dumps conventionally contain the whole executable, but we're trying + * to elide everything that can't be found in a file elsewhere. + */ +#if 0 + if (MH_EXECUTE == le->le_mh->filetype) + return; // cause the whole a.out to be emitted +#endif + retval = add_subregions_for_libent(&srlhead, r, le->le_mh, le->le_mhaddr, le); + } + }); + if (WALK_CONTINUE != retval) + goto done; + + /* + * Take the unsorted list of subregions, if any, + * and hang a sorted array of ranges on the region structure. + */ + if (!STAILQ_EMPTY(&srlhead)) { + struct subregionlist *srl; + STAILQ_FOREACH(srl, &srlhead, srl_linkage) { + r->r_nsubregions++; + } + assert(r->r_nsubregions); + + r->r_subregions = calloc(r->r_nsubregions, sizeof (void *)); + unsigned i = 0; + STAILQ_FOREACH(srl, &srlhead, srl_linkage) { + r->r_subregions[i++] = srl->srl_s; + } + qsort_b(r->r_subregions, r->r_nsubregions, sizeof (void *), + ^(const void *a, const void *b) { + const struct subregion *lhs = *(struct subregion **)a; + const struct subregion *rhs = *(struct subregion **)b; + if (S_ADDR(lhs) > S_ADDR(rhs)) + return 1; + if (S_ADDR(lhs) < S_ADDR(rhs)) + return -1; + return 0; + }); + + eliminate_duplicate_subregions(r); + + const struct libent *lesc = NULL; /* libent ref for shared cache */ + if (r->r_insharedregion) { + uuid_t uusc; + if (get_sc_uuid(dpi, uusc)) { + lesc = libent_lookup_byuuid(uusc); + assert(NULL == lesc->le_mh && 0 == lesc->le_mhaddr); + } + } + + /* + * Only very specific segment types get to be filerefs + */ + for (i = 0; i < r->r_nsubregions; i++) { + struct subregion *s = r->r_subregions[i]; + /* + * Anything writable is trivially disqualified + */ + if (s->s_segcmd.initprot & VM_PROT_WRITE) + continue; + /* + * As long as there's a filename, __TEXT and __LINKEDIT + * end up as a file reference. + * + * __LINKEDIT is more complicated: the segment commands point + * at a unified segment in the shared cache mapping. + * Ditto for __UNICODE(?) + */ + if (issubregiontype(s, SEG_TEXT)) { + /* fall through */; + } else if (issubregiontype(s, SEG_LINKEDIT)) { + if (r->r_insharedregion) + s->s_libent = lesc; + } else if (issubregiontype(s, "__UNICODE")) { + if (r->r_insharedregion) + s->s_libent = lesc; + } else + continue; + + if (s->s_libent) + s->s_isfileref = true; + } + } + assert(WALK_CONTINUE == retval); + +done: + if (!STAILQ_EMPTY(&srlhead)) { + struct subregionlist *srl, *trl; + STAILQ_FOREACH_SAFE(srl, &srlhead, srl_linkage, trl) { + free(srl); + } + } + return retval; +} + +/* + * Strip region of all decoration + * + * Invoked (on every region!) after an error during the initial + * 'decoration' phase to discard to discard potentially incomplete + * information. + */ +walk_return_t +undecorate_memory_region(struct region *r, __unused void *arg) +{ + assert(&sparse_ops != r->r_op); + return r->r_nsubregions ? clean_subregions(r) : WALK_CONTINUE; +} + +/* + * This optimization occurs -after- the vanilla_region_optimizations(), + * and -after- we've tagged zfod and first-pass fileref's. + */ +walk_return_t +sparse_region_optimization(struct region *r, __unused void *arg) +{ + assert(&sparse_ops != r->r_op); + + if (r->r_inzfodregion) { + /* + * Pure zfod region: almost certainly a more compact + * representation - keep it that way. + */ + assert(&zfod_ops == r->r_op); + return clean_subregions(r); + } + +#ifdef CONFIG_REFSC + if (r->r_fileref) { + /* + * Already have a fileref for the whole region: almost + * certainly a more compact representation - keep + * it that way. + */ + assert(&fileref_ops == r->r_op); + return clean_subregions(r); + } +#endif + + if (r->r_insharedregion && 0 == r->r_nsubregions) { + /* + * A segment in the shared region needs to be + * identified with an LC_SEGMENT that dyld claims, + * otherwise (we assert) it's not useful to the dump. + */ + if (opt->debug) { + hsize_str_t hstr; + printr(r, "not referenced in dyld info => " + "eliding %s range in shared region\n", + str_hsize(hstr, R_SIZE(r))); + } + return WALK_DELETE_REGION; + } + + if (r->r_nsubregions > 1) { + /* + * Merge adjacent or identical subregions that have no file reference + * (Reducing the number of subregions reduces header overhead and + * improves compressability) + */ + unsigned i = 1; + while (i < r->r_nsubregions) { + struct subregion *s0 = r->r_subregions[i-1]; + struct subregion *s1 = r->r_subregions[i]; + + if (s0->s_isfileref) { + i++; + continue; /* => destined to be a fileref */ + } + if (!issamesubregiontype(s0, s1)) { + i++; + continue; /* merge-able subregions must have same "type" */ + } + + if (S_ENDADDR(s0) == S_ADDR(s1)) { + /* directly adjacent subregions */ +#if 1 + if (opt->debug) + printr(r, "merging subregions (%llx-%llx + %llx-%llx) -- adjacent\n", + S_ADDR(s0), S_ENDADDR(s0), S_ADDR(s1), S_ENDADDR(s1)); +#endif + S_SETSIZE(s0, S_ENDADDR(s1) - S_ADDR(s0)); + elide_subregion(r, i); + continue; + } + + const mach_vm_size_t pfn[2] = { + S_ADDR(s0) >> pageshift_host, + S_ADDR(s1) >> pageshift_host + }; + const mach_vm_size_t endpfn[2] = { + (S_ENDADDR(s0) - 1) >> pageshift_host, + (S_ENDADDR(s1) - 1) >> pageshift_host + }; + + if (pfn[0] == pfn[1] && pfn[0] == endpfn[0] && pfn[0] == endpfn[1]) { + /* two small subregions share a host page */ +#if 1 + if (opt->debug) + printr(r, "merging subregions (%llx-%llx + %llx-%llx) -- same page\n", + S_ADDR(s0), S_ENDADDR(s0), S_ADDR(s1), S_ENDADDR(s1)); +#endif + S_SETSIZE(s0, S_ENDADDR(s1) - S_ADDR(s0)); + elide_subregion(r, i); + continue; + } + + if (pfn[1] == 1 + endpfn[0]) { + /* subregions are pagewise-adjacent: bigger chunks to compress */ +#if 1 + if (opt->debug) + printr(r, "merging subregions (%llx-%llx + %llx-%llx) -- adjacent pages\n", + S_ADDR(s0), S_ENDADDR(s0), S_ADDR(s1), S_ENDADDR(s1)); +#endif + S_SETSIZE(s0, S_ENDADDR(s1) - S_ADDR(s0)); + elide_subregion(r, i); + continue; + } + + i++; /* this isn't the subregion we're looking for */ + } + } + + if (r->r_nsubregions) + r->r_op = &sparse_ops; + + return WALK_CONTINUE; +} diff --git a/gcore.tproj/sparse.h b/gcore.tproj/sparse.h new file mode 100644 index 0000000..1880bc5 --- /dev/null +++ b/gcore.tproj/sparse.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "region.h" +#include "dyld.h" + +#ifndef _SPARSE_H +#define _SPARSE_H + +struct subregion { + mach_vm_offset_t s_address; + mach_vm_offset_t s_size; + native_segment_command_t s_segcmd; + const struct libent *s_libent; + bool s_isfileref; +}; + +static __inline void S_SETADDR(struct subregion *s, mach_vm_offset_t a) { + s->s_address = a; +} + +static __inline void S_SETSIZE(struct subregion *s, mach_vm_offset_t sz) { + s->s_size = sz; +} + +static __inline const mach_vm_offset_t S_ADDR(const struct subregion *s) { + return s->s_address; +} + +static __inline const mach_vm_offset_t S_SIZE(const struct subregion *s) { + return s->s_size; +} + +static __inline const mach_vm_offset_t S_ENDADDR(const struct subregion *s) { + return S_ADDR(s) + S_SIZE(s); +} + +static __inline const char *S_MACHO_TYPE(const struct subregion *s) { + return s->s_segcmd.segname; +} + +static __inline off_t S_MACHO_FILEOFF(const struct subregion *s) { + return s->s_segcmd.fileoff; +} + +static __inline off_t S_MACHO_FILESIZE(const struct subregion *s) { + return s->s_segcmd.filesize; +} + +static __inline const struct libent *S_LIBENT(const struct subregion *s) { + return s->s_libent; +} + +static __inline const char *S_PATHNAME(const struct subregion *s) { + const struct libent *le = S_LIBENT(s); + return le ? le->le_pathname : "(unknown)"; +} + +static __inline const char *S_FILENAME(const struct subregion *s) { + const struct libent *le = S_LIBENT(s); + return le ? le->le_filename : S_PATHNAME(s); +} + +extern bool issubregiontype(const struct subregion *, const char *); + +extern walk_region_cbfn_t decorate_memory_region; +extern walk_region_cbfn_t undecorate_memory_region; +extern walk_region_cbfn_t sparse_region_optimization; + +#endif /* _SPARSE_H */ diff --git a/gcore.tproj/threads.c b/gcore.tproj/threads.c new file mode 100644 index 0000000..9903803 --- /dev/null +++ b/gcore.tproj/threads.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "utils.h" +#include "threads.h" +#include "corefile.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + int flavor; + mach_msg_type_number_t count; +} threadflavor_t; + +static threadflavor_t thread_flavor[] = { +#if defined(__i386__) || defined(__x86_64__) + { x86_THREAD_STATE, x86_THREAD_STATE_COUNT }, + { x86_FLOAT_STATE, x86_FLOAT_STATE_COUNT }, + { x86_EXCEPTION_STATE, x86_EXCEPTION_STATE_COUNT }, +#elif defined(__arm__) + { ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT }, + { ARM_VFP_STATE, ARM_VFP_STATE_COUNT }, + { ARM_EXCEPTION_STATE, ARM_EXCEPTION_STATE_COUNT }, +#elif defined(__arm64__) + { ARM_THREAD_STATE64, ARM_THREAD_STATE64_COUNT }, + /* ARM64_TODO: NEON? */ + { ARM_EXCEPTION_STATE64, ARM_EXCEPTION_STATE64_COUNT }, +#else +#error architecture not supported +#endif +}; + +static const int nthread_flavors = sizeof (thread_flavor) / sizeof (thread_flavor[0]); + +size_t +sizeof_LC_THREAD() +{ + size_t cmdsize = sizeof (struct thread_command); + for (int i = 0; i < nthread_flavors; i++) { + cmdsize += sizeof (thread_flavor[i]) + + thread_flavor[i].count * sizeof (int); + } + return cmdsize; +} + +void +dump_thread_state(native_mach_header_t *mh, struct thread_command *tc, mach_port_t thread) +{ + tc->cmd = LC_THREAD; + tc->cmdsize = (uint32_t) sizeof_LC_THREAD(); + + uint32_t *wbuf = (void *)(tc + 1); + + for (int f = 0; f < nthread_flavors; f++) { + + memcpy(wbuf, &thread_flavor[f], sizeof (thread_flavor[f])); + wbuf += sizeof (thread_flavor[f]) / sizeof (*wbuf); + + const kern_return_t kr = thread_get_state(thread, thread_flavor[f].flavor, (thread_state_t)wbuf, &thread_flavor[f].count); + if (KERN_SUCCESS != kr) { + err_mach(kr, NULL, "getting flavor %d of thread", + thread_flavor[f].flavor); + bzero(wbuf, thread_flavor[f].count * sizeof (int)); + } + + wbuf += thread_flavor[f].count; + } + mach_header_inc_ncmds(mh, 1); + mach_header_inc_sizeofcmds(mh, tc->cmdsize); +} diff --git a/gcore.tproj/threads.h b/gcore.tproj/threads.h new file mode 100644 index 0000000..c5605ce --- /dev/null +++ b/gcore.tproj/threads.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include "corefile.h" +#include + +#ifndef _THREADS_H +#define _THREADS_H + +extern size_t sizeof_LC_THREAD(void); +extern void dump_thread_state(native_mach_header_t *, struct thread_command *, mach_port_t); + +#endif /* _THREADS_H */ diff --git a/gcore.tproj/utils.c b/gcore.tproj/utils.c new file mode 100644 index 0000000..2c90967 --- /dev/null +++ b/gcore.tproj/utils.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "utils.h" +#include "region.h" + +#include +#include +#include +#include +#include +#include +#include + +void +err_mach(kern_return_t kr, const struct region *r, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (0 != kr) + printf("%s: ", pgm); + if (NULL != r) + printf("%llx-%llx ", R_ADDR(r), R_ENDADDR(r)); + vprintf(fmt, ap); + va_end(ap); + + if (0 != kr) { + printf(": %s (%x)", mach_error_string(kr), kr); + switch (err_get_system(kr)) { + case err_get_system(err_mach_ipc): + /* 0x10000000 == (4 << 26) */ + printf(" => fatal\n"); + exit(127); + default: + putchar('\n'); + break; + } + } else + putchar('\n'); +} + +void +printr(const struct region *r, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (NULL != r) + printf("%llx-%llx ", R_ADDR(r), R_ENDADDR(r)); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +/* + * Print power-of-1024 sizes in human-readable form + */ +const char * +str_hsize(hsize_str_t hstr, uint64_t size) +{ + humanize_number(hstr, sizeof (hsize_str_t) - 1, size, "", + HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL | HN_IEC_PREFIXES); + return hstr; +} + +/* + * Put two strings together separated by a '+' sign + * If the string gets too long, then add an elipsis and + * stop concatenating it. + */ +char * +strconcat(const char *s0, const char *s1, size_t maxlen) +{ + const char ellipsis[] = "..."; + const char junction[] = ", "; + const size_t s0len = strlen(s0); + size_t nmlen = s0len + strlen(s1) + strlen(junction) + 1; + if (maxlen > strlen(ellipsis) && nmlen > maxlen) { + if (strcmp(s0 + s0len - strlen(ellipsis), ellipsis) == 0) + return strdup(s0); + s1 = ellipsis; + nmlen = s0len + strlen(s1) + strlen(junction) + 1; + } + char *p = malloc(nmlen); + if (p) { + strlcpy(p, s0, nmlen); + strlcat(p, junction, nmlen); + strlcat(p, s1, nmlen); + } + return p; +} diff --git a/gcore.tproj/utils.h b/gcore.tproj/utils.h new file mode 100644 index 0000000..890f837 --- /dev/null +++ b/gcore.tproj/utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef _UTILS_H +#define _UTILS_H + +extern const char *pgm; + +struct region; + +extern void err_mach(kern_return_t, const struct region *r, const char *fmt, ...) __printflike(3, 4); +extern void printr(const struct region *r, const char *fmt, ...) __printflike(2, 3); + +typedef char hsize_str_t[7]; /* e.g. 1008Mib */ + +extern const char *str_hsize(hsize_str_t hstr, uint64_t); +extern char *strconcat(const char *, const char *, size_t); + +#endif /* _UTILS_H */ diff --git a/gcore.tproj/vanilla.c b/gcore.tproj/vanilla.c new file mode 100644 index 0000000..61f9c09 --- /dev/null +++ b/gcore.tproj/vanilla.c @@ -0,0 +1,708 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "vm.h" +#include "region.h" +#include "utils.h" +#include "dyld.h" +#include "threads.h" +#include "vanilla.h" +#include "sparse.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +walk_return_t +vanilla_region_optimization(struct region *r, __unused void *arg) +{ + assert(0 != R_SIZE(r)); + + /* + * Elide unreadable regions + */ + if ((r->r_info.max_protection & VM_PROT_READ) != VM_PROT_READ) { + if (opt->debug) + printr(r, "eliding unreadable region\n"); + return WALK_DELETE_REGION; + } +#ifdef CONFIG_SUBMAP + /* + * Elide submaps (here for debugging purposes?) + */ + if (r->r_info.is_submap) { + if (opt->debug) + printr(r, "eliding submap\n"); + return WALK_DELETE_REGION; + } +#endif + /* + * Elide guard regions + */ + if (r->r_info.protection == VM_PROT_NONE && + (VM_MEMORY_STACK == r->r_info.user_tag || + VM_MEMORY_MALLOC == r->r_info.user_tag)) { + if (opt->debug) { + hsize_str_t hstr; + printr(r, "eliding %s - guard\n", + str_hsize(hstr, R_SIZE(r))); + } + return WALK_DELETE_REGION; + } + return WALK_CONTINUE; +} + +/* + * (Paranoid validation + debugging assistance.) + */ +static void +validate_core_header(const native_mach_header_t *mh, off_t corefilesize) +{ + if (opt->debug) + printf("Core file: mh %p ncmds %u sizeofcmds %u\n", + mh, mh->ncmds, mh->sizeofcmds); + + const struct load_command *lc = (const void *)(mh + 1); + for (unsigned i = 0; i < mh->ncmds; i++) { + + if ((uintptr_t)lc < (uintptr_t)mh || + (uintptr_t)lc > (uintptr_t)mh + mh->sizeofcmds) { + warnx("load command %p outside mach header range [%p, 0x%lx]?", + lc, mh, (uintptr_t)mh + mh->sizeofcmds); + abort(); + } + if (opt->debug) + printf("lc %p cmd %u cmdsize %u ", lc, lc->cmd, lc->cmdsize); + + const native_segment_command_t *sc; + const struct proto_coreinfo_command *cic; + const struct proto_fileref_command *frc; + const struct thread_command *tc; + + switch (lc->cmd) { + case NATIVE_LC_SEGMENT: + sc = (const void *)lc; + if (opt->debug) { + printf("%8s: mem %llx-%llx file %lld-%lld %x/%x flags %x\n", + "SEGMENT", + (mach_vm_offset_t)sc->vmaddr, + (mach_vm_offset_t)sc->vmaddr + sc->vmsize, + (off_t)sc->fileoff, + (off_t)sc->fileoff + (off_t)sc->filesize, + sc->initprot, sc->maxprot, sc->flags); + } + if ((off_t)sc->fileoff < mh->sizeofcmds || + (off_t)sc->filesize < 0) { + warnx("bad segment command"); + abort(); + } + if ((off_t)sc->fileoff > corefilesize || + (off_t)sc->fileoff + (off_t)sc->filesize > corefilesize) { + /* + * We may have run out of space to write the data + */ + warnx("segment command points beyond end of file"); + } + break; + + case proto_LC_COREINFO: + cic = (const void *)lc; + if (opt->debug) { + uuid_string_t uustr; + uuid_unparse_lower(cic->uuid, uustr); + printf("%8s: version %d type %d uuid %s addr %llx dyninfo %llx\n", + "COREINFO", cic->version, cic->type, uustr, cic->address, cic->dyninfo); + } + if (cic->version < 1 || + cic->type != proto_CORETYPE_USER) { + warnx("bad coreinfo command"); + abort(); + } + break; + + case proto_LC_FILEREF: + frc = (const void *)lc; + const char *nm = frc->filename.offset + (char *)lc; + if (opt->debug) { + uuid_string_t uustr; + uuid_unparse_lower(frc->uuid, uustr); + printf("%8s: mem %llx-%llx file %lld-%lld %x/%x '%s' %.12s..\n", + "FILEREF", + frc->vmaddr, + frc->vmaddr + frc->vmsize, + (off_t)frc->fileoff, + (off_t)frc->fileoff + (off_t)frc->filesize, + frc->initprot, frc->maxprot, nm, uustr); + } + if (nm <= (caddr_t)lc || + nm > (caddr_t)lc + lc->cmdsize || + (off_t)frc->fileoff < 0 || (off_t)frc->filesize < 0) { + warnx("bad fileref command"); + abort(); + } + break; + + case LC_THREAD: + tc = (const void *)lc; + if (opt->debug) + printf("%8s:\n", "THREAD"); + uint32_t *wbuf = (void *)(tc + 1); + do { + const uint32_t flavor = *wbuf++; + const uint32_t count = *wbuf++; + + if (opt->debug) { + printf(" flavor %u count %u\n", flavor, count); + if (count) { + boolean_t nl = false; + for (unsigned k = 0; k < count; k++) { + if (0 == (k & 7)) + printf(" [%3u] ", k); + printf("%08x ", *wbuf++); + if (7 == (k & 7)) { + printf("\n"); + nl = true; + } else + nl = false; + } + if (!nl) + printf("\n"); + } + } else + wbuf += count; + + if (!VALID_THREAD_STATE_FLAVOR(flavor)) { + warnx("bad thread state flavor"); + abort(); + } + } while ((caddr_t) wbuf < (caddr_t)tc + tc->cmdsize); + break; + + default: + warnx("unknown cmd %u in header\n", lc->cmd); + abort(); + } + if (lc->cmdsize) + lc = (const void *)((caddr_t)lc + lc->cmdsize); + else + break; + } +} + +/* + * The vanilla Mach-O core file consists of: + * + * - A Mach-O header of type MH_CORE + * + * A set of load commands of the following types: + * + * - LC_SEGMENT{,_64} pointing at memory content in the file, + * each chunk consisting of a contiguous region. Regions may be zfod + * (no file content present) or content may be compressed (experimental) + * + * - prototype_LC_COREINFO (experimental), pointing at dyld (10.12 onwards) + * + * - prototype_LC_FILEREF (experimental) pointing at memory + * content to be mapped in from another file at various offsets + * + * - LC_THREAD commands with state for each thread + * + * These load commands are followed by the relevant contents of memory, + * pointed to by the various commands. + */ + +int +coredump_write( + const task_t task, + const int fd, + struct regionhead *rhead, + const uuid_t aout_uuid, + mach_vm_offset_t aout_load_addr, + mach_vm_offset_t dyld_aii_addr) +{ + struct size_segment_data ssda; + bzero(&ssda, sizeof (ssda)); + + if (walk_region_list(rhead, region_size_memory, &ssda) < 0) { + warnx(0, "cannot count segments"); + return EX_OSERR; + } + + unsigned thread_count = 0; + mach_port_t *threads = NULL; + kern_return_t ret = task_threads(task, &threads, &thread_count); + if (KERN_SUCCESS != ret || thread_count < 1) { + err_mach(ret, NULL, "cannot retrieve threads"); + thread_count = 0; + } + + if (opt->debug) { + print_memory_region_header(); + walk_region_list(rhead, region_print_memory, NULL); + } + + size_t headersize = sizeof (native_mach_header_t) + + thread_count * sizeof_LC_THREAD() + + ssda.ssd_fileref.headersize + + ssda.ssd_zfod.headersize + + ssda.ssd_vanilla.headersize + + ssda.ssd_sparse.headersize; + if (opt->coreinfo) + headersize += sizeof (struct proto_coreinfo_command); + + void *header = calloc(1, headersize); + if (NULL == header) + errx(EX_OSERR, "out of memory for header"); + + native_mach_header_t *mh = make_corefile_mach_header(header); + struct load_command *lc = (void *)(mh + 1); + + if (opt->coreinfo) { + const struct proto_coreinfo_command *cc = + make_coreinfo_command(mh, lc, aout_uuid, aout_load_addr, dyld_aii_addr); + lc = (void *)((caddr_t)cc + cc->cmdsize); + } + + if (opt->debug) { + const unsigned long fileref_count = ssda.ssd_fileref.count; + const unsigned long segment_count = fileref_count + + ssda.ssd_zfod.count + ssda.ssd_vanilla.count + ssda.ssd_sparse.count; + printf("Dumping %lu memory segments", segment_count); + if (0 != fileref_count) + printf(" (including %lu file reference%s (%lu bytes))", + fileref_count, 1 == fileref_count ? "" : "s", + ssda.ssd_fileref.headersize); + printf("\n"); + } + + vm_size_t pagesize = ((vm_offset_t)1 << pageshift_host); + vm_offset_t pagemask = (vm_offset_t)(pagesize - 1); + + struct write_segment_data wsda = { + .wsd_task = task, + .wsd_mh = mh, + .wsd_lc = lc, + .wsd_fd = fd, + .wsd_foffset = ((vm_offset_t)headersize + pagemask) & ~pagemask, + .wsd_nwritten = 0, + }; + + int ecode = 0; + if (0 != walk_region_list(rhead, region_write_memory, &wsda)) + ecode = EX_IOERR; + + del_region_list(rhead); + + struct thread_command *tc = (void *)wsda.wsd_lc; + + for (unsigned t = 0; t < thread_count; t++) { + dump_thread_state(mh, tc, threads[t]); + mach_port_deallocate(mach_task_self(), threads[t]); + tc = (void *)((caddr_t)tc + tc->cmdsize); + } + + /* + * Even if we've run out of space, try our best to + * write out the header. + */ + if (-1 == pwrite(fd, header, headersize, 0)) + ecode = EX_IOERR; + else + wsda.wsd_nwritten += headersize; + + validate_core_header(mh, wsda.wsd_foffset); + + if (ecode) + warnx("failed to write core file correctly"); + else if (opt->verbose) { + hsize_str_t hsz; + printf("Wrote %s to corefile ", str_hsize(hsz, wsda.wsd_nwritten)); + printf("(memory image %s", str_hsize(hsz, ssda.ssd_vanilla.memsize)); + if (ssda.ssd_sparse.memsize) + printf("+%s", str_hsize(hsz, ssda.ssd_sparse.memsize)); + if (ssda.ssd_fileref.memsize) + printf(", referenced %s", str_hsize(hsz, ssda.ssd_fileref.memsize)); + if (ssda.ssd_zfod.memsize) + printf(", zfod %s", str_hsize(hsz, ssda.ssd_zfod.memsize)); + printf(")\n"); + } + free(header); + return ecode; +} + +int +coredump(task_t task, int fd) +{ + /* this is the shared cache id, if any */ + uuid_t sc_uuid; + uuid_clear(sc_uuid); + + dyld_process_info dpi = get_task_dyld_info(task); + if (dpi) { + get_sc_uuid(dpi, sc_uuid); + } + + /* this group is for LC_COREINFO */ + mach_vm_offset_t dyld_addr = 0; // all_image_infos -or- dyld mach header + mach_vm_offset_t aout_load_addr = 0; + uuid_t aout_uuid; + uuid_clear(aout_uuid); + + /* + * Walk the address space + */ + int ecode = 0; + struct regionhead *rhead = coredump_prepare(task, sc_uuid); + if (NULL == rhead) { + ecode = EX_OSERR; + goto done; + } + + if (opt->debug) + printf("Optimizing dump content\n"); + walk_region_list(rhead, vanilla_region_optimization, NULL); + + if (dpi) { + if (opt->coreinfo || opt->sparse) { + /* + * Snapshot dyld's info .. + */ + if (!libent_build_nametable(task, dpi)) + warnx("error parsing dyld data => ignored"); + else { + if (opt->coreinfo) { + /* + * Find the a.out load address and uuid, and the dyld mach header for the coreinfo + */ + const struct libent *le; + if (NULL != (le = libent_lookup_first_bytype(MH_EXECUTE))) { + aout_load_addr = le->le_mhaddr; + uuid_copy(aout_uuid, le->le_uuid); + } + if (NULL != (le = libent_lookup_first_bytype(MH_DYLINKER))) { + dyld_addr = le->le_mhaddr; + } + } + if (opt->sparse) { + /* + * Use dyld's view of what's being used in the address + * space to shrink the dump. + */ + if (0 == walk_region_list(rhead, decorate_memory_region, (void *)dpi)) { + if (opt->debug) + printf("Performing sparse dump optimization(s)\n"); + walk_region_list(rhead, sparse_region_optimization, NULL); + } else { + walk_region_list(rhead, undecorate_memory_region, NULL); + warnx("error parsing dyld data => ignored"); + } + } + } + } + free_task_dyld_info(dpi); + } + + if (opt->debug) + printf("Optimization(s) done\n"); +done: + if (0 == ecode) + ecode = coredump_write(task, fd, rhead, aout_uuid, aout_load_addr, dyld_addr); + return ecode; +} + +#ifdef CONFIG_REFSC + +struct find_shared_cache_args { + task_t fsc_task; + vm_object_id_t fsc_object_id; + vm32_object_id_t fsc_region_object_id; + uuid_t fsc_uuid; + const struct libent *fsc_le; + int fsc_fd; +}; + +/* + * This is "find the objid of the first shared cache" in the shared region. + */ +static walk_return_t +find_shared_cache(struct region *r, void *arg) +{ + struct find_shared_cache_args *fsc = arg; + + if (!r->r_insharedregion) + return WALK_CONTINUE; /* wrong address range! */ + if (0 != r->r_info.user_tag) + return WALK_CONTINUE; /* must be tag zero */ + if ((VM_PROT_READ | VM_PROT_EXECUTE) != r->r_info.protection || + r->r_info.protection != r->r_info.max_protection) + return WALK_CONTINUE; /* must be r-x / r-x */ + if (r->r_pageinfo.offset != 0) + return WALK_CONTINUE; /* must map beginning of file */ + + if (opt->debug) { + hsize_str_t hstr; + printf("Examining shared cache candidate %llx-%llx (%s)\n", + R_ADDR(r), R_ENDADDR(r), str_hsize(hstr, R_SIZE(r))); + } + + struct copied_dyld_cache_header *ch; + mach_msg_type_number_t chlen = sizeof (*ch); + kern_return_t ret = mach_vm_read(fsc->fsc_task, R_ADDR(r), sizeof (*ch), (vm_offset_t *)&ch, &chlen); + + if (KERN_SUCCESS != ret) { + err_mach(ret, NULL, "mapping candidate shared region"); + return WALK_CONTINUE; + } + + uuid_t scuuid; + if (get_uuid_from_shared_cache_mapping(ch, chlen, scuuid) && + uuid_compare(scuuid, fsc->fsc_uuid) == 0) { + if (opt->debug > 2) { + uuid_string_t uustr; + uuid_unparse_lower(fsc->fsc_uuid, uustr); + printr(r, "found shared cache %s here\n", uustr); + } + if (!r->r_info.external_pager) { + if (opt->debug) + printf("Hmm. Found shared cache magic# + uuid, but not externally paged?\n"); +#if 0 + return WALK_CONTINUE; /* should be "paged" from a file */ +#endif + } + // This is the ID associated with the first page of the mapping + fsc->fsc_object_id = r->r_pageinfo.object_id; + // This is the ID associated with the region + fsc->fsc_region_object_id = r->r_info.object_id; + } + mach_vm_deallocate(mach_task_self(), (vm_offset_t)ch, chlen); + if (fsc->fsc_object_id) { + if (opt->debug) { + uuid_string_t uu; + uuid_unparse_lower(fsc->fsc_uuid, uu); + printf("Shared cache objid %llx uuid %s\n", + fsc->fsc_object_id, uu); + } + return WALK_TERMINATE; + } + return WALK_CONTINUE; +} + +static boolean_t +compare_region_with_shared_cache(const struct region *r, struct find_shared_cache_args *fsc) +{ + struct stat st; + if (-1 == fstat(fsc->fsc_fd, &st)) { + if (opt->debug) + printr(r, "%s - %s\n", + fsc->fsc_le->le_filename, strerror(errno)); + return false; + } + void *file = mmap(NULL, (size_t)R_SIZE(r), PROT_READ, MAP_PRIVATE, fsc->fsc_fd, r->r_pageinfo.offset); + if ((void *)-1L == file) { + if (opt->debug) + printr(r, "mmap %s - %s\n", fsc->fsc_le->le_filename, strerror(errno)); + return false; + } + madvise(file, (size_t)R_SIZE(r), MADV_SEQUENTIAL); + + vm_offset_t data = 0; + mach_msg_type_number_t data_count; + const kern_return_t kr = mach_vm_read(fsc->fsc_task, R_ADDR(r), R_SIZE(r), &data, &data_count); + + if (KERN_SUCCESS != kr || data_count < R_SIZE(r)) { + err_mach(kr, r, "mach_vm_read()"); + munmap(file, (size_t)R_SIZE(r)); + return false; + } + + mach_vm_size_t cmpsize = data_count; + +#ifdef RDAR_23744374 + /* + * Now we have the corresponding regions mapped, we should be + * able to compare them. There's just one last twist that relates + * to heterogenous pagesize systems: rdar://23744374 + */ + if (st.st_size < (off_t)(r->r_pageinfo.offset + cmpsize) && + pageshift_host < pageshift_app) { + /* + * Looks like we're about to map close to the end of the object. + * Check what's really mapped there and reduce the size accordingly. + */ + if (!is_actual_size(fsc->fsc_task, r, &cmpsize)) { + if (opt->debug) + printr(r, "narrowing the comparison (%llu " + "-> %llu)\n", R_SIZE(r), cmpsize); + } + } +#endif + + mach_vm_behavior_set(mach_task_self(), data, data_count, VM_BEHAVIOR_SEQUENTIAL); + + const boolean_t thesame = memcmp(file, (void *)data, (size_t)cmpsize) == 0; +#if 0 + if (!thesame) { + int diffcount = 0; + int samecount = 0; + const char *f = file; + const char *d = (void *)data; + for (mach_vm_size_t off = 0; off < cmpsize; off += 4096) { + if (memcmp(f, d, 4096) != 0) { + diffcount++; + } else samecount++; + f += 4096; + d += 4096; + } + if (diffcount) + printr(r, "%d of %d pages different\n", diffcount, diffcount + samecount); + } +#endif + mach_vm_deallocate(mach_task_self(), data, data_count); + munmap(file, (size_t)R_SIZE(r)); + + if (!thesame && opt->debug) + printr(r, "mapped file (%s) region is modified\n", fsc->fsc_le->le_filename); + return thesame; +} + +static walk_return_t +label_shared_cache(struct region *r, void *arg) +{ + struct find_shared_cache_args *fsc = arg; + + if (!r->r_insharedregion) + return WALK_CONTINUE; + if (!r->r_info.external_pager) + return WALK_CONTINUE; + if (r->r_pageinfo.object_id != fsc->fsc_object_id) { + /* wrong object, or first page already modified */ + return WALK_CONTINUE; + } + if (((r->r_info.protection | r->r_info.max_protection) & VM_PROT_WRITE) != 0) { + /* writable, but was it written? */ + if (r->r_info.pages_dirtied + r->r_info.pages_swapped_out != 0) + return WALK_CONTINUE; // a heuristic .. + if (!compare_region_with_shared_cache(r, fsc)) { + /* bits don't match */ + return WALK_CONTINUE; + } + } + + if (opt->debug > 2) { + /* this validation is -really- expensive */ + if (!compare_region_with_shared_cache(r, fsc)) + printr(r, "WARNING: region should match, but doesn't\n"); + } + + /* + * This mapped file segment will be represented as a reference + * to the file, rather than as a copy of the file. + */ + const struct libent *le = libent_lookup_byuuid(fsc->fsc_uuid); + r->r_fileref = calloc(1, sizeof (*r->r_fileref)); + if (r->r_fileref) { + r->r_fileref->fr_libent = le; + if (r->r_fileref->fr_libent) { + r->r_fileref->fr_offset = r->r_pageinfo.offset; + r->r_op = &fileref_ops; + } else { + free(r->r_fileref); + r->r_fileref = NULL; + } + } + return WALK_CONTINUE; +} +#endif /* CONFIG_REFSC */ + +struct regionhead * +coredump_prepare(task_t task, uuid_t sc_uuid) +{ + struct regionhead *rhead = build_region_list(task); + + if (opt->debug) { + print_memory_region_header(); + walk_region_list(rhead, region_print_memory, NULL); + } + + if (uuid_is_null(sc_uuid)) + return rhead; + + /* + * Name the shared cache, if we can + */ + char *nm = shared_cache_filename(sc_uuid); + const struct libent *le; + + if (NULL != nm) + le = libent_insert(nm, sc_uuid, 0, NULL); + else { + le = libent_insert("(shared cache)", sc_uuid, 0, NULL); + if (opt->verbose){ + uuid_string_t uustr; + uuid_unparse_lower(sc_uuid, uustr); + printf("Shared cache UUID: %s, but no filename => ignored\n", uustr); + return rhead; + } + } + +#ifdef CONFIG_REFSC + if (opt->scfileref) { + /* + * See if we can replace entire regions with references to the shared cache + * by looking at the VM meta-data about those regions. + */ + if (opt->debug) { + uuid_string_t uustr; + uuid_unparse_lower(sc_uuid, uustr); + printf("Searching for shared cache with uuid %s\n", uustr); + } + + /* + * Identify the regions mapping the shared cache by comparing the UUID via + * dyld with the UUID of likely-looking mappings in the right address range + */ + struct find_shared_cache_args fsca; + bzero(&fsca, sizeof (fsca)); + fsca.fsc_task = task; + uuid_copy(fsca.fsc_uuid, sc_uuid); + fsca.fsc_fd = -1; + + walk_region_list(rhead, find_shared_cache, &fsca); + + if (0 == fsca.fsc_object_id) { + printf("Cannot identify the shared cache region(s) => ignored\n"); + } else { + if (opt->verbose) + printf("Referenced %s\n", nm); + fsca.fsc_le = le; + fsca.fsc_fd = open(fsca.fsc_le->le_filename, O_RDONLY); + + walk_region_list(rhead, label_shared_cache, &fsca); + + close(fsca.fsc_fd); + free(nm); + } + } +#endif /* CONFIG_REFSC */ + + return rhead; +} diff --git a/gcore.tproj/vanilla.h b/gcore.tproj/vanilla.h new file mode 100644 index 0000000..ac29e85 --- /dev/null +++ b/gcore.tproj/vanilla.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "vm.h" + +#ifndef _VANILLA_H +#define _VANILLA_H + +extern walk_region_cbfn_t vanilla_region_optimization; + +extern int coredump(task_t, int); +extern int coredump_write(task_t, int, struct regionhead *, const uuid_t, mach_vm_offset_t, mach_vm_offset_t); +extern struct regionhead *coredump_prepare(task_t, uuid_t); + +#endif /* _VANILLA_H */ diff --git a/gcore.tproj/vm.c b/gcore.tproj/vm.c new file mode 100644 index 0000000..fdd6814 --- /dev/null +++ b/gcore.tproj/vm.c @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include "options.h" +#include "vm.h" +#include "utils.h" +#include "region.h" +#include "sparse.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * There should be better APIs to describe the shared region + * For now, some hackery. + */ + +#include + +static __inline boolean_t +in_shared_region(mach_vm_address_t addr) +{ + const mach_vm_address_t base = SHARED_REGION_BASE; + const mach_vm_address_t size = SHARED_REGION_SIZE; + return addr >= base && addr < (base + size); +} + +/* + * On both x64 and arm, there's a globallly-shared + * read-only page at _COMM_PAGE_START_ADDRESS + * which low-level library routines reference. + * + * On x64, somewhere randomly chosen between _COMM_PAGE_TEXT_ADDRESS + * and the top of the user address space, there's the + * pre-emption-free-zone read-execute page. + */ + +#include + +static __inline boolean_t +in_comm_region(const mach_vm_address_t addr, const vm_region_submap_info_data_64_t *info) +{ + return addr >= _COMM_PAGE_START_ADDRESS && + SM_TRUESHARED == info->share_mode && + VM_INHERIT_SHARE == info->inheritance && + !info->external_pager && (info->max_protection & VM_PROT_WRITE) == 0; +} + +static __inline boolean_t +in_zfod_region(const vm_region_submap_info_data_64_t *info) +{ + return info->share_mode == SM_EMPTY && !info->is_submap && + 0 == info->object_id && !info->external_pager && + 0 == info->pages_dirtied + info->pages_resident + info->pages_swapped_out; +} + +static struct region * +new_region(mach_vm_offset_t vmaddr, mach_vm_size_t vmsize, const vm_region_submap_info_data_64_t *infop) +{ + struct region *r = calloc(1, sizeof (*r)); + assert(vmaddr != 0 && vmsize != 0); + R_SETADDR(r, vmaddr); + R_SETSIZE(r, vmsize); + r->r_info = *infop; +#ifdef CONFIG_PURGABLE + r->r_purgable = VM_PURGABLE_DENY; +#endif + r->r_insharedregion = in_shared_region(vmaddr); + r->r_incommregion = in_comm_region(vmaddr, &r->r_info); + r->r_inzfodregion = in_zfod_region(&r->r_info); + + if (r->r_inzfodregion) + r->r_op = &zfod_ops; + else + r->r_op = &vanilla_ops; + return r; +} + +#ifdef CONFIG_REFSC +void +del_fileref_region(struct region *r) +{ + assert(&fileref_ops == r->r_op); + /* r->r_fileref->fr_libent is a reference into the name table */ + poison(r->r_fileref, 0xdeadbee9, sizeof (*r->r_fileref)); + free(r->r_fileref); + poison(r, 0xdeadbeeb, sizeof (*r)); + free(r); +} +#endif /* CONFIG_REFSC */ + +void +del_zfod_region(struct region *r) +{ + assert(&zfod_ops == r->r_op); + assert(r->r_inzfodregion && 0 == r->r_nsubregions); +#ifdef CONFIG_REFSC + assert(NULL == r->r_fileref); +#endif + poison(r, 0xdeadbeed, sizeof (*r)); + free(r); +} + +void +del_vanilla_region(struct region *r) +{ + assert(&vanilla_ops == r->r_op); + assert(!r->r_inzfodregion && 0 == r->r_nsubregions); +#ifdef CONFIG_REFSC + assert(NULL == r->r_fileref); +#endif + poison(r, 0xdeadbeef, sizeof (*r)); + free(r); +} + +/* + * "does any part of this address range match the tag?" + */ +int +is_tagged(task_t task, mach_vm_offset_t addr, mach_vm_offset_t size, unsigned tag) +{ + mach_vm_offset_t vm_addr = addr; + mach_vm_offset_t vm_size = 0; + natural_t depth = 0; + size_t pgsize = (1u << pageshift_host); + + do { + mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; + vm_region_submap_info_data_64_t info; + + kern_return_t ret = mach_vm_region_recurse(task, &vm_addr, &vm_size, &depth, (vm_region_recurse_info_t)&info, &count); + + if (KERN_FAILURE == ret) { + err_mach(ret, NULL, "error inspecting task at %llx", vm_addr); + return -1; + } else if (KERN_INVALID_ADDRESS == ret) { + err_mach(ret, NULL, "invalid address at %llx", vm_addr); + return -1; + } else if (KERN_SUCCESS != ret) { + err_mach(ret, NULL, "error inspecting task at %llx", vm_addr); + return -1; + } + if (info.is_submap) { + depth++; + continue; + } + if (info.user_tag == tag) + return 1; + if (vm_addr + vm_size > addr + size) + return 0; + vm_addr += pgsize; + } while (1); +} + +STAILQ_HEAD(regionhead, region); + +/* + * XXX Need something like mach_vm_shared_region_recurse() + * to properly identify the shared region address ranges as + * we go. + */ + +static int +walk_regions(task_t task, struct regionhead *rhead) +{ + mach_vm_offset_t vm_addr = MACH_VM_MIN_ADDRESS; + natural_t depth = 0; + + if (opt->debug > 3) + print_memory_region_header(); + + while (1) { + vm_region_submap_info_data_64_t info; + mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; + mach_vm_size_t vm_size; + + kern_return_t ret = mach_vm_region_recurse(task, &vm_addr, &vm_size, &depth, (vm_region_recurse_info_t)&info, &count); + + if (KERN_FAILURE == ret) { + err_mach(ret, NULL, "error inspecting task at %llx", vm_addr); + goto bad; + } else if (KERN_INVALID_ADDRESS == ret) { + break; /* loop termination */ + } else if (KERN_SUCCESS != ret) { + err_mach(ret, NULL, "error inspecting task at %llx", vm_addr); + goto bad; + } + + if (opt->debug > 3) { + struct region *d = new_region(vm_addr, vm_size, &info); + ROP_PRINT(d); + ROP_DELETE(d); + } + + if (info.is_submap) { +#ifdef CONFIG_SUBMAP + /* We also want to see submaps -- for debugging purposes. */ + struct region *r = new_region(vm_addr, vm_size, &info); + r->r_depth = depth; + STAILQ_INSERT_TAIL(rhead, r, r_linkage); +#endif + depth++; + continue; + } + + if (VM_MEMORY_IOKIT == info.user_tag) { + vm_addr += vm_size; + continue; // ignore immediately: IO memory has side-effects + } + + struct region *r = new_region(vm_addr, vm_size, &info); +#ifdef CONFIG_SUBMAP + r->r_depth = depth; +#endif + /* grab the page info of the first page in the mapping */ + + mach_msg_type_number_t pageinfoCount = VM_PAGE_INFO_BASIC_COUNT; + ret = mach_vm_page_info(task, R_ADDR(r), VM_PAGE_INFO_BASIC, (vm_page_info_t)&r->r_pageinfo, &pageinfoCount); + if (KERN_SUCCESS != ret) + err_mach(ret, r, "getting pageinfo at %llx", R_ADDR(r)); + +#ifdef CONFIG_PURGABLE + /* record the purgability */ + + ret = mach_vm_purgable_control(task, vm_addr, VM_PURGABLE_GET_STATE, &r->r_purgable); + if (KERN_SUCCESS != ret) + r->r_purgable = VM_PURGABLE_DENY; +#endif + STAILQ_INSERT_TAIL(rhead, r, r_linkage); + + vm_addr += vm_size; + } + + return 0; +bad: + return EX_OSERR; +} + +void +del_region_list(struct regionhead *rhead) +{ + struct region *r, *t; + + STAILQ_FOREACH_SAFE(r, rhead, r_linkage, t) { + STAILQ_REMOVE(rhead, r, region, r_linkage); + ROP_DELETE(r); + } + free(rhead); +} + +struct regionhead * +build_region_list(task_t task) +{ + struct regionhead *rhead = malloc(sizeof (*rhead)); + STAILQ_INIT(rhead); + if (0 != walk_regions(task, rhead)) { + del_region_list(rhead); + return NULL; + } + return rhead; +} + +int +walk_region_list(struct regionhead *rhead, walk_region_cbfn_t cbfn, void *arg) +{ + struct region *r, *t; + + STAILQ_FOREACH_SAFE(r, rhead, r_linkage, t) { + switch (cbfn(r, arg)) { + case WALK_CONTINUE: + break; + case WALK_DELETE_REGION: + STAILQ_REMOVE(rhead, r, region, r_linkage); + ROP_DELETE(r); + break; + case WALK_TERMINATE: + goto done; + case WALK_ERROR: + return -1; + } + } +done: + return 0; +} + +int pageshift_host; +int pageshift_app; + +void +setpageshift(void) +{ + if (0 == pageshift_host) { + vm_size_t hps = 0; + kern_return_t ret = host_page_size(MACH_PORT_NULL, &hps); + if (KERN_SUCCESS != ret || hps == 0) + err_mach(ret, NULL, "host page size"); + int pshift = 0; + while (((vm_offset_t)1 << pshift) != hps) + pshift++; + pageshift_host = pshift; + } + if (opt->debug) + printf("host page size: %lu\n", 1ul << pageshift_host); + + if (0 == pageshift_app) { + size_t psz = getpagesize(); + int pshift = 0; + while ((1ul << pshift) != psz) + pshift++; + pageshift_app = pshift; + } + if (opt->debug && pageshift_app != pageshift_host) + printf("app page size: %lu\n", 1ul << pageshift_app); +} + +static const char * +strshared(const int sm) +{ + switch (sm) { + case SM_COW: + return "cow"; + case SM_PRIVATE: + return "priv"; + case SM_EMPTY: + return "empty"; + case SM_SHARED: + return "shr"; + case SM_TRUESHARED: + return "true_shr"; + case SM_PRIVATE_ALIASED: + return "priv_alias"; + case SM_SHARED_ALIASED: + return "shr_alias"; + case SM_LARGE_PAGE: + return "large_pg"; + default: + return "share?"; + } +} + +typedef char prot_str_t[9]; /* rwxNCWT& */ + +static const char * +str_prot(prot_str_t pstr, const vm_prot_t prot) +{ + snprintf(pstr, sizeof (prot_str_t), "%c%c%c", + prot & VM_PROT_READ ? 'r' : '-', + prot & VM_PROT_WRITE ? 'w' : '-', + prot & VM_PROT_EXECUTE ? 'x' : '-'); + /* for completeness */ + if (prot & VM_PROT_NO_CHANGE) + strlcat(pstr, "N", sizeof (prot_str_t)); + if (prot & VM_PROT_COPY) + strlcat(pstr, "C", sizeof (prot_str_t)); + if (prot & VM_PROT_WANTS_COPY) + strlcat(pstr, "W", sizeof (prot_str_t)); + if (prot & 0x20) + strlcat(pstr, "T", sizeof (prot_str_t)); + if (prot & VM_PROT_IS_MASK) + strlcat(pstr, "&", sizeof (prot_str_t)); + return pstr; +} + +void +print_memory_region_header(void) +{ + printf("%-33s %c %-7s %-7s %8s %16s ", + "Address Range", 'S', "Size", "Cur/Max", "Obj32", "FirstPgObjectID"); + printf("%9s %-3s %-11s %5s ", + "Offset", "Tag", "Mode", "Refc"); +#ifdef CONFIG_SUBMAP + printf("%5s ", "Depth"); +#endif + printf("%5s %5s %5s %3s ", + "Res", "SNP", "Dirty", "Pgr"); + printf("\n"); +} + +static __inline char +region_type(const struct region *r) +{ +#ifdef CONFIG_REFSC + if (r->r_fileref) + return 'f'; +#endif + if (r->r_inzfodregion) + return 'z'; + if (r->r_incommregion) + return 'c'; + if (r->r_insharedregion) + return 's'; + return ' '; +} + +void +print_memory_region(const struct region *r) +{ + prot_str_t pstr, pstr_max; + hsize_str_t hstr; + + printf("%016llx-%016llx %c %-7s %s/%s %8x %16llx ", + R_ADDR(r), R_ENDADDR(r), region_type(r), + str_hsize(hstr, R_SIZE(r)), + str_prot(pstr, r->r_info.protection), + str_prot(pstr_max, r->r_info.max_protection), + r->r_info.object_id, r->r_pageinfo.object_id + ); + + printf("%9lld %3d %-11s %5u ", + r->r_info.external_pager ? + r->r_pageinfo.offset : r->r_info.offset, + r->r_info.user_tag, + strshared(r->r_info.share_mode), + r->r_info.ref_count + ); +#ifdef CONFIG_SUBMAP + printf("%5u ", r->r_depth); +#endif + + if (!r->r_info.is_submap) { + printf("%5u %5u %5u %3s ", + r->r_info.pages_resident, + r->r_info.pages_shared_now_private, + r->r_info.pages_dirtied, + r->r_info.external_pager ? "ext" : ""); +#if CONFIG_REFSC + if (r->r_fileref) + printf("\n %s at %lld ", + r->r_fileref->fr_libent->le_filename, + r->r_fileref->fr_offset); +#endif + printf("\n"); + if (r->r_nsubregions) { + printf(" %-33s %7s %12s\t%s\n", + "Address Range", "Size", "Type(s)", "Filename(s)"); + for (unsigned i = 0; i < r->r_nsubregions; i++) { + struct subregion *s = r->r_subregions[i]; + printf(" %016llx-%016llx %7s %12s\t%s\n", + S_ADDR(s), S_ENDADDR(s), + str_hsize(hstr, S_SIZE(s)), + S_MACHO_TYPE(s), + S_FILENAME(s)); + } + } + } else { + switch (r->r_info.user_tag) { + case VM_MEMORY_SHARED_PMAP: + printf("// VM_MEMORY_SHARED_PMAP"); + break; + case VM_MEMORY_UNSHARED_PMAP: + printf("// VM_MEMORY_UNSHARED_PMAP"); + break; + default: + printf("// is a submap"); + break; + } + printf("\n"); + } +} + +walk_return_t +region_print_memory(struct region *r, __unused void *arg) +{ + ROP_PRINT(r); + return WALK_CONTINUE; +} + +#ifdef RDAR_23744374 +/* + * The reported size of a mapping to a file object gleaned from + * mach_vm_region_recurse() can exceed the underlying size of the file. + * If we attempt to write out the full reported size, we find that we + * error (EFAULT) or if we compress it, we die with the SIGBUS. + * + * See rdar://23744374 + * + * Figure out what the "non-faulting" size of the object is to + * *host* page size resolution. + */ +boolean_t +is_actual_size(const task_t task, const struct region *r, mach_vm_size_t *hostvmsize) +{ + if (!r->r_info.external_pager || + (r->r_info.max_protection & VM_PROT_READ) == VM_PROT_NONE) + return true; + + const size_t pagesize_host = 1ul << pageshift_host; + const unsigned filepages = r->r_info.pages_resident + + r->r_info.pages_swapped_out; + + if (pagesize_host * filepages == R_SIZE(r)) + return true; + + /* + * Verify that the last couple of host-pagesize pages + * of a file backed mapping are actually pageable in the + * underlying object by walking backwards from the end + * of the application-pagesize mapping. + */ + *hostvmsize = R_SIZE(r); + + const long npagemax = 1ul << (pageshift_app - pageshift_host); + for (long npage = 0; npage < npagemax; npage++) { + + const mach_vm_address_t taddress = + R_ENDADDR(r) - pagesize_host * (npage + 1); + if (taddress < R_ADDR(r) || taddress >= R_ENDADDR(r)) + break; + + mach_msg_type_number_t pCount = VM_PAGE_INFO_BASIC_COUNT; + vm_page_info_basic_data_t pInfo; + + kern_return_t ret = mach_vm_page_info(task, taddress, VM_PAGE_INFO_BASIC, (vm_page_info_t)&pInfo, &pCount); + if (KERN_SUCCESS != ret) { + err_mach(ret, NULL, "getting pageinfo at %llx", taddress); + break; /* bail */ + } + + /* + * If this page has been in memory before, assume it can + * be brought back again + */ + if (pInfo.disposition & (VM_PAGE_QUERY_PAGE_PRESENT | VM_PAGE_QUERY_PAGE_REF | VM_PAGE_QUERY_PAGE_DIRTY | VM_PAGE_QUERY_PAGE_PAGED_OUT)) + continue; + + /* + * Force the page to be fetched to see if it faults + */ + mach_vm_size_t tsize = 1ul << pageshift_host; + void *tmp = valloc((size_t)tsize); + const mach_vm_address_t vtmp = (mach_vm_address_t)tmp; + + switch (ret = mach_vm_read_overwrite(task, + taddress, tsize, vtmp, &tsize)) { + case KERN_INVALID_ADDRESS: + *hostvmsize = taddress - R_ADDR(r); + break; + case KERN_SUCCESS: + break; + default: + err_mach(ret, NULL, "mach_vm_overwrite()"); + break; + } + free(tmp); + } + return R_SIZE(r) == *hostvmsize; +} +#endif diff --git a/gcore.tproj/vm.h b/gcore.tproj/vm.h new file mode 100644 index 0000000..b029bea --- /dev/null +++ b/gcore.tproj/vm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "corefile.h" +#include "region.h" + +#ifndef _VM_H +#define _VM_H + +extern void setpageshift(void); +extern int pageshift_host; +extern int pageshift_app; + +struct region; +struct regionhead; + +#ifdef CONFIG_REFSC +extern void del_fileref_region(struct region *); +#endif +extern void del_zfod_region(struct region *); +extern void del_sparse_region(struct region *); +extern void del_vanilla_region(struct region *); + +extern struct regionhead *build_region_list(task_t); +extern int walk_region_list(struct regionhead *, walk_region_cbfn_t, void *); +extern void del_region_list(struct regionhead *); + +extern void print_memory_region_header(void); +extern void print_memory_region(const struct region *); + +extern walk_region_cbfn_t region_print_memory; +extern walk_region_cbfn_t region_write_memory; +extern walk_region_cbfn_t region_size_memory; + +extern int is_tagged(task_t, mach_vm_offset_t, mach_vm_offset_t, unsigned); + +#ifdef RDAR_23744374 +extern boolean_t is_actual_size(const task_t, const struct region *, mach_vm_size_t *); +#endif + +#endif /* _VM_H */ diff --git a/getconf.tproj/getconf.c b/getconf.tproj/getconf.c index 5ee262d..b2a2752 100644 --- a/getconf.tproj/getconf.c +++ b/getconf.tproj/getconf.c @@ -109,13 +109,13 @@ main(int argc, char **argv) do_confstr(name, key); else printf("undefined\n"); - } else { + } else { valid = find_sysconf(name, &key); if (valid > 0) { do_sysconf(name, key); } else if (valid < 0) { printf("undefined\n"); - } else + } else errx(EX_USAGE, "no such configuration parameter `%s'", name); @@ -187,4 +187,3 @@ do_pathconf(const char *name, int key, const char *path) else printf("%ld\n", value); } - diff --git a/getty.tproj/chat.c b/getty.tproj/chat.c index 9094722..d79aae7 100644 --- a/getty.tproj/chat.c +++ b/getty.tproj/chat.c @@ -23,8 +23,10 @@ * For semi-intelligent modem handling. */ +#include + #ifndef lint -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/libexec/getty/chat.c,v 1.11 2005/04/06 17:42:24 stefanf Exp $"; #endif /* not lint */ @@ -367,9 +369,9 @@ chat_expect(const char *str) } } alarm(0); - chat_unalarm(); - alarmed = 0; - free(got); + chat_unalarm(); + alarmed = 0; + free(got); } } @@ -401,13 +403,13 @@ chat_send(char const *str) unsigned char ch = (unsigned char)*str++; if (alarmed) - r = 3; + r = 3; else if (ch == PAUSE_CH) usleep(500000); /* 1/2 second */ else { usleep(10000); /* be kind to modem */ if (write(STDOUT_FILENO, &ch, 1) != 1) - r = alarmed ? 3 : 2; + r = alarmed ? 3 : 2; } } alarm(0); diff --git a/getty.tproj/init.c b/getty.tproj/init.c index 7982b5c..a0d69d2 100644 --- a/getty.tproj/init.c +++ b/getty.tproj/init.c @@ -31,11 +31,13 @@ * SUCH DAMAGE. */ +#include + #ifndef lint #if 0 static char sccsid[] = "@(#)from: init.c 8.1 (Berkeley) 6/4/93"; #endif -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/libexec/getty/init.c,v 1.16 2005/04/06 17:42:24 stefanf Exp $"; #endif /* not lint */ @@ -115,13 +117,13 @@ struct gettynums gettynums[] = { { "o0" }, /* output o_flags */ { "o1" }, /* input o_flags */ { "o2" }, /* user mode o_flags */ - { "de" }, /* delay before sending 1st prompt */ + { "de" }, /* delay before sending 1st prompt */ { "rt" }, /* reset timeout */ { "ct" }, /* chat script timeout */ { "dc" }, /* debug chat script value */ - { 0 } + { 0 } }; - + struct gettyflags gettyflags[] = { { "ht", 0 }, /* has tabs */ diff --git a/getty.tproj/main.c b/getty.tproj/main.c index 77313e0..12c78b6 100644 --- a/getty.tproj/main.c +++ b/getty.tproj/main.c @@ -34,7 +34,7 @@ #include #ifndef lint -static const char copyright[] = +__unused static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ @@ -43,7 +43,7 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93"; #endif -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/libexec/getty/main.c,v 1.47 2005/04/06 17:42:24 stefanf Exp $"; #endif /* not lint */ @@ -290,12 +290,12 @@ main(int argc, char *argv[]) int i, rfds; struct timeval to; - rfds = 1 << 0; /* FD_SET */ - to.tv_sec = RT; - to.tv_usec = 0; - i = select(32, (fd_set*)&rfds, (fd_set*)NULL, - (fd_set*)NULL, RT ? &to : NULL); - if (i < 0) { + rfds = 1 << 0; /* FD_SET */ + to.tv_sec = RT; + to.tv_usec = 0; + i = select(32, (fd_set*)&rfds, (fd_set*)NULL, + (fd_set*)NULL, RT ? &to : NULL); + if (i < 0) { syslog(LOG_ERR, "select %s: %m", ttyn); } else if (i == 0) { syslog(LOG_NOTICE, "recycle tty %s", ttyn); @@ -323,7 +323,7 @@ main(int argc, char *argv[]) for (;;) { /* - * if a delay was specified then sleep for that + * if a delay was specified then sleep for that * number of seconds before writing the initial prompt */ if (first_sleep && DE) { @@ -479,7 +479,7 @@ opentty(const char *tty, int flags) } sleep(60); } - if (login_tty(i) < 0) { + if (login_tty(i) < 0) { #ifndef __APPLE__ if (daemon(0,0) < 0) { syslog(LOG_ERR,"daemon: %m"); @@ -497,7 +497,7 @@ opentty(const char *tty, int flags) } static void -defttymode() +defttymode(void) { /* Start with default tty settings. */ @@ -842,7 +842,6 @@ putf(const char *cp) static void dogettytab() { - /* Read the database entry. */ gettable(tname); diff --git a/getty.tproj/subr.c b/getty.tproj/subr.c index 00bb982..2bff200 100644 --- a/getty.tproj/subr.c +++ b/getty.tproj/subr.c @@ -31,11 +31,13 @@ * SUCH DAMAGE. */ +#include + #ifndef lint #if 0 static char sccsid[] = "@(#)from: subr.c 8.1 (Berkeley) 6/4/93"; #endif -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/libexec/getty/subr.c,v 1.19 2004/06/25 10:11:28 phk Exp $"; #endif /* not lint */ @@ -58,8 +60,6 @@ static const char rcsid[] = #include "pathnames.h" #include "extern.h" - - /* * Get a table entry. */ diff --git a/hostinfo.tproj/hostinfo.c b/hostinfo.tproj/hostinfo.c index 65cd143..1993b30 100644 --- a/hostinfo.tproj/hostinfo.c +++ b/hostinfo.tproj/hostinfo.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,10 +18,10 @@ * 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@ */ -/* +/* * Mach Operating System * Copyright (c) 1990 Carnegie-Mellon University * All rights reserved. The CMU software License Agreement specifies @@ -48,13 +48,14 @@ struct host_basic_info hi; kernel_version_t version; int slots[1024]; -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { kern_return_t ret; unsigned int size, count; char *cpu_name, *cpu_subname; int i; - int mib[2]; + int mib[2]; size_t len; uint64_t memsize; processor_set_name_port_t default_pset; @@ -108,7 +109,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if (hi.max_cpus > 1) printf("Kernel configured for up to %d processors.\n", hi.max_cpus); @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) printf(" %s (%s)\n", cpu_name, cpu_subname); printf("Processor%s active:", (hi.avail_cpus > 1) ? "s" : ""); - for (i = 0; i < hi.avail_cpus; i++) + for (i = 0; i < hi.avail_cpus; i++) printf(" %d", i); printf("\n"); @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) else printf("Primary memory available: %.2f megabytes\n", (float)memsize/(1024.0*1024.0)); - + printf("Default processor set: %d tasks, %d threads, %d processors\n", load_info.task_count, load_info.thread_count, basic_info.processor_count); printf("Load average: %d.%02d, Mach factor: %d.%02d\n", @@ -146,4 +146,3 @@ int main(int argc, char *argv[]) exit(0); } - diff --git a/iosim.tproj/iosim.c b/iosim.tproj/iosim.c index 349b9c8..51cf5b0 100644 --- a/iosim.tproj/iosim.c +++ b/iosim.tproj/iosim.c @@ -15,39 +15,39 @@ #include #include -#define IO_MODE_SEQ 0 -#define IO_MODE_RANDOM 1 - -#define WORKLOAD_TYPE_RO 0 -#define WORKLOAD_TYPE_WO 1 -#define WORKLOAD_TYPE_RW 2 - -#define MAX_THREADS 1000 -#define MAX_FILENAME 64 -#define MAX_ITERATIONS 10000 -#define LATENCY_BIN_SIZE 500 -#define LATENCY_BINS 11 -#define LOW_LATENCY_BIN_SIZE 50 -#define LOW_LATENCY_BINS 11 +#define IO_MODE_SEQ 0 +#define IO_MODE_RANDOM 1 + +#define WORKLOAD_TYPE_RO 0 +#define WORKLOAD_TYPE_WO 1 +#define WORKLOAD_TYPE_RW 2 + +#define MAX_THREADS 1000 +#define MAX_FILENAME 64 +#define MAX_ITERATIONS 10000 +#define LATENCY_BIN_SIZE 500 +#define LATENCY_BINS 11 +#define LOW_LATENCY_BIN_SIZE 50 +#define LOW_LATENCY_BINS 11 #define THROUGHPUT_INTERVAL 5000 -#define DEFAULT_FILE_SIZE (262144) -#define BLOCKSIZE 1024 -#define MAX_CMD_SIZE 256 -#define PG_MASK ~(0xFFF) - -int burst_count = 10; /* Unit: Number ; Desc.: I/O Burst Count */ -int inter_burst_duration = 0; /* Unit: msecs ; Desc.: I/O Inter-Burst Duration (-1: Random value [0,100]) */ -int inter_io_delay_ms = 0; /* Unit: msecs ; Desc.: Inter I/O Delay */ -int thread_count = 1; /* Unit: Number ; Desc.: Thread Count */ +#define DEFAULT_FILE_SIZE (262144) +#define BLOCKSIZE 1024 +#define MAX_CMD_SIZE 256 +#define PG_MASK ~(0xFFF) + +int burst_count = 10; /* Unit: Number ; Desc.: I/O Burst Count */ +int inter_burst_duration = 0; /* Unit: msecs ; Desc.: I/O Inter-Burst Duration (-1: Random value [0,100]) */ +int inter_io_delay_ms = 0; /* Unit: msecs ; Desc.: Inter I/O Delay */ +int thread_count = 1; /* Unit: Number ; Desc.: Thread Count */ int workload_type = WORKLOAD_TYPE_RO; /* Unit: 0/1/2 ; Desc.: Workload Type */ -int io_size = 4096; /* Unit: Bytes ; Desc.: I/O Unit Size */ -int sync_frequency_ms = 0; /* Unit: msecs ; Desc.: Sync thread frequency (0: Indicates no sync) */ -int io_mode = 0; /* Unit: 0/1 ; Desc.: I/O Mode (Seq./Rand.) */ +int io_size = 4096; /* Unit: Bytes ; Desc.: I/O Unit Size */ +int sync_frequency_ms = 0; /* Unit: msecs ; Desc.: Sync thread frequency (0: Indicates no sync) */ +int io_mode = 0; /* Unit: 0/1 ; Desc.: I/O Mode (Seq./Rand.) */ int test_duration = 0; /* Unit: secs ; Desc.: Total Test Duration (0 indicates wait for Ctrl+C signal) */ -int io_tier = 0; /* Unit: 0/1/2/3; Desc.: I/O Tier */ -int file_size = DEFAULT_FILE_SIZE; /* Unit: pages ; Desc.: File Size in 4096 byte blocks */ -int cached_io_flag = 0; /* Unit: 0/1 ; Desc.: I/O Caching behavior (no-cached/cached) */ -char *user_fname; +int io_tier = 0; /* Unit: 0/1/2/3; Desc.: I/O Tier */ +int file_size = DEFAULT_FILE_SIZE; /* Unit: pages ; Desc.: File Size in 4096 byte blocks */ +int cached_io_flag = 0; /* Unit: 0/1 ; Desc.: I/O Caching behavior (no-cached/cached) */ +char *user_fname; int user_specified_file = 0; int64_t total_io_count; @@ -74,7 +74,8 @@ void print_test_setup(int value, char *option, char *units, char *comment); void setup_process_io_policy(int io_tier); void print_latency_histogram(int64_t *data, int latency_bins, int latency_bin_size); -void print_usage() +void +print_usage(void) { printf("Usage: ./iosim [options]\n"); printf("Options:\n"); @@ -133,7 +134,7 @@ void print_stats() printf("I/O Statistics:\n"); printf("Total I/Os : %lld\n", total_io_count); - printf("Avg. Latency : %.2lf usecs\n", ((double)total_io_time) / ((double)total_io_count)); + printf("Avg. Latency : %.2lf usecs\n", ((double)total_io_time) / ((double)total_io_count)); printf("Low Latency Histogram: \n"); print_latency_histogram(low_latency_histogram, LOW_LATENCY_BINS, LOW_LATENCY_BIN_SIZE); @@ -141,7 +142,7 @@ void print_stats() print_latency_histogram(latency_histogram, LATENCY_BINS, LATENCY_BIN_SIZE); printf("Burst Avg. Latency Histogram: \n"); print_latency_histogram(burst_latency_histogram, LATENCY_BINS, LATENCY_BIN_SIZE); - + printf("Throughput Timeline: \n"); int64_t max_throughput = 0; @@ -158,7 +159,6 @@ void print_stats() printf("%.2lf MBps\n", ((double)throughput_histogram[i] / 1048576.0) / ((double)THROUGHPUT_INTERVAL / 1000.0)); } printf("\n"); - } unsigned int find_io_bin(int64_t latency, int latency_bin_size, int latency_bins) @@ -190,14 +190,14 @@ void perform_io(int fd, char *buf, int size, int type) ret = read(fd, buf, size); else ret = write(fd, buf, size); - + if (ret == 0) { if (lseek(fd, 0, SEEK_SET) < 0) { perror("lseek() to reset file offset to zero failed!\n"); goto error; } } - + if (ret < 0) { perror("read/write syscall failed!\n"); goto error; @@ -214,7 +214,7 @@ error: void *sync_routine(void *arg) { - while(1) { + while(1) { usleep(sync_frequency_ms * 1000); sync(); } @@ -231,10 +231,10 @@ void *calculate_throughput(void *arg) size = total_io_size - prev_total_io_size; throughput_histogram[throughput_index] = size; prev_total_io_size = total_io_size; - throughput_index++; + throughput_index++; } pthread_exit(NULL); -} +} void *io_routine(void *arg) { @@ -261,7 +261,7 @@ void *io_routine(void *arg) if (fstat(fd, &filestat) < 0) { printf("Error stat()ing file %s!\n", test_filename); exit(1); - } + } if (filestat.st_size < io_size) { printf("%s: File size (%lld) smaller than I/O size (%d)!\n", test_filename, filestat.st_size, io_size); @@ -272,7 +272,7 @@ void *io_routine(void *arg) fcntl(fd, F_NOCACHE, 1); fcntl(fd, F_RDAHEAD, 0); - + if(!(data = (char *)calloc(io_size, 1))) { perror("Error allocating buffers for I/O!\n"); exit(1); @@ -280,7 +280,6 @@ void *io_routine(void *arg) memset(data, '\0', io_size); while(1) { - burst_elapsed = 0; for(i = 0; i < burst_count; i++) { @@ -290,7 +289,6 @@ void *io_routine(void *arg) exit(1); } } - gettimeofday(&start_tv, NULL); perform_io(fd, data, io_size, workload_type); @@ -303,7 +301,7 @@ void *io_routine(void *arg) OSAtomicIncrement64(&(latency_histogram[find_io_bin(elapsed, LATENCY_BIN_SIZE, LATENCY_BINS)])); OSAtomicIncrement64(&(low_latency_histogram[find_io_bin(elapsed, LOW_LATENCY_BIN_SIZE, LOW_LATENCY_BINS)])); burst_elapsed += elapsed; - + if (inter_io_delay_ms) usleep(inter_io_delay_ms * 1000); } @@ -423,7 +421,7 @@ int main(int argc, char *argv[]) case 'z': file_size = atoi(optarg); validate_option(file_size, 0, INT_MAX, "File Size", "bytes"); - break; + break; case 'n': user_fname = optarg; user_specified_file = 1; @@ -453,14 +451,14 @@ int main(int argc, char *argv[]) print_test_setup(io_tier, "I/O Tier", "", 0); print_test_setup(cached_io_flag, "I/O Caching", "", "0 indicates non-cached I/Os"); print_test_setup(0, "File read-aheads", "", "0 indicates read-aheads disabled"); - + printf("**********************************************************\n"); if (user_specified_file == 0) { char dd_command[MAX_CMD_SIZE]; for (i=0; i < thread_count; i++) { snprintf(fname, MAX_FILENAME, "iosim-%d-%d", (int)getpid(), i); - snprintf(dd_command, MAX_CMD_SIZE, "dd if=/dev/urandom of=%s bs=4096 count=%d", fname, file_size); + snprintf(dd_command, MAX_CMD_SIZE, "dd if=/dev/urandom of=%s bs=4096 count=%d", fname, file_size); printf("Creating file %s of size %lld...\n", fname, ((int64_t)file_size * 4096)); system(dd_command); } @@ -470,8 +468,8 @@ int main(int argc, char *argv[]) system("purge"); setup_process_io_policy(io_tier); - printf("**********************************************************\n"); - printf("Creating threads and generating workload...\n"); + printf("**********************************************************\n"); + printf("Creating threads and generating workload...\n"); signal(SIGINT, signalHandler); signal(SIGALRM, signalHandler); @@ -497,16 +495,15 @@ int main(int argc, char *argv[]) /* All threads are now initialized */ if (test_duration) - alarm(test_duration); + alarm(test_duration); for(i=0; i < thread_count; i++) pthread_join(thread_list[i], NULL); - + if (sync_frequency_ms) pthread_join(sync_thread, NULL); pthread_join(throughput_thread, NULL); pthread_exit(0); - } diff --git a/iostat.tproj/iostat.c b/iostat.tproj/iostat.c index a346053..58f62a2 100644 --- a/iostat.tproj/iostat.c +++ b/iostat.tproj/iostat.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /* @@ -190,7 +190,7 @@ static int record_device(io_registry_entry_t drive); static int compare_drivestats(const void* pa, const void* pb); -static long double compute_etime(struct timeval cur_time, +static long double compute_etime(struct timeval cur_time, struct timeval prev_time); static void @@ -315,7 +315,7 @@ main(int argc, char **argv) maxshowdevs = 4; } else { if ((dflag > 0) && (Cflag == 0)) - maxshowdevs = 4; + maxshowdevs = 4; else maxshowdevs = 3; } @@ -346,7 +346,7 @@ main(int argc, char **argv) waittime = atoi(*argv); /* Let the user know he goofed, but keep going anyway */ - if (wflag != 0) + if (wflag != 0) warnx("discarding previous wait interval, using" " %d instead", waittime); wflag++; @@ -412,7 +412,7 @@ main(int argc, char **argv) headercount = 20; do_phdr(); } - + last_time = cur_time; gettimeofday(&cur_time, NULL); @@ -431,7 +431,7 @@ main(int argc, char **argv) etime = 1.0; if (Tflag > 0) - printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, + printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, cur.tk_nout / etime); devstats(hflag, etime, havelast); @@ -464,11 +464,11 @@ static void phdr(int signo) { - phdr_flag = 1; + phdr_flag = 1; } static void -do_phdr() +do_phdr(void) { register int i; @@ -479,14 +479,14 @@ do_phdr() if (oflag > 0) (void)printf("%12.6s ", drivestat[i].name); else - printf("%15.6s ", drivestat[i].name); + printf("%19.6s ", drivestat[i].name); } - + if (Cflag > 0) (void)printf(" cpu"); if (Uflag > 0) - (void)printf(" load average\n"); + (void)printf(" load average\n"); else (void)printf("\n"); @@ -501,7 +501,7 @@ do_phdr() (void)printf(" blk xfr msps "); } else { if (Iflag == 0) - printf(" KB/t tps MB/s "); + printf(" KB/t tps MB/s "); else printf(" KB/t xfrs MB "); } @@ -605,7 +605,7 @@ devstats(int perf_select, long double etime, int havelast) * Compute delta values and stats. */ interval_bytes = total_bytes - drivestat[i].total_bytes; - interval_transfers = total_transfers + interval_transfers = total_transfers - drivestat[i].total_transfers; interval_time = total_time - drivestat[i].total_time; @@ -614,7 +614,7 @@ devstats(int perf_select, long double etime, int havelast) drivestat[i].total_bytes = total_bytes; drivestat[i].total_transfers = total_transfers; drivestat[i].total_time = total_time; - } + } interval_blocks = interval_bytes / drivestat[i].blocksize; total_blocks = total_bytes / drivestat[i].blocksize; @@ -624,16 +624,16 @@ devstats(int perf_select, long double etime, int havelast) mb_per_second = (interval_bytes / etime) / (1024 * 1024); kb_per_transfer = (interval_transfers > 0) ? - ((long double)interval_bytes / interval_transfers) + ((long double)interval_bytes / interval_transfers) / 1024 : 0; /* times are in nanoseconds, convert to milliseconds */ ms_per_transaction = (interval_transfers > 0) ? - ((long double)interval_time / interval_transfers) + ((long double)interval_time / interval_transfers) / 1000 : 0; if (Kflag) - total_blocks = total_blocks * drivestat[i].blocksize + total_blocks = total_blocks * drivestat[i].blocksize / 1024; if (oflag > 0) { @@ -645,7 +645,7 @@ devstats(int perf_select, long double etime, int havelast) transfers_per_second, msdig, ms_per_transaction); - else + else printf("%4.1qu%4.1qu%5.*Lf ", interval_blocks, interval_transfers, @@ -653,7 +653,7 @@ devstats(int perf_select, long double etime, int havelast) ms_per_transaction); } else { if (Iflag == 0) - printf(" %7.2Lf %3.0Lf %5.2Lf ", + printf(" %7.2Lf %4.0Lf %5.2Lf ", kb_per_transfer, transfers_per_second, mb_per_second); @@ -661,7 +661,7 @@ devstats(int perf_select, long double etime, int havelast) interval_mb = interval_bytes; interval_mb /= 1024 * 1024; - printf(" %7.2Lf %3.1qu %5.2Lf ", + printf(" %7.2Lf %3.1qu %5.2Lf ", kb_per_transfer, interval_transfers, interval_mb); @@ -706,7 +706,7 @@ cpustats(void) last.load.cpu_ticks[CPU_STATE_IDLE] += cur.load.cpu_ticks[CPU_STATE_IDLE]; time += cur.load.cpu_ticks[CPU_STATE_IDLE]; - + /* * Print times. */ @@ -779,8 +779,8 @@ compute_etime(struct timeval cur_time, struct timeval prev_time) timersub(&cur_time, &prev_time, &busy_time); - busy_usec = busy_time.tv_sec; - busy_usec *= 1000000; + busy_usec = busy_time.tv_sec; + busy_usec *= 1000000; busy_usec += busy_time.tv_usec; etime = busy_usec; etime /= 1000000; @@ -832,7 +832,8 @@ record_all_devices(void) return(0); } -static void record_drivelist(void* context, io_iterator_t drivelist) +static void +record_drivelist(void* context, io_iterator_t drivelist) { io_registry_entry_t drive; while ((drive = IOIteratorNext(drivelist))) { @@ -845,7 +846,8 @@ static void record_drivelist(void* context, io_iterator_t drivelist) qsort(drivestat, num_devices, sizeof(struct drivestats), &compare_drivestats); } -static void remove_drivelist(void* context, io_iterator_t drivelist) +static void +remove_drivelist(void* context, io_iterator_t drivelist) { io_registry_entry_t drive; while ((drive = IOIteratorNext(drivelist))) { @@ -936,7 +938,7 @@ record_device(io_registry_entry_t drive) CFStringRef name; CFNumberRef number; kern_return_t status; - + /* get drive's parent */ status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &parent); @@ -957,7 +959,7 @@ record_device(io_registry_entry_t drive) name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)); if (name) - CFStringGetCString(name, drivestat[num_devices].name, + CFStringGetCString(name, drivestat[num_devices].name, MAXDRIVENAME, kCFStringEncodingUTF8); else { errx(1, "device does not have a BSD name"); diff --git a/kdprof/Action.hpp b/kdprof/Action.hpp deleted file mode 100644 index c139122..0000000 --- a/kdprof/Action.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// Action.hpp -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_Action_hpp -#define kdprof_Action_hpp - -class Action { - public: - virtual void execute(Globals& globals) = 0; -}; - -#endif diff --git a/kdprof/CollectAction.cpp b/kdprof/CollectAction.cpp deleted file mode 100644 index 9bb6207..0000000 --- a/kdprof/CollectAction.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// CollectAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -template -static void execute_arch_specific(Globals& globals, KDState& state) { - // Collect all data first, printing takes time... - auto threadmap = KDBG::threadmap(state); - auto cpumap = KDBG::cpumap(); - - MemoryBuffer> events(state.capacity()); - int count = KDBG::read(events.data(), events.capacity() * sizeof(KDEvent)); - - // Now handle any verbose printing. - /*if (globals.is_verbose()) { - printf("\n%lu threadmap entries:\n", threadmap.size()); - for (auto& entry : threadmap) { - printf("\t0x%08llX %8u %20s\n", (uint64_t)entry.tid(), entry.pid(), entry.name()); - } - - printf("\n%lu cpumap entries:\n", cpumap.size()); - for (auto& entry : cpumap) { - printf("\t%3u %8s\n", entry.cpu_id(), entry.name()); - } - - printf("\n%d events:\n", count); - }*/ - - if (globals.should_presort_events()) { - std::sort(events.data(), events.data() + count, [](KDEvent const& p0, KDEvent const& p1) -> bool { - return p0.timestamp() < p1.timestamp(); - }); - } - Machine machine((KDCPUMapEntry*)cpumap.data(), (uint32_t)cpumap.size(), (KDThreadMapEntry*)threadmap.data(), (uint32_t)threadmap.size(), (KDEvent*)events.data(), (uintptr_t)count); - - if (!machine.lost_events()) { - if (globals.should_zero_base_timestamps() && count) { - globals.set_beginning_of_time((events.data())->timestamp()); - } else { - globals.set_beginning_of_time(AbsTime(0)); - } - - if (!globals.is_timebase_set()) { - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - globals.set_timebase(timebase, false); - } - - if (globals.is_verbose()) { - dprintf(globals.output_fd(), "\nLIVE DATA\n"); - print_verbose_machine_info(globals, machine, (uint32_t)threadmap.size(), (uint32_t)cpumap.size()); - } - - if (globals.should_print_events()) { - // print_machine(globals, machine); - // print_machine_parallel(globals, machine); - print_machine_events(globals, machine); - } - - if (globals.should_print_summary()) { - print_machine_summary(globals, machine); - } - - if (globals.should_print_csv_summary()) { - print_machine_csv_summary(globals, machine); - } - - if (globals.should_print_process_start_stop_timestamps()) { - print_process_start_stop_timestamps(globals, machine); - } - } else { - log_msg(ASL_LEVEL_WARNING, "The trace data indicates that events were lost, the file cannot be processed\n"); - } -} - -void CollectAction::execute(Globals& globals) { - KDState state = KDBG::state(); - if (state.is_lp64()) { - execute_arch_specific(globals, state); - } else { - execute_arch_specific(globals, state); - } -} diff --git a/kdprof/CollectAction.hpp b/kdprof/CollectAction.hpp deleted file mode 100644 index ae6cc2e..0000000 --- a/kdprof/CollectAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// CollectAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_CollectAction_hpp -#define kdprof_CollectAction_hpp - -class CollectAction : public Action { - public: - CollectAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/DisableAction.cpp b/kdprof/DisableAction.cpp deleted file mode 100644 index d54511e..0000000 --- a/kdprof/DisableAction.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// DisableAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void DisableAction::execute(Globals& globals) { - if (!KDBG::set_enabled(false)) { - usage("Unable to disable tracing"); - } -} diff --git a/kdprof/DisableAction.hpp b/kdprof/DisableAction.hpp deleted file mode 100644 index cc87c46..0000000 --- a/kdprof/DisableAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// DisableAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_DisableAction_hpp -#define kdprof_DisableAction_hpp - -class DisableAction : public Action { - public: - DisableAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/EnableAction.cpp b/kdprof/EnableAction.cpp deleted file mode 100644 index 9a9b169..0000000 --- a/kdprof/EnableAction.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// EnableAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void EnableAction::execute(Globals& globals) { - if (!KDBG::set_enabled(true)) { - usage("Unable to enable tracing"); - } -} diff --git a/kdprof/EnableAction.hpp b/kdprof/EnableAction.hpp deleted file mode 100644 index 39447f4..0000000 --- a/kdprof/EnableAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// EnableAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_EnableAction_hpp -#define kdprof_EnableAction_hpp - -class EnableAction : public Action { - public: - EnableAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/EventPrinting.cpp b/kdprof/EventPrinting.cpp deleted file mode 100644 index c2f5f61..0000000 --- a/kdprof/EventPrinting.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// EventPrinting.cpp -// kdprof -// -// Created by James McIlree on 6/6/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void print_event_header(const Globals& globals, bool is_64_bit) { - - // Header is... - // - // [Index] Time Type Code arg1 arg2 arg3 arg4 thread cpu# command/IOP-name pid - // 8 16 4 34 8/16 8/16 8/16 8/16 10 4 16 6 - - - if (globals.should_print_event_index()) - dprintf(globals.output_fd(), "%8s ", "Event#"); - - // The character counting for "Time(µS)" is OBO, it treats the µ as two characters. - // This means the %16s misaligns. We force it by making the input string 16 printable chars long, - // which overflows the %16s to the correct actual output length. - const char* time = globals.should_print_mach_absolute_timestamps() ? "Time(mach-abs)" : " Time(µS)"; - - if (is_64_bit) - dprintf(globals.output_fd(), "%16s %4s %-34s %-16s %-16s %-16s %-16s %10s %4s %-16s %-6s\n", time, "Type", "Code", "arg1", "arg2", "arg3", "arg4", "thread", "cpu#", "command", "pid"); - else - dprintf(globals.output_fd(), "%16s %4s %-34s %-8s %-8s %-8s %-8s %10s %4s %-16s %-6s\n", time, "Type", "Code", "arg1", "arg2", "arg3", "arg4", "thread", "cpu#", "command", "pid"); -} diff --git a/kdprof/EventPrinting.hpp b/kdprof/EventPrinting.hpp deleted file mode 100644 index 5ad238d..0000000 --- a/kdprof/EventPrinting.hpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// EventPrinting.hpp -// kdprof -// -// Created by James McIlree on 4/20/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_ParallelPrinting_hpp -#define kdprof_ParallelPrinting_hpp - -void print_event_header(const Globals& globals, bool is_64_bit); - -template -char* print_event(char* buf, char* buf_end, const Globals& globals, const Machine& machine, const KDEvent& event, uintptr_t event_index) -{ - // Header is... - // - // [Index] Time Type Code arg1 arg2 arg3 arg4 thread cpu# command/IOP-name pid - // 8 16 4 34 8/16 8/16 8/16 8/16 10 4 16 6 - // - // For now, each column is folding up the "after" spacing in a single printf, IOW - // - // buf += snprintf(buf, buf_end - buf, "%8s ", "COL"); /* + 2 spaces */ - // - // Not: - // - // buf += snprintf(buf, buf_end - buf, "%8s", "COL"); - // buf += snprintf(buf, buf_end - buf, " "); /* 2 spaces */ - - ASSERT(event.cpu() > -1 && event.cpu() < machine.cpus().size(), "cpu_id out of range"); - const MachineCPU& cpu = machine.cpus()[event.cpu()]; - - // - // Okay, here is how snprintf works. - // - // char buf[2]; - // - // snprintf(buf, 0, "a"); // Returns 1, buf is unchanged. - // snprintf(buf, 1, "a"); // Returns 1, buf = \0 - // snprintf(buf, 2, "a"); // Returns 1, buf = 'a', \0 - - // - // If we cannot print successfully, we return the orignal pointer. - // - char* orig_buf = buf; - - // - // [Index] - // - if (globals.should_print_event_index()) { - buf += snprintf(buf, buf_end - buf, "%8llu ", (uint64_t)event_index); - } - - if (buf >= buf_end) - return orig_buf; - - // - // Time - // - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - buf += snprintf(buf, buf_end - buf, "%16llX ", (event.timestamp() - globals.beginning_of_time()).value()); - else - buf += snprintf(buf, buf_end - buf, "%16llu ", (event.timestamp() - globals.beginning_of_time()).value()); - } else { - NanoTime ntime = (event.timestamp() - globals.beginning_of_time()).nano_time(globals.timebase()); - buf += snprintf(buf, buf_end - buf, "%16.2f ", (double)ntime.value() / 1000.0); - } - - if (buf >= buf_end) - return orig_buf; - - // - // Type Code - // - const char* type = event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---"); - auto trace_code_it = globals.trace_codes().find(event.dbg_cooked()); - if (cpu.is_iop() || !globals.should_print_symbolic_event_codes() || trace_code_it == globals.trace_codes().end()) { - buf += snprintf(buf, buf_end - buf, "%4s %-34x ", type, event.dbg_cooked()); - } else { - buf += snprintf(buf, buf_end - buf, "%4s %-34s ", type, trace_code_it->second.c_str()); - } - - if (buf >= buf_end) - return orig_buf; - - // - // arg1 - // - if (event.dbg_class() == DBG_IOKIT && event.dbg_subclass() == DBG_IOPOWER) { - std::string kext_name = event.arg1_as_string(); - std::reverse(kext_name.begin(), kext_name.end()); - - if (SIZE::is_64_bit) - buf += snprintf(buf, buf_end - buf, "%-16s ", kext_name.c_str()); - else - buf += snprintf(buf, buf_end - buf, "%-8s ", kext_name.c_str()); - } else { - if (SIZE::is_64_bit) - buf += snprintf(buf, buf_end - buf, "%-16llX ", (uint64_t)event.arg1()); - else - buf += snprintf(buf, buf_end - buf, "%-8x ", (uint32_t)event.arg1()); - } - - if (buf >= buf_end) - return orig_buf; - - // - // Profiling showed that the repeated snprintf calls were hot, rolling them up is ~2.5% per on a HUGE file. - // - // arg2 arg3 arg4 thread cpu - // - if (SIZE::is_64_bit) - buf += snprintf(buf, buf_end - buf, "%-16llX %-16llX %-16llX %10llX %4u ", (uint64_t)event.arg2(), (uint64_t)event.arg3(), (uint64_t)event.arg4(), (uint64_t)event.tid(), event.cpu()); - else - buf += snprintf(buf, buf_end - buf, "%-8x %-8x %-8x %10llX %4u ", (uint32_t)event.arg2(), (uint32_t)event.arg3(), (uint32_t)event.arg4(), (uint64_t)event.tid(), event.cpu()); - - if (buf >= buf_end) - return orig_buf; - - // - // command & pid (handled together due to IOP not printing a pid - // - if (cpu.is_iop()) { - // We print the IOP name instead of a command - buf += snprintf(buf, buf_end - buf, "%-16s\n", cpu.name()); - } else { - if (const MachineThread* thread = machine.thread(event.tid(), event.timestamp())) { - buf += snprintf(buf, buf_end - buf, "%-16s %-6d\n", thread->process().name(), thread->process().pid()); - } else { - buf += snprintf(buf, buf_end - buf, "%-16s %-6s\n", "?????", "???"); - } - } - - // Still need to check this, its an error if we overflow on the last print! - if (buf >= buf_end) - return orig_buf; - - return buf; -} - -template -char* print_event_range_to_buffer(const Globals& globals, const Machine& machine, TRange range, MemoryBuffer& buffer ) { - char* cursor = buffer.data(); - char* cursor_end = cursor + buffer.capacity(); - - if (const KDEvent* events = machine.events()) { - ASSERT(TRange(0, machine.event_count()).contains(range), "Sanity"); - for (uintptr_t index = range.location(); index < range.max(); ++index) { - char* temp = print_event(cursor, cursor_end, globals, machine, events[index], index); - if (temp != cursor) - cursor = temp; - else { - // Changing the capacity will invalidate the cursor - ptrdiff_t offset = cursor - buffer.data(); - buffer.set_capacity(buffer.capacity()*2); - cursor = buffer.data() + offset; - cursor_end = buffer.data() + buffer.capacity(); - } - } - } - - return cursor; -} - -class PrintWorkUnit { - protected: - MemoryBuffer _buffer; - TRange _event_range; - char* _buffer_end; - - // We do not want work units copied. - PrintWorkUnit(const PrintWorkUnit& that) = delete; - PrintWorkUnit& operator=(const PrintWorkUnit& other) = delete; - - public: - PrintWorkUnit(MemoryBuffer&& buffer, TRange event_range, char* buffer_end) : - _buffer(std::move(buffer)), - _event_range(event_range), - _buffer_end(buffer_end) - { - ASSERT(_buffer.capacity(), "Sanity"); - ASSERT(_buffer.data(), "Sanity"); - ASSERT(!_buffer_end || _buffer_end > _buffer.data(), "Sanity"); - ASSERT(!_buffer_end || (_buffer_end < _buffer.data() + _buffer.capacity()), "Sanity"); - } - - MemoryBuffer& buffer() { return _buffer; } - - TRange event_range() { return _event_range; } - void set_event_range(TRange range) { _event_range = range; } - - char* buffer_end() const { return _buffer_end; } - void set_buffer_end(char* buffer_end) { _buffer_end = buffer_end; } -}; - -template -class PrintProducer { - protected: - const Globals& _globals; - const Machine& _machine; - uintptr_t _start_index; - uintptr_t _end_index; - uintptr_t _chunk_size; - - public: - PrintProducer(const Globals& globals, const Machine& machine, uintptr_t chunk_size) : - _globals(globals), - _machine(machine), - _chunk_size(chunk_size) - { - _start_index = 0; - _end_index = machine.event_count(); - - if (globals.is_summary_start_set() || globals.is_summary_stop_set()) { - AbsInterval machine_timespan = machine.timespan(); - - KDEvent start_event(globals.summary_start(machine_timespan)); - auto it = std::lower_bound(machine.events(), machine.events() + _end_index, start_event); - ASSERT(&*it >= machine.events(), "Returned start index lower than start"); - _start_index = std::distance(machine.events(), it); - - KDEvent end_event(globals.summary_stop(machine_timespan)); - it = std::lower_bound(machine.events(), machine.events() + _end_index, end_event); - ASSERT(&*it <= machine.events() + _end_index, "Returned end index greater than end"); - _end_index = std::distance(machine.events(), it); - - ASSERT(_start_index <= _end_index, "start index is > end index"); - } - } - - bool produce(PrintWorkUnit& work_unit) { - // Claim a chunk of work to do - uintptr_t orig_start_index, new_start_index; - do { - orig_start_index = _start_index; - new_start_index = orig_start_index + std::min(_chunk_size, _end_index - orig_start_index); - } while (orig_start_index < _end_index && !OSAtomicCompareAndSwapPtrBarrier((void*)orig_start_index, (void *)new_start_index, (void * volatile *)&_start_index)); - - // Did we claim work? - if (orig_start_index < _end_index) { - TRange event_range(orig_start_index, new_start_index - orig_start_index); - char* end = print_event_range_to_buffer(_globals, _machine, event_range, work_unit.buffer()); - - work_unit.set_event_range(event_range); - work_unit.set_buffer_end(end); - return true; - } - - return false; - } - - uintptr_t start_index() const { return _start_index; } -}; - -template -class PrintConsumer { - protected: - const Globals& _globals; - uintptr_t _write_index; - std::mutex _write_mutex; - std::condition_variable _write_condition; - - public: - PrintConsumer(const Globals& globals, const Machine& machine, uintptr_t start_index) : - _globals(globals), - _write_index(start_index) - { - } - - void consume(PrintWorkUnit& work_unit) { - std::unique_lock guard(_write_mutex); - _write_condition.wait(guard, [&](){ return work_unit.event_range().location() == this->_write_index; }); - - ASSERT(work_unit.event_range().location() == _write_index, "Sanity"); - - char* data = work_unit.buffer().data(); - size_t bytes = work_unit.buffer_end() - data; - write(_globals.output_fd(), work_unit.buffer().data(), bytes); - _write_index = work_unit.event_range().max(); - - _write_condition.notify_all(); - } -}; - -template -uintptr_t print_machine_events(const Globals& globals, const Machine& machine) { - print_event_header(globals, SIZE::is_64_bit); - - if (const KDEvent* events = machine.events()) { - if (uintptr_t event_count = machine.event_count()) { - - // - // We want to chunk this up into reasonably sized pieces of work. - // Because each piece of work can potentially accumulate a large - // amount of memory, we need to limit the amount of work "in-flight". - // - uint32_t active_cpus = Kernel::active_cpu_count(); - - uintptr_t chunk_size = 2000; - - PrintProducer producer(globals, machine, chunk_size); - PrintConsumer consumer(globals, machine, producer.start_index()); - - std::vector threads; - for (uint32_t i=0; i(160 * chunk_size), TRange(0, 0), (char*)NULL); - while (producer.produce(work_unit)) { - consumer.consume(work_unit); - } - })); - } - - for(auto& thread : threads){ - thread.join(); - } - - uint32_t totalProcesses = 0; - uint32_t totalThreads = 0; - - for (auto process : machine.processes()) { - if (!process->is_created_by_previous_machine_state()) { - totalProcesses++; - } - } - - for (auto thread : machine.threads()) { - if (!thread->is_created_by_previous_machine_state()) { - totalThreads++; - } - } - - dprintf(globals.output_fd(), "Total Events: %llu\n", (uint64_t)event_count); - dprintf(globals.output_fd(), "Total Processes: %u\n", totalProcesses); - dprintf(globals.output_fd(), "Total Threads: %u\n", totalThreads); - - return event_count; - } - } - - return 0; -} - -#endif diff --git a/kdprof/Globals.cpp b/kdprof/Globals.cpp deleted file mode 100644 index 6f8132d..0000000 --- a/kdprof/Globals.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// MachineGlobals.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -Globals::Globals() : - _cpu_count(0), - _iop_count(0), - _kernel_size(Kernel::is_64_bit() ? KernelSize::k64 : KernelSize::k32), - _is_cpu_count_set(false), - _is_iop_count_set(false), - _is_kernel_size_set(false), - _is_summary_start_set(false), - _is_summary_stop_set(false), - _is_summary_step_set(false), - _is_should_print_summary_set(false), - _is_timebase_set(false), - _should_read_default_trace_codes(true), - _should_print_mach_absolute_timestamps(false), - _should_print_event_index(false), - _should_print_symbolic_event_codes(true), - _is_verbose(false), - _should_presort_events(false), - _should_print_cpu_summaries(false), - _should_print_process_summaries(true), - _should_print_thread_summaries(false), - _should_print_events(false), - _should_print_summary(false), - _should_zero_base_timestamps(true), - _should_print_process_start_stop_timestamps(false), - _should_print_csv_summary(false), - _sort_key(kSortKey::CPU) -{ - // Default to the current machine's values - mach_timebase_info(&_timebase_info); - - for (auto& entry : KDBG::cpumap()) { - if (entry.is_iop()) - _iop_count++; - else - _cpu_count++; - } - - // If we are unable to get a cpumap, - // fallback on the current # of cpus - if (_cpu_count == 0) { - _cpu_count = Kernel::active_cpu_count(); - _iop_count = 0; - } -} - -AbsTime Globals::parse_time(const char* arg) const { - - char* units; - uint64_t value = strtoull(arg, &units, 0); - - // Unspecified units are treated as seconds - if (*units == 0 || strcmp(units, "s") == 0) { - return NanoTime(value * NANOSECONDS_PER_SECOND).abs_time(_timebase_info); - } - - if (strcmp(units, "ms") == 0) - return NanoTime(value * NANOSECONDS_PER_MILLISECOND).abs_time(_timebase_info); - - if (strcmp(units, "us") == 0) - return NanoTime(value * NANOSECONDS_PER_MICROSECOND).abs_time(_timebase_info); - - if (strcmp(units, "ns") == 0) - return NanoTime(value).abs_time(_timebase_info); - - if (strcmp(units, "mabs") == 0) { - return AbsTime(value); - } - - usage("Unable to parse units on time value"); -} - -AbsTime Globals::summary_start(AbsInterval timespan) const { - AbsTime start(timespan.location()); - - if (is_summary_start_set()) { - AbsTime summary_start = parse_time(_summary_start.c_str()); - - bool absolute_start_stop = (_beginning_of_time == 0); - if (absolute_start_stop) - start = summary_start; - else - start += summary_start; - } - - return start; -} - -AbsTime Globals::summary_stop(AbsInterval timespan) const { - - if (is_summary_stop_set()) { - AbsTime summary_stop = parse_time(_summary_stop.c_str()); - - bool absolute_start_stop = (_beginning_of_time == 0); - if (absolute_start_stop) - return summary_stop; - else - return timespan.location() + summary_stop; - } - - return timespan.max(); -} - -AbsTime Globals::summary_step(AbsInterval timespan) const { - if (is_summary_step_set()) { - return parse_time(_summary_step.c_str()); - } - - return timespan.length(); -} diff --git a/kdprof/Globals.hpp b/kdprof/Globals.hpp deleted file mode 100644 index 281edeb..0000000 --- a/kdprof/Globals.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// Globals.hpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_Globals_hpp -#define kdprof_Globals_hpp - -// -// These are "global" values that control parsing and printing behavior. -// - -enum class kSortKey : std::uint32_t { - CPU=0, - VMFault, - IO_Ops, - IO_Size, - IO_Wait, - ID -}; - -class Globals { - protected: - // Default/unknown parsing values - uint32_t _cpu_count; - uint32_t _iop_count; - KernelSize _kernel_size; - std::string _summary_start; - std::string _summary_stop; - std::string _summary_step; - - bool _is_cpu_count_set; - bool _is_iop_count_set; - bool _is_kernel_size_set; - bool _is_summary_start_set; - bool _is_summary_stop_set; - bool _is_summary_step_set; - bool _is_should_print_summary_set; - bool _is_timebase_set; - - // Output, printing related. - AbsTime _beginning_of_time; - mach_timebase_info_data_t _timebase_info; - FileDescriptor _output_fd; - bool _should_read_default_trace_codes; - std::vector _additional_trace_code_paths; - std::unordered_map _trace_codes; - bool _should_print_mach_absolute_timestamps; - bool _should_print_event_index; - bool _should_print_symbolic_event_codes; - bool _is_verbose; - bool _should_presort_events; - bool _should_print_cpu_summaries; - bool _should_print_process_summaries; - bool _should_print_thread_summaries; - bool _should_print_events; - bool _should_print_summary; - bool _should_zero_base_timestamps; - bool _should_print_process_start_stop_timestamps; - bool _should_print_csv_summary; - kSortKey _sort_key; - - AbsTime parse_time(const char* arg) const; - - public: - Globals(); - - uint32_t cpu_count() const { return _cpu_count; } - void set_cpu_count(uint32_t num) { _cpu_count = num; _is_cpu_count_set = true; } - bool is_cpu_count_set() const { return _is_cpu_count_set; } - - uint32_t iop_count() const { return _iop_count; } - void set_iop_count(uint32_t num) { _iop_count = num; _is_iop_count_set = true; } - bool is_iop_count_set() const { return _is_iop_count_set; } - - KernelSize kernel_size() const { return _kernel_size; } - void set_kernel_size(KernelSize size) { _kernel_size = size; _is_kernel_size_set = true; } - bool is_kernel_size_set() const { return _is_kernel_size_set; } - - AbsTime beginning_of_time() const { return _beginning_of_time; } - void set_beginning_of_time(AbsTime t) { _beginning_of_time = t; } - - mach_timebase_info_data_t timebase() const { return _timebase_info; } - void set_timebase(mach_timebase_info_data_t timebase, bool is_user_set) { _timebase_info = timebase; if (is_user_set) _is_timebase_set = true; } - bool is_timebase_set() const { return _is_timebase_set; } - - int output_fd() const { return _output_fd.is_open() ? (int)_output_fd : STDOUT_FILENO; } - - // Okay, this method caused enough pain to make the final resolution worth a comment. - // - // http://thbecker.net/articles/rvalue_references/section_05.html - // - // Things that are declared as rvalue reference can be lvalues or rvalues. - // The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue. - // - // In this case, you cannot call set_output_fd with an lvalue, but fd is STILL an lvalue. - // We must still explicitly use std::move on fd! - void set_output_fd(FileDescriptor&& fd) { _output_fd = std::move(fd); } - - void set_should_read_default_trace_codes(bool value) { _should_read_default_trace_codes = value; } - void append_trace_codes_at_path(std::string path) { _additional_trace_code_paths.push_back(path); } - void resolve_trace_codes(void) { _trace_codes = ::resolve_trace_codes(_should_read_default_trace_codes, _is_verbose ? 1 : -1, _additional_trace_code_paths); } - - const std::unordered_map& trace_codes() const { return _trace_codes; } - void set_trace_codes(std::unordered_map&& codes) { _trace_codes = codes; } - - bool should_print_mach_absolute_timestamps() const { return _should_print_mach_absolute_timestamps; } - void set_should_print_mach_absolute_timestamps(bool value) { _should_print_mach_absolute_timestamps = value; } - - bool should_print_event_index() const { return _should_print_event_index; } - void set_should_print_event_index(bool value) { _should_print_event_index = value; } - - bool should_print_symbolic_event_codes() const { return _should_print_symbolic_event_codes; } - void set_should_print_symbolic_event_codes(bool value) { _should_print_symbolic_event_codes = value; } - - bool is_verbose() const { return _is_verbose; } - void set_is_verbose(bool value) { _is_verbose = value; } - - bool should_presort_events() const { return _should_presort_events; } - void set_should_presort_events(bool value) { _should_presort_events = value; } - - bool should_print_cpu_summaries() const { return _should_print_cpu_summaries; } - void set_should_print_cpu_summaries(bool value) { _should_print_cpu_summaries = value; } - - bool should_print_process_summaries() const { return _should_print_process_summaries; } - void set_should_print_process_summaries(bool value) { _should_print_process_summaries = value; } - - bool should_print_thread_summaries() const { return _should_print_thread_summaries; } - void set_should_print_thread_summaries(bool value) { _should_print_thread_summaries = value; } - - bool should_print_events() const { return _should_print_events; } - void set_should_print_events(bool value) { _should_print_events = value; } - - bool should_print_summary() const { return _should_print_summary; } - void set_should_print_summary(bool value) { _should_print_summary = value; _is_should_print_summary_set = true; } - bool is_should_print_summary_set() const { return _is_should_print_summary_set; } - - bool should_zero_base_timestamps() const { return _should_zero_base_timestamps; } - void set_should_zero_base_timestamps(bool value) { _should_zero_base_timestamps = value; } - - bool should_print_process_start_stop_timestamps() const { return _should_print_process_start_stop_timestamps; } - void set_should_print_process_start_stop_timestamps(bool value) { _should_print_process_start_stop_timestamps = value; } - - bool should_print_csv_summary() const { return _should_print_csv_summary; } - void set_should_print_csv_summary(bool value) { _should_print_csv_summary = value; } - - kSortKey sort_key() const { return _sort_key; } - void set_sort_key(kSortKey key) { _sort_key = key; } - - // - // The summary {start/stop/step} functions translate the string on the fly, - // using the currently set timebase. They need to be fed a timespan that - // corresponds to the Machine's timespan, because the default values - // and offsets depend on that. - // - // This solve the issue of the user saying --start 1234mabs at the command line - // and getting an offset of 1234 nanoseconds on a desktop when they are looking - // at a device file. - // - AbsTime summary_start(AbsInterval timespan) const; - void set_summary_start(const char* value) { _summary_start = value; _is_summary_start_set = true; } - bool is_summary_start_set() const { return _is_summary_start_set; } - - AbsTime summary_stop(AbsInterval timespan) const; - void set_summary_stop(const char* value) { _summary_stop = value; _is_summary_stop_set = true; } - bool is_summary_stop_set() const { return _is_summary_stop_set; } - - AbsTime summary_step(AbsInterval timespan) const; - void set_summary_step(const char* value) { _summary_step = value; _is_summary_step_set = true; } - bool is_summary_step_set() const { return _is_summary_step_set; } -}; - -#endif diff --git a/kdprof/InitializeAction.cpp b/kdprof/InitializeAction.cpp deleted file mode 100644 index e4943e5..0000000 --- a/kdprof/InitializeAction.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// InitializeAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void InitializeAction::execute(Globals& globals) { - if (_buffers) { - if (!KDBG::set_buffer_capacity(_buffers)) { - usage("Attempt to set buffer count failed"); - } - } - - if (!KDBG::initialize_buffers()) { - usage("Attempt to initialize buffers failed\n"); - } -} diff --git a/kdprof/InitializeAction.hpp b/kdprof/InitializeAction.hpp deleted file mode 100644 index ac594de..0000000 --- a/kdprof/InitializeAction.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// InitializeAction.hpp -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_InitializeAction_hpp -#define kdprof_InitializeAction_hpp - -class InitializeAction : public Action { - protected: - uint32_t _buffers; - - public: - InitializeAction(uint32_t buffers) : _buffers(buffers) { } - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/NoWrapAction.cpp b/kdprof/NoWrapAction.cpp deleted file mode 100644 index c4fe5cc..0000000 --- a/kdprof/NoWrapAction.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// NoWrapAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void NoWrapAction::execute(Globals& globals) { - KDBG::set_nowrap(true); -} diff --git a/kdprof/NoWrapAction.hpp b/kdprof/NoWrapAction.hpp deleted file mode 100644 index 947e6a4..0000000 --- a/kdprof/NoWrapAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// NoWrapAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_NoWrapAction_hpp -#define kdprof_NoWrapAction_hpp - -class NoWrapAction : public Action { - public: - NoWrapAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/PrintStateAction.cpp b/kdprof/PrintStateAction.cpp deleted file mode 100644 index 66e27cb..0000000 --- a/kdprof/PrintStateAction.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// PrintStateAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void PrintStateAction::execute(Globals& globals) { - printf("\n"); - KDBG::state().print(); - printf("\n"); -} diff --git a/kdprof/PrintStateAction.hpp b/kdprof/PrintStateAction.hpp deleted file mode 100644 index daaa357..0000000 --- a/kdprof/PrintStateAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// PrintStateAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_PrintStateAction_hpp -#define kdprof_PrintStateAction_hpp - -class PrintStateAction : public Action { - public: - PrintStateAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/RemoveAction.cpp b/kdprof/RemoveAction.cpp deleted file mode 100644 index a84f2fc..0000000 --- a/kdprof/RemoveAction.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// RemoveAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void RemoveAction::execute(Globals& globals) { - KDBG::reset(); -} diff --git a/kdprof/RemoveAction.hpp b/kdprof/RemoveAction.hpp deleted file mode 100644 index 387352b..0000000 --- a/kdprof/RemoveAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// RemoveAction.hpp -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_RemoveAction_hpp -#define kdprof_RemoveAction_hpp - -class RemoveAction : public Action { - public: - RemoveAction() {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/SaveTraceAction.cpp b/kdprof/SaveTraceAction.cpp deleted file mode 100644 index ce95b37..0000000 --- a/kdprof/SaveTraceAction.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// SaveTraceAction.cpp -// kdprof -// -// Created by James McIlree on 5/2/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -template -static void execute_arch_specific(Globals& globals, KDState& state, FileDescriptor& save_fd) { - // Collect all data first, printing takes time... - auto threadmap = KDBG::threadmap(state); - auto cpumap = KDBG::cpumap(); - - // These are future proofing, trace doesn't actually need page alignment - // here, just file block size alignment. When page sizes go to 16k, we - // don't want 16k of padding. - -#define FILE_BLOCK_SIZE 4096 -#define FILE_BLOCK_SIZE_MASK 4095 - - /* - * To write a RAW_VERSION1+ file, we must embed a cpumap in the "padding" - * used to file block align the events folloing the threadmap. If the - * threadmap happens to not require enough padding, we artificially - * increase its footprint until it needs enough padding. - */ - - uint32_t pad_size = FILE_BLOCK_SIZE - ((sizeof(TraceDataHeader) + (threadmap.size() * sizeof(KDThreadMapEntry))) & FILE_BLOCK_SIZE_MASK); - uint32_t cpumap_size = sizeof(kd_cpumap_header) + (uint32_t)cpumap.size() * sizeof(KDCPUMapEntry); - uint32_t extra_thread_count = 0; - - if (cpumap_size > pad_size) { - /* Force an overflow onto the next page, we get a full page of padding */ - extra_thread_count = (pad_size / sizeof(KDCPUMapEntry)) + 1; - } - - // Write the header - TraceDataHeader header(RAW_VERSION1, (uint32_t)threadmap.size(), time(NULL), 0); - write(save_fd, &header, sizeof(TraceDataHeader)); - - // Write the threadmaps - write(save_fd, threadmap.data(), threadmap.size() * sizeof(KDThreadMapEntry)); - - if (extra_thread_count) { - pad_size = extra_thread_count * sizeof(KDThreadMapEntry); - auto pad_buf = (uint8_t *)calloc(pad_size, 1); - write(save_fd, pad_buf, pad_size); - free(pad_buf); - } - - // Write the cpumaps & any remaining padding - size_t bytes_written = sizeof(TraceDataHeader) + (threadmap.size() + extra_thread_count) * sizeof(KDThreadMapEntry); - pad_size = FILE_BLOCK_SIZE - (bytes_written & FILE_BLOCK_SIZE_MASK); - - ASSERT(pad_size >= cpumap.size() * sizeof(KDCPUMapEntry), "Not enough padding bytes!"); - if (pad_size) { - auto cpumap_header = (kd_cpumap_header*)calloc(pad_size, 1); - cpumap_header->version_no = RAW_VERSION1; - cpumap_header->cpu_count = (uint32_t)cpumap.size(); - auto cpus = (kd_cpumap*)&cpumap_header[1]; - memcpy(cpus, cpumap.data(), cpumap.size() * sizeof(KDCPUMapEntry)); - write(save_fd, cpumap_header, pad_size); - } - - // Write the events - // - // Because this may be used to capture boot traces which consume very - // large amounts of memory, we will likely not be able to collect - // the entire buffer space in a single shot. Read it in small chunks. - // - auto twenty_mb = 20 * 1024 * 1024; - auto num_events_in_twenty_mb = twenty_mb / sizeof(KDEvent); - MemoryBuffer> events(num_events_in_twenty_mb); - - // We read until we don't get back a full buffer, hoping thats enough. - while (1) { - int count = KDBG::read(events.data(), events.capacity_in_bytes()); - - if (count != -1) - write(save_fd, events.data(), count * sizeof(KDEvent)); - - if (count < num_events_in_twenty_mb) { - break; - } - } - - // close up - save_fd.close(); -} - -void SaveTraceAction::execute(Globals& globals) { - KDState state = KDBG::state(); - if (state.is_lp64()) { - execute_arch_specific(globals, state, _save_fd); - } else { - execute_arch_specific(globals, state, _save_fd); - } -} diff --git a/kdprof/SaveTraceAction.hpp b/kdprof/SaveTraceAction.hpp deleted file mode 100644 index 54bffb8..0000000 --- a/kdprof/SaveTraceAction.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// SaveTraceAction.hpp -// kdprof -// -// Created by James McIlree on 5/2/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __kdprof__SaveTraceAction__ -#define __kdprof__SaveTraceAction__ - -class SaveTraceAction : public Action { - FileDescriptor _save_fd; - - public: - SaveTraceAction(FileDescriptor&& fd) : - _save_fd(std::move(fd)) - { - ASSERT(_save_fd.is_open(), "Sanity"); - } - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/SleepAction.cpp b/kdprof/SleepAction.cpp deleted file mode 100644 index 1c00a76..0000000 --- a/kdprof/SleepAction.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// SleepAction.cpp -// kdprof -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -void SleepAction::execute(Globals& globals) { - uint64_t nanos = _time.value(); - struct timespec ts; - ts.tv_sec = decltype(ts.tv_sec)(nanos / NANOSECONDS_PER_SECOND); - ts.tv_nsec = decltype(ts.tv_sec)(nanos - ts.tv_sec * NANOSECONDS_PER_SECOND); - nanosleep(&ts, NULL); -} diff --git a/kdprof/SleepAction.hpp b/kdprof/SleepAction.hpp deleted file mode 100644 index 8dd9bbf..0000000 --- a/kdprof/SleepAction.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// SleepAction.hpp -// kdprof -// -// Created by James McIlree on 4/16/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_SleepAction_hpp -#define kdprof_SleepAction_hpp - -class SleepAction : public Action { - NanoTime _time; - - public: - SleepAction(NanoTime t) : _time(t) {} - - virtual void execute(Globals& globals); -}; - -#endif diff --git a/kdprof/SummaryPrinting.cpp b/kdprof/SummaryPrinting.cpp deleted file mode 100644 index 96b68b4..0000000 --- a/kdprof/SummaryPrinting.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// -// SummaryPrinting.cpp -// kdprof -// -// Created by James McIlree on 4/19/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -constexpr const char* const SummaryLineData::indent_string[]; - -void print_summary_header(const Globals& globals) { - // Header is... - // Avg Actual Wanted Actual Wanted Jetsam - // All CPU Thr Avg Actual Wanted Concurrency Processes To Run Threads To Run VMFault VMFault IO Wait # IO IO Bytes Jetsam Proc - // [Time(mS)] Name Run% Idle% Intr% Idle% #Intr #CSW On CPU/µS CPU/mS CPU/mS (# CPU) Ran Processes Ran Threads Count Time (mS) Time (mS) Ops Completed Time (mS) Count - // 123456789abcdef0 123456789012345678901234567890 1234567 1234567 1234567 1234567 1234567 12345678 123456789 123456789abc 123456789abc 123456789ab 123456789 123456789 1234567 1234567 1234567 123456789abc 123456789abc 1234567 1234567890 123456789 123456 - // 1119100000.00 76.58 16.53 6.89 0.00 230 112 10000.00 100000.00 100000.00 1.55 2 3 12 13 2280 230.48 1998.22 3318 123.40 MB 0.00 - - const char* time1 = ""; - const char* time2 = ""; - const char* time3 = ""; - char time_buffer1[32]; - char time_buffer2[32]; - char time_buffer3[32]; - - // If we're printing the entire data set, don't print a timestamp. - if (globals.is_summary_start_set() || globals.is_summary_stop_set() || globals.is_summary_step_set()) { - sprintf(time_buffer1, "%16s ", ""); - sprintf(time_buffer2, "%16s ", ""); - sprintf(time_buffer3, "%-16s ", globals.should_print_mach_absolute_timestamps() ? "Time(mach-abs)" : "Time(mS)"); - - time1 = time_buffer1; - time2 = time_buffer2; - time3 = time_buffer3; - } - - dprintf(globals.output_fd(), "%s%-30s %7s %7s %7s %7s %7s %8s %9s %12s %12s %11s %9s %9s %7s %7s %7s %12s %12s %7s %10s %9s %6s\n", time1, "", "", "", "", "", "", "", "", "", "", "Avg", "Actual", "Wanted", "Actual", "Wanted", "", "", "", "", "", "", "Jetsam"); - dprintf(globals.output_fd(), "%s%-30s %7s %7s %7s %7s %7s %8s %9s %12s %12s %11s %9s %9s %7s %7s %7s %12s %12s %7s %10s %9s %6s\n", time2, "", "", "", "", "All-CPU", "", "", "Thr Avg", "Actual", "Wanted", "Concurrency", "Processes", "To Run", "Threads", "To Run", "VMFault", "VMFault", "IO Wait", "# IO", "IO Bytes", "Jetsam", "Proc"); - dprintf(globals.output_fd(), "%s%-30s %7s %7s %7s %7s %7s %8s %9s %12s %12s %11s %9s %9s %7s %7s %7s %12s %12s %7s %10s %9s %6s\n", time3, "Name", "Run%", "Idle%", "Intr%", "Idle%", "#Intr", "#CSW", "On CPU/µS", "CPU/mS", "CPU/mS", "(# CPU)", "Ran", "Processes", "Ran", "Threads", "Count", "Time (mS)", "Time (mS)", "Ops", "Completed", "Time (mS)", "Count"); -} diff --git a/kdprof/SummaryPrinting.hpp b/kdprof/SummaryPrinting.hpp deleted file mode 100644 index abb5e51..0000000 --- a/kdprof/SummaryPrinting.hpp +++ /dev/null @@ -1,1504 +0,0 @@ -// -// SummaryPrinting.hpp -// kdprof -// -// Created by James McIlree on 4/19/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_Printing_hpp -#define kdprof_Printing_hpp - -void print_summary_header(const Globals& globals); - -struct SummaryLineData { - protected: - static constexpr const char* const indent_string[] = { "", " ", " ", " " }; - static const uint32_t MAX_INDENT_LEVEL = 3; // Need to know this for time indenting to work correctly - - uint32_t _indent_level; - const char* _name; - - public: - - enum class SummaryType { - Unknown, - CPU, - Process, - Thread - }; - - SummaryLineData(const char* name, uint32_t indent_level) : - _indent_level(indent_level), - _name(name), - should_print_timestamp(true), - num_intr_events(0), - context_switches(0), - actual_process_count(0), - wanted_process_count(0), - actual_thread_count(0), - wanted_thread_count(0), - num_vm_fault_events(0), - num_io_events(0), - io_bytes_completed(0), - num_jetsam_pids(0), - percent_multiplier(100.0), - type(SummaryType::Unknown), - is_colored(false), - begin_color(NULL), - end_color(NULL) - { - ASSERT(_indent_level <= MAX_INDENT_LEVEL, "Sanity"); - ASSERT(_name && strlen(_name) > 0, "Sanity"); - } - - bool should_print_timestamp; - AbsTime total_time; - AbsTime total_run_time; - AbsTime total_idle_time; - AbsTime total_intr_time; - AbsTime total_wanted_run_time; - AbsTime total_wallclock_run_time; - AbsTime total_all_cpus_idle_time; - AbsTime total_vm_fault_time; - AbsTime total_io_time; - AbsTime total_jetsam_time; - uint32_t num_intr_events; - uint32_t context_switches; - uint32_t actual_process_count; - uint32_t wanted_process_count; - uint32_t actual_thread_count; - uint32_t wanted_thread_count; - uint32_t num_vm_fault_events; - uint32_t num_io_events; - uint64_t io_bytes_completed; - uint32_t num_jetsam_pids; - double percent_multiplier; - SummaryType type; - bool is_colored; - const char* begin_color; - const char* end_color; - - const char* name() { return _name; } - const char* outdent() { return indent_string[MAX_INDENT_LEVEL - _indent_level]; } - const char* indent() { return indent_string[_indent_level]; } - - bool is_unknown() { return type == SummaryType::Unknown; } - bool is_cpu() { return type == SummaryType::CPU; } - bool is_process() { return type == SummaryType::Process; } - bool is_thread() { return type == SummaryType::Thread; } -}; - -template -void print_summary_line(const Globals& globals, const Machine& machine, AbsInterval summary_interval, struct SummaryLineData& line_data) -{ - // Header is... - // Avg Actual Wanted Actual Wanted Jetsam - // All CPU Thr Avg Actual Wanted Concurrency Processes To Run Threads To Run VMFault VMFault IO Wait # IO IO Bytes Jetsam Proc - // [Time(mS)] Name Run% Idle% Intr% Idle% #Intr #CSW On CPU/µS CPU/mS CPU/mS (# CPU) Ran Processes Ran Threads Count Time (mS) Time (mS) Ops Completed Time (mS) Count - // 123456789abcdef0 123456789012345678901234567890 1234567 1234567 1234567 1234567 1234567 12345678 123456789 123456789abc 123456789abc 123456789ab 123456789 123456789 1234567 1234567 1234567 123456789abc 123456789abc 1234567 1234567890 123456789 123456 - // 1119100000.00 76.58 16.53 6.89 0.00 230 112 10000.00 100000.00 100000.00 1.55 2 3 12 13 2280 230.48 1998.22 3318 123.40 MB 0.00 - - ASSERT(!line_data.is_unknown(), "Sanity"); - - // - // It turns out that calling dprintf is very expensive; we're going to - // accumulate to a string buffer and then flush once at the end. - // - char line[1024]; - char* cursor = line; - char* line_end = line + sizeof(line); - - // - // Begin line coloring (if any) - // - if (line_data.is_colored) { - ASSERT(line_data.begin_color && line_data.end_color, "Sanity"); - cursor += snprintf(cursor, line_end - cursor, "%s", line_data.begin_color); - - if (cursor > line_end) - cursor = line_end; - } - - if (line_data.should_print_timestamp) { - - // - // Time and Name get a special indent treatment, so they come out - // as heirarchically aligned, while not disturbing the rest of the - // columns. The time value is actually outdented, the name value - // is indented. - // - // The result is that you get something like this: - // - // [Time(mS)] Name Run% - // 123456789abcdef0 123456789012345678901234567890 1234567 - // - // 1000.00 INDENT-LEVEL-0 ##.## - // 1000.00 INDENT-LEVEL-1 ##.## - // 1000.00 INDENT-LEVEL-2 ##.## - // 1000.00 INDENT-LEVEL-3 ##.## - // - - char time_buffer[64]; - - // - // Time - // - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - snprintf(time_buffer, sizeof(time_buffer), "%llX%s", (summary_interval.location() - globals.beginning_of_time()).value(), line_data.outdent()); - else - snprintf(time_buffer, sizeof(time_buffer), "%llu%s", (summary_interval.location() - globals.beginning_of_time()).value(), line_data.outdent()); - } else { - NanoTime ntime = (summary_interval.location() - globals.beginning_of_time()).nano_time(globals.timebase()); - snprintf(time_buffer, sizeof(time_buffer), "%3.2f%s", (double)ntime.value() / 1000000.0, line_data.outdent()); - } - - cursor += snprintf(cursor, line_end - cursor, "%16s ", time_buffer); - - if (cursor > line_end) - cursor = line_end; - } - - // - // Name - // - - { - char name_buffer[64]; - snprintf(name_buffer, sizeof(name_buffer), "%s%s", line_data.indent(), line_data.name()); - - cursor += snprintf(cursor, line_end - cursor, "%-30s ", name_buffer); - if (cursor > line_end) - cursor = line_end; - } - - // - // Run% Idle% Intr% All-CPUs-Idle% #Intr - // - - // Special case for process/thread summary lines, print idle/intr as "-"; - if (line_data.is_process() || line_data.is_thread()) { - double run_percent = 0.0; - - if (line_data.total_time.value() > 0) - run_percent = line_data.total_run_time.double_value() / line_data.total_time.double_value() * line_data.percent_multiplier; - - cursor += snprintf(cursor, line_end - cursor, "%7.2f %7s %7s %7s %7u ", - run_percent, - "-", - "-", - "-", - line_data.num_intr_events); - } else { - ASSERT(line_data.total_time.value() > 0, "Sanity"); - - cursor += snprintf(cursor, line_end - cursor, "%7.2f %7.2f %7.2f %7.2f %7u ", - line_data.total_run_time.double_value() / line_data.total_time.double_value() * line_data.percent_multiplier, - line_data.total_idle_time.double_value() / line_data.total_time.double_value() * line_data.percent_multiplier, - line_data.total_intr_time.double_value() / line_data.total_time.double_value() * line_data.percent_multiplier, - line_data.total_all_cpus_idle_time.double_value() / line_data.total_time.double_value() * line_data.percent_multiplier, - line_data.num_intr_events); - } - - if (cursor > line_end) - cursor = line_end; - - // - // #context-switches avg-on-cpu/µS - // - if (line_data.context_switches > 0) { - double avg_on_cpu_uS = (line_data.total_run_time / AbsTime(line_data.context_switches)).nano_time(globals.timebase()).value() / 1000.0; - cursor += snprintf(cursor, line_end - cursor, "%8u %9.2f ", line_data.context_switches, avg_on_cpu_uS); - } else { - cursor += snprintf(cursor, line_end - cursor, "%8u %9s ", line_data.context_switches, "-"); - } - - if (cursor > line_end) - cursor = line_end; - - // - // Actual CPU/mS, Wanted CPU/mS - // - if (line_data.total_wanted_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%12.2f %12.2f ", - (double)line_data.total_run_time.nano_time(globals.timebase()).value() / 1000000.0, - (double)(line_data.total_run_time + line_data.total_wanted_run_time).nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, "%12.2f %12s ", - (double)line_data.total_run_time.nano_time(globals.timebase()).value() / 1000000.0, - "-"); - } - - if (cursor > line_end) - cursor = line_end; - - // - // Proc Avg Concurrency - // - - if (line_data.total_wallclock_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%11.2f ", (double)line_data.total_run_time.value() / (double)line_data.total_wallclock_run_time.value()); - // cursor += snprintf(cursor, line_end - cursor, "%11.2f ", (double)line_data.total_wallclock_run_time.nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, "%11s ", "-"); - } - - if (cursor > line_end) - cursor = line_end; - - // - // Actual Processes, Wanted Processes - // - if (line_data.is_thread()) { - cursor += snprintf(cursor, line_end - cursor, "%9s %9s ", "-", "-"); - } else { - if (line_data.total_run_time > 0 && line_data.total_wanted_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%9u %9u ", (uint32_t)line_data.actual_process_count, (uint32_t)line_data.wanted_process_count); - } else if (line_data.total_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%9u %9s ", (uint32_t)line_data.actual_process_count, "-"); - } else if (line_data.total_wanted_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%9s %9u ", "-", (uint32_t)line_data.wanted_process_count); - } else { - cursor += snprintf(cursor, line_end - cursor, "%9s %9s ", "-", "-"); - } - } - - if (cursor > line_end) - cursor = line_end; - - // - // Actual Threads, Wanted Threads - // - if (line_data.total_run_time > 0 && line_data.total_wanted_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%7u %7u ", (uint32_t)line_data.actual_thread_count, (uint32_t)line_data.wanted_thread_count); - } else if (line_data.total_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%7u %7s ", (uint32_t)line_data.actual_thread_count, "-"); - } else if (line_data.total_wanted_run_time > 0) { - cursor += snprintf(cursor, line_end - cursor, "%7s %7u ", "-", (uint32_t)line_data.wanted_thread_count); - } else { - cursor += snprintf(cursor, line_end - cursor, "%7s %7s ", "-", "-"); - } - - if (cursor > line_end) - cursor = line_end; - - - // - // #vmfaults, mS blocked in vmfault - // - if (line_data.num_vm_fault_events == 0 && line_data.total_vm_fault_time.value() == 0) { - cursor += snprintf(cursor, line_end - cursor, "%7s %12s ", "-", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%7u %12.2f ", - line_data.num_vm_fault_events, - (double)line_data.total_vm_fault_time.nano_time(globals.timebase()).value() / 1000000.0); - } - - // - // mS blocked on IO activity - // - if (line_data.total_io_time.value() == 0) { - cursor += snprintf(cursor, line_end - cursor, "%12s ", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%12.2f ", - (double)line_data.total_io_time.nano_time(globals.timebase()).value() / 1000000.0); - } - - // - // # IO operations - // - if (line_data.num_io_events == 0) { - cursor += snprintf(cursor, line_end - cursor, "%7s ", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%7u ", line_data.num_io_events); - } - - // - // IO bytes completed - // - if (line_data.io_bytes_completed == 0) { - cursor += snprintf(cursor, line_end - cursor, "%10s ", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%10s ", formated_byte_size(line_data.io_bytes_completed).c_str()); - } - - // - // Jetsam time - // - if (line_data.total_jetsam_time == 0) { - cursor += snprintf(cursor, line_end - cursor, "%9s ", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%9.2f ", - (double)line_data.total_jetsam_time.nano_time(globals.timebase()).value() / 1000000.0); - } - - // - // Jetsam count - // - if (line_data.is_cpu()) { - if (line_data.num_jetsam_pids == 0) { - cursor += snprintf(cursor, line_end - cursor, "%6s", "-"); - } else { - cursor += snprintf(cursor, line_end - cursor, "%6u", line_data.num_jetsam_pids); - } - } else { - cursor += snprintf(cursor, line_end - cursor, "%6s", ""); - } - - // - // End line coloring (if any) - // - if (line_data.is_colored) { - cursor += snprintf(cursor, line_end - cursor, "%s", line_data.end_color); - - if (cursor > line_end) - cursor = line_end; - } - - dprintf(globals.output_fd(), "%s\n", line); -} - -template -void print_cpu_summary_with_name_and_indent(const Globals& globals, const Machine& machine, AbsInterval summary_interval, const CPUSummary& master_summary, const CPUSummary& cpu_summary, const char* name, uint32_t indent) -{ - struct SummaryLineData data(name, indent); - - data.should_print_timestamp = (globals.is_summary_start_set() || globals.is_summary_stop_set() || globals.is_summary_step_set()); - data.total_time = master_summary.total_time(); - data.total_run_time = cpu_summary.total_run_time(); - data.total_idle_time = cpu_summary.total_idle_time(); - data.total_intr_time = cpu_summary.total_intr_time(); - data.total_wanted_run_time = cpu_summary.total_future_run_time(); - data.total_wallclock_run_time = cpu_summary.total_wallclock_run_time(); - data.total_all_cpus_idle_time = cpu_summary.total_all_cpus_idle_time(); - data.total_vm_fault_time = cpu_summary.total_vm_fault_time(); - data.total_io_time = cpu_summary.total_io_time(); - data.total_jetsam_time = cpu_summary.total_jetsam_time(); - data.context_switches = cpu_summary.context_switches(); - data.num_intr_events = cpu_summary.num_intr_events(); - data.num_vm_fault_events = cpu_summary.num_vm_fault_events(); - data.num_io_events = cpu_summary.num_io_events(); - data.num_jetsam_pids = cpu_summary.num_processes_jetsammed(); - data.io_bytes_completed = cpu_summary.io_bytes_completed(); - data.type = SummaryLineData::SummaryType::CPU; - - for (auto& process_summary : cpu_summary.process_summaries()) { - - if (process_summary.total_run_time() > 0) { - data.actual_process_count++; - data.wanted_process_count++; - } else if (process_summary.total_future_run_time() > 0) { - data.wanted_process_count++; - } else { - // ASSERT(cpu_summary.total_vm_fault_time() > 0, "Process in summary no actual or wanted run time, and no vm_fault time"); - } - - for (auto& thread_summary : process_summary.thread_summaries()) { - if (thread_summary.total_run_time() > 0) { - data.actual_thread_count++; - data.wanted_thread_count++; - } else if (thread_summary.total_future_run_time() > 0) { - data.wanted_thread_count++; - } else { - // ASSERT((thread_summary.total_vm_fault_time() > 0) || (thread_summary.total_pgin_time() > 0), "Thread in summary no actual or wanted run time, and no vm_fault or pgin time"); - } - } - } - - data.percent_multiplier *= (double)master_summary.active_cpus(); - - print_summary_line(globals, machine, summary_interval, data); -} - -template -void print_process_summary_with_name_and_indent(const Globals& globals, const Machine& machine, AbsInterval summary_interval, const CPUSummary& master_summary, const ProcessSummary& process_summary, const char* name, uint32_t indent) -{ - struct SummaryLineData data(name, indent); - - data.should_print_timestamp = (globals.is_summary_start_set() || globals.is_summary_stop_set() || globals.is_summary_step_set()); - data.total_run_time = process_summary.total_run_time(); - data.total_wanted_run_time = process_summary.total_future_run_time(); - data.total_wallclock_run_time = process_summary.total_wallclock_run_time(); - data.total_vm_fault_time = process_summary.total_vm_fault_time(); - data.total_io_time = process_summary.total_io_time(); - data.total_jetsam_time = process_summary.total_jetsam_time(); - data.context_switches = process_summary.context_switches(); - data.num_intr_events = process_summary.num_intr_events(); - data.actual_process_count = 1; - data.wanted_process_count = 1; - data.num_vm_fault_events = process_summary.num_vm_fault_events(); - data.num_io_events = process_summary.num_io_events(); - data.num_jetsam_pids = process_summary.num_processes_jetsammed(); - data.io_bytes_completed = process_summary.io_bytes_completed(); - data.total_time = master_summary.total_time(); - // This causes the line printer to put "-" in the idle and intr % columns. - data.type = SummaryLineData::SummaryType::Process; - data.percent_multiplier *= (double)master_summary.active_cpus(); - - // We have to walk the threads to decide actual vs wanted to run - for (auto& thread_summary : process_summary.thread_summaries()) { - if (thread_summary.total_run_time() > 0) { - data.actual_thread_count++; - data.wanted_thread_count++; - } else if (thread_summary.total_future_run_time() > 0) { - data.wanted_thread_count++; - } else { - // ASSERT(thread_summary.total_vm_fault_time() > 0, "Thread in summary no actual or wanted run time, and no vm_fault time"); - } - } - - print_summary_line(globals, machine, summary_interval, data); -} - -template -void print_thread_summary_with_name_and_indent(const Globals& globals, const Machine& machine, AbsInterval summary_interval, const CPUSummary& master_summary, const ThreadSummary& thread_summary, const char* name, uint32_t indent) -{ - struct SummaryLineData data(name, indent); - - /*data.is_colored = true; - data.begin_color = TerminalColorStringFor(kTerminalColor::GREEN, true, false); - data.end_color = TerminalColorResetString();*/ - - data.should_print_timestamp = (globals.is_summary_start_set() || globals.is_summary_stop_set() || globals.is_summary_step_set()); - data.total_run_time = thread_summary.total_run_time(); - data.total_wanted_run_time = thread_summary.total_future_run_time(); - data.total_vm_fault_time = thread_summary.total_vm_fault_time(); - data.total_io_time = thread_summary.total_io_time(); - data.total_jetsam_time = thread_summary.total_jetsam_time(); - data.context_switches = thread_summary.context_switches(); - data.num_intr_events = thread_summary.num_intr_events(); - data.num_vm_fault_events = thread_summary.num_vm_fault_events(); - data.num_io_events = thread_summary.num_io_events(); - data.num_jetsam_pids = 0; - data.io_bytes_completed = thread_summary.io_bytes_completed(); - data.total_time = master_summary.total_time(); - data.percent_multiplier *= (double)master_summary.active_cpus(); - data.actual_thread_count = 1; - data.wanted_thread_count = 1; - - // This causes the line printer to put "-" in various columns that don't make sense for a thread summary - data.type = SummaryLineData::SummaryType::Thread; - - print_summary_line(globals, machine, summary_interval, data); -} - -template -static void sort_processes(const Globals& globals, const CPUSummary& summary, std::vector*>& processes) { - switch (globals.sort_key()) { - case kSortKey::CPU: - // Sort by Actual CPU, Future CPU, pid - std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess* p0, const MachineProcess* p1) -> bool { - auto p0_summary = summary.process_summary(p0); - auto p1_summary = summary.process_summary(p1); - - AbsTime p0_run_time = p0_summary->total_run_time(); - AbsTime p1_run_time = p1_summary->total_run_time(); - - if (p0_run_time == p1_run_time) { - AbsTime p0_future_run_time = p0_summary->total_future_run_time(); - AbsTime p1_future_run_time = p1_summary->total_future_run_time(); - - if (p0_future_run_time == p1_future_run_time) - return p0->pid() < p1->pid(); - - return p1_future_run_time < p0_future_run_time; - } - - return p1_run_time < p0_run_time; - }); - break; - - case kSortKey::VMFault: - // Sort by VMFault time, #-faults, pid - std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess* p0, const MachineProcess* p1) -> bool { - auto p0_summary = summary.process_summary(p0); - auto p1_summary = summary.process_summary(p1); - - AbsTime p0_vm_fault_time = p0_summary->total_vm_fault_time(); - AbsTime p1_vm_fault_time = p1_summary->total_vm_fault_time(); - - if (p0_vm_fault_time == p1_vm_fault_time) { - uint32_t p0_vm_fault_count = p0_summary->num_vm_fault_events(); - uint32_t p1_vm_fault_count = p1_summary->num_vm_fault_events(); - - if (p0_vm_fault_count == p1_vm_fault_count) - return p0->pid() < p1->pid(); - - return p1_vm_fault_count < p0_vm_fault_count; - } - - return p1_vm_fault_time < p0_vm_fault_time; - }); - break; - - case kSortKey::IO_Wait: - // Sort by IO time, pid - std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess* p0, const MachineProcess* p1) -> bool { - auto p0_summary = summary.process_summary(p0); - auto p1_summary = summary.process_summary(p1); - - AbsTime p0_io_time = p0_summary->total_io_time(); - AbsTime p1_io_time = p1_summary->total_io_time(); - - if (p0_io_time == p1_io_time) { - uint32_t p0_io_ops = p0_summary->num_io_events(); - uint32_t p1_io_ops = p1_summary->num_io_events(); - - if (p0_io_ops == p1_io_ops) - return p0->pid() < p1->pid(); - - return p1_io_ops < p0_io_ops; - } - - return p1_io_time < p0_io_time; - }); - break; - - case kSortKey::IO_Ops: - // Sort by IO time, pid - std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess* p0, const MachineProcess* p1) -> bool { - auto p0_summary = summary.process_summary(p0); - auto p1_summary = summary.process_summary(p1); - - uint32_t p0_io_ops = p0_summary->num_io_events(); - uint32_t p1_io_ops = p1_summary->num_io_events(); - - if (p0_io_ops == p1_io_ops) { - AbsTime p0_io_time = p0_summary->total_io_time(); - AbsTime p1_io_time = p1_summary->total_io_time(); - - if (p0_io_time == p1_io_time) - return p0->pid() < p1->pid(); - - return p1_io_time < p0_io_time; - } - - return p1_io_ops < p0_io_ops; - }); - break; - - case kSortKey::IO_Size: - // Sort by IO time, pid - std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess* p0, const MachineProcess* p1) -> bool { - auto p0_summary = summary.process_summary(p0); - auto p1_summary = summary.process_summary(p1); - - uint64_t p0_io_bytes_completed = p0_summary->io_bytes_completed(); - uint64_t p1_io_bytes_completed = p1_summary->io_bytes_completed(); - - if (p0_io_bytes_completed == p1_io_bytes_completed) { - AbsTime p0_io_time = p0_summary->total_io_time(); - AbsTime p1_io_time = p1_summary->total_io_time(); - - if (p0_io_time == p1_io_time) - return p0->pid() < p1->pid(); - - return p1_io_time < p0_io_time; - } - - return p1_io_bytes_completed < p0_io_bytes_completed; - }); - break; - - case kSortKey::ID: - // Sort by pid - std::sort(processes.begin(), processes.end(), [](const MachineProcess* p0, const MachineProcess* p1) -> bool { - return p0->pid() < p1->pid(); - }); - break; - } -} - -template -static void sort_threads(const Globals& globals, const ProcessSummary& summary, std::vector*>& threads) { - switch (globals.sort_key()) { - case kSortKey::CPU: - std::sort(threads.begin(), threads.end(), [&summary](const MachineThread* t0, const MachineThread* t1) -> bool { - auto t0_summary = summary.thread_summary(t0); - auto t1_summary = summary.thread_summary(t1); - - AbsTime t0_run_time = t0_summary->total_run_time(); - AbsTime t1_run_time = t1_summary->total_run_time(); - - if (t0_run_time == t1_run_time) { - AbsTime t0_future_run_time = t0_summary->total_future_run_time(); - AbsTime t1_future_run_time = t1_summary->total_future_run_time(); - - if (t0_future_run_time == t1_future_run_time) - return t0->tid() < t1->tid(); - - return t1_future_run_time < t0_future_run_time; - } - - return t1_run_time < t0_run_time; - }); - break; - - case kSortKey::VMFault: - // Sort by VMFault time, #-faults, pid - std::sort(threads.begin(), threads.end(), [&summary](const MachineThread* t0, const MachineThread* t1) -> bool { - auto t0_summary = summary.thread_summary(t0); - auto t1_summary = summary.thread_summary(t1); - - AbsTime t0_vm_fault_time = t0_summary->total_vm_fault_time(); - AbsTime t1_vm_fault_time = t1_summary->total_vm_fault_time(); - - if (t0_vm_fault_time == t1_vm_fault_time) { - uint32_t t0_vm_fault_count = t0_summary->num_vm_fault_events(); - uint32_t t1_vm_fault_count = t1_summary->num_vm_fault_events(); - - if (t0_vm_fault_count == t1_vm_fault_count) - return t0->tid() < t1->tid(); - - return t1_vm_fault_count < t0_vm_fault_count; - } - - return t1_vm_fault_time < t0_vm_fault_time; - }); - break; - - case kSortKey::IO_Wait: - // Sort by IO time, pid - std::sort(threads.begin(), threads.end(), [&summary](const MachineThread* t0, const MachineThread* t1) -> bool { - auto t0_summary = summary.thread_summary(t0); - auto t1_summary = summary.thread_summary(t1); - - AbsTime t0_io_time = t0_summary->total_io_time(); - AbsTime t1_io_time = t1_summary->total_io_time(); - - if (t0_io_time == t1_io_time) { - uint32_t t0_io_ops = t0_summary->num_io_events(); - uint32_t t1_io_ops = t1_summary->num_io_events(); - - if (t0_io_ops == t1_io_ops) - return t0->tid() < t1->tid(); - - return t1_io_ops < t0_io_ops; - } - - return t1_io_time < t0_io_time; - }); - break; - - case kSortKey::IO_Ops: - // Sort by IO time, pid - std::sort(threads.begin(), threads.end(), [&summary](const MachineThread* t0, const MachineThread* t1) -> bool { - auto t0_summary = summary.thread_summary(t0); - auto t1_summary = summary.thread_summary(t1); - - uint32_t t0_io_ops = t0_summary->num_io_events(); - uint32_t t1_io_ops = t1_summary->num_io_events(); - - if (t0_io_ops == t1_io_ops) { - AbsTime t0_io_time = t0_summary->total_io_time(); - AbsTime t1_io_time = t1_summary->total_io_time(); - - if (t0_io_time == t1_io_time) - return t0->tid() < t1->tid(); - - return t1_io_time < t0_io_time; - } - - return t1_io_ops < t0_io_ops; - }); - break; - - case kSortKey::IO_Size: - // Sort by IO time, pid - std::sort(threads.begin(), threads.end(), [&summary](const MachineThread* t0, const MachineThread* t1) -> bool { - auto t0_summary = summary.thread_summary(t0); - auto t1_summary = summary.thread_summary(t1); - - uint64_t t0_io_bytes_completed = t0_summary->io_bytes_completed(); - uint64_t t1_io_bytes_completed = t1_summary->io_bytes_completed(); - - if (t0_io_bytes_completed == t1_io_bytes_completed) { - AbsTime t0_io_time = t0_summary->total_io_time(); - AbsTime t1_io_time = t1_summary->total_io_time(); - - if (t0_io_time == t1_io_time) - return t0->tid() < t1->tid(); - - return t1_io_time < t0_io_time; - } - - return t1_io_bytes_completed < t0_io_bytes_completed; - }); - break; - - case kSortKey::ID: - std::sort(threads.begin(), threads.end(), [](const MachineThread* t0, const MachineThread* t1) -> bool { - return t0->tid() < t1->tid(); - }); - break; - } -} - -template -void print_machine_summary(const Globals& globals, const Machine& machine) { - AbsInterval machine_timespan = machine.timespan(); - - AbsTime start(globals.summary_start(machine_timespan)); - AbsTime stop(globals.summary_stop(machine_timespan)); - AbsTime step(globals.summary_step(machine_timespan)); - - print_summary_header(globals); - - AbsInterval start_stop_timespan(start, stop - start); - AbsInterval clipped_start_stop_timespan(start_stop_timespan.intersection_range(machine_timespan)); - - start = clipped_start_stop_timespan.location(); - stop = clipped_start_stop_timespan.max(); - - while (start < stop) { - AbsInterval base_interval(start, step); - AbsInterval summary_interval(base_interval.intersection_range(clipped_start_stop_timespan)); - - // - // TOTAL summary - // - CPUSummary summary = machine.summary_for_timespan(summary_interval, NULL); - - // - // We want the TOTAL to include the number of ms elapsed, so print a duration - // - char total_buffer[64]; - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - snprintf(total_buffer, sizeof(total_buffer), "TOTAL (0x%llXmabs)", summary_interval.length().value()); - else - snprintf(total_buffer, sizeof(total_buffer), "TOTAL (%llumabs)", summary_interval.length().value()); - } else { - NanoTime ntime = summary_interval.length().nano_time(globals.timebase()); - snprintf(total_buffer, sizeof(total_buffer), "TOTAL (%3.2fms)", (double)ntime.value() / 1000000.0); - } - print_cpu_summary_with_name_and_indent(globals, machine, summary_interval, summary, summary, total_buffer, 0); - - std::vector> per_cpu_summaries; - - // - // TOTAL per cpu summary - // - if (globals.should_print_cpu_summaries()) { - // summary.cpus() is unordered, we want to display sorted by cpu_id. - std::vector*> sorted_cpus; - - for (auto& cpu : summary.cpus()) { - sorted_cpus.emplace_back(cpu); - } - - std::sort(sorted_cpus.begin(), sorted_cpus.end(), [](MachineCPU const* cpu0, MachineCPU const* cpu1) -> bool { - return cpu0->id() < cpu1->id(); - }); - - for (auto cpu : sorted_cpus) { - per_cpu_summaries.push_back(machine.summary_for_timespan(summary_interval, cpu)); - - char name[16]; - snprintf(name, sizeof(name), "CPU%d", cpu->id()); - print_cpu_summary_with_name_and_indent(globals, machine, summary_interval, summary, per_cpu_summaries.back(), name, 1); - } - } - - // - // PER PROCESS summary - // - if (globals.should_print_process_summaries()) { - // - // We want to sort the list of processes by PID, so they always display in the same order. - // - std::vector*> sorted_processes; - for (auto& process_summary : summary.process_summaries()) { - sorted_processes.emplace_back(process_summary.process()); - } - - sort_processes(globals, summary, sorted_processes); - - for (auto process : sorted_processes) { - ASSERT(summary.process_summary(process), "Unable to find process summary by pointer lookup"); - if (const ProcessSummary* process_summary = summary.process_summary(process)) { - char name[32]; - snprintf(name, sizeof(name), "%s (%d)%s", process->name(), process->pid(), process->is_exit_by_jetsam() ? " *" : ""); - print_process_summary_with_name_and_indent(globals, machine, summary_interval, summary, *process_summary, name, 1); - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const ProcessSummary* per_cpu_process_summary = cpu_summary.process_summary(process)) { - char name[32]; - snprintf(name, sizeof(name), "CPU%d %s (%d)", (*cpu_summary.cpus().begin())->id(), process->name(), process->pid()); - print_process_summary_with_name_and_indent(globals, machine, summary_interval, summary, *per_cpu_process_summary, name, 2); - } - } - } - - if (globals.should_print_thread_summaries()) { - // - // PER PROCESS per thread summary - // - std::vector*> sorted_threads; - for (auto& thread_summary : process_summary->thread_summaries()) { - sorted_threads.emplace_back(thread_summary.thread()); - } - - sort_threads(globals, *process_summary, sorted_threads); - - for (auto thread : sorted_threads) { - ASSERT(process_summary->thread_summary(thread), "Unable to find thread summary by pointer lookup"); - if (const ThreadSummary* thread_summary = process_summary->thread_summary(thread)) { - char name[32]; - snprintf(name, sizeof(name), "tid-%llX", (uint64_t)thread->tid()); - print_thread_summary_with_name_and_indent(globals, machine, summary_interval, summary, *thread_summary, name, 2); - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per thread per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const ProcessSummary* per_cpu_process_summary = cpu_summary.process_summary(process)) { - if (const ThreadSummary* per_cpu_thread_summary = per_cpu_process_summary->thread_summary(thread)) { - char name[32]; - snprintf(name, sizeof(name), "CPU%d tid-%llX", (*cpu_summary.cpus().begin())->id(), (uint64_t)thread->tid()); - print_thread_summary_with_name_and_indent(globals, machine, summary_interval, summary, *per_cpu_thread_summary, name, 3); - } - } - } - } - - } - } - } - } - } - } - - start += step; - } -} - - -template -void print_machine_csv_summary_header(const Globals& globals, - const Machine& machine, - std::vector*>& all_cpus, - std::vector*>& all_processes, - std::unordered_map*, std::vector*>>& all_threads, - const char* header_type) -{ - // Header is... - // - // "", header_type - // - // "", "TOTAL", "CPU0", "CPU1", "proc1", "proc1-tid1", "proc1-tid2", "proc2", etc.. - - // - // It turns out that calling dprintf is very expensive; we're going to - // accumulate to a string buffer and then flush once at the end. - // - char line[16384]; // Header lines can be big! - char* cursor = line; - char* line_end = line + sizeof(line); - - // - // header + TOTAL - // - cursor += snprintf(cursor, line_end - cursor, "%s\n\nTIME, TOTAL", header_type); - if (cursor > line_end) - cursor = line_end; - - // - // TOTAL per cpu summary - // - if (globals.should_print_cpu_summaries()) { - for (auto cpu : all_cpus) { - cursor += snprintf(cursor, line_end - cursor, ", CPU%d", cpu->id()); - if (cursor > line_end) - cursor = line_end; - } - } - - // - // PER PROCESS summary - // - if (globals.should_print_process_summaries()) { - for (auto process : all_processes) { - cursor += snprintf(cursor, line_end - cursor, ", %s (%d)", process->name(), process->pid()); - if (cursor > line_end) - cursor = line_end; - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per cpu summary - // - for (auto cpu : all_cpus) { - cursor += snprintf(cursor, line_end - cursor, ", CPU%d %s (%d)", cpu->id(), process->name(), process->pid()); - if (cursor > line_end) - cursor = line_end; - } - } - - if (globals.should_print_thread_summaries()) { - // - // PER PROCESS per thread summary - // - for (auto thread : all_threads[process]) { - cursor += snprintf(cursor, line_end - cursor, ", tid-%llX", (uint64_t)thread->tid()); - if (cursor > line_end) - cursor = line_end; - - // - // PER PROCESS per thread per cpu summary - // - for (auto cpu : all_cpus) { - cursor += snprintf(cursor, line_end - cursor, ", CPU%d tid-%llX", cpu->id(), (uint64_t)thread->tid()); - if (cursor > line_end) - cursor = line_end; - } - } - } - } - } - - dprintf(globals.output_fd(), "%s\n", line); -} - -template -void print_machine_csv_summary_actual_cpu_ms_line(const Globals& globals, - const Machine& machine, - AbsInterval summary_interval, - std::vector*>& all_cpus, - std::vector*>& all_processes, - std::unordered_map*, std::vector*>>& all_threads, - CPUSummary& master_summary, - std::vector>& per_cpu_summaries) -{ - char line[16384]; // Header lines can be big! - char* cursor = line; - char* line_end = line + sizeof(line); - - // - // Time - // - - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - cursor += snprintf(cursor, line_end - cursor, "%llX", (summary_interval.location() - globals.beginning_of_time()).value()); - else - cursor += snprintf(cursor, line_end - cursor, "%llu", (summary_interval.location() - globals.beginning_of_time()).value()); - } else { - NanoTime ntime = (summary_interval.location() - globals.beginning_of_time()).nano_time(globals.timebase()); - cursor += snprintf(cursor, line_end - cursor, "%3.2f", (double)ntime.value() / 1000000.0); - } - - if (cursor > line_end) - cursor = line_end; - - // - // TOTAL - // - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)master_summary.total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - - if (cursor > line_end) - cursor = line_end; - - // - // TOTAL per cpu summary - // - if (globals.should_print_cpu_summaries()) { - for (auto& cpu_summary : per_cpu_summaries) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)cpu_summary.total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - - if (cursor > line_end) - cursor = line_end; - } - } - - // - // PER PROCESS summary - // - if (globals.should_print_process_summaries()) { - for (auto process : all_processes) { - const ProcessSummary* process_summary; - - // Not all summaries will have a matching process entry! - if ((process_summary = master_summary.process_summary(process))) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)process_summary->total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, ","); - } - - if (cursor > line_end) - cursor = line_end; - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const auto& process_summary = cpu_summary.process_summary(process)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)process_summary->total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, ","); - } - - if (cursor > line_end) - cursor = line_end; - } - } - - if (globals.should_print_thread_summaries()) { - // - // PER PROCESS per thread summary - // - - // - // We again have to do a bit more work, sometime a process is missing and we still need to print empty slots for its threads. - - - for (auto thread : all_threads[process]) { - if (process_summary) { - if (const auto& thread_summary = process_summary->thread_summary(thread)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)thread_summary->total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - - if (cursor > line_end) - cursor = line_end; - - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per thread per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const auto& per_cpu_process_summary = cpu_summary.process_summary(process)) { - if (const auto& per_cpu_thread_summary = per_cpu_process_summary->thread_summary(thread)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)per_cpu_thread_summary->total_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - - if (cursor > line_end) - cursor = line_end; - } - } - } - } - } - } - - dprintf(globals.output_fd(), "%s\n", line); -} - -template -void print_machine_csv_summary_wanted_cpu_ms_line(const Globals& globals, - const Machine& machine, - AbsInterval summary_interval, - std::vector*>& all_cpus, - std::vector*>& all_processes, - std::unordered_map*, std::vector*>>& all_threads, - CPUSummary& master_summary, - std::vector>& per_cpu_summaries) -{ - char line[16384]; // Header lines can be big! - char* cursor = line; - char* line_end = line + sizeof(line); - - // - // Time - // - - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - cursor += snprintf(cursor, line_end - cursor, "%llX", (summary_interval.location() - globals.beginning_of_time()).value()); - else - cursor += snprintf(cursor, line_end - cursor, "%llu", (summary_interval.location() - globals.beginning_of_time()).value()); - } else { - NanoTime ntime = (summary_interval.location() - globals.beginning_of_time()).nano_time(globals.timebase()); - cursor += snprintf(cursor, line_end - cursor, "%3.2f", (double)ntime.value() / 1000000.0); - } - - if (cursor > line_end) - cursor = line_end; - - // - // TOTAL - // - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)master_summary.total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - - if (cursor > line_end) - cursor = line_end; - - // - // TOTAL per cpu summary - // - if (globals.should_print_cpu_summaries()) { - for (auto& cpu_summary : per_cpu_summaries) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)cpu_summary.total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - - if (cursor > line_end) - cursor = line_end; - } - } - - // - // PER PROCESS summary - // - if (globals.should_print_process_summaries()) { - for (auto process : all_processes) { - const ProcessSummary* process_summary; - - // Not all summaries will have a matching process entry! - if ((process_summary = master_summary.process_summary(process))) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)process_summary->total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, ","); - } - - if (cursor > line_end) - cursor = line_end; - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const auto& process_summary = cpu_summary.process_summary(process)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)process_summary->total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else { - cursor += snprintf(cursor, line_end - cursor, ","); - } - - if (cursor > line_end) - cursor = line_end; - } - } - - if (globals.should_print_thread_summaries()) { - // - // PER PROCESS per thread summary - // - - // - // We again have to do a bit more work, sometime a process is missing and we still need to print empty slots for its threads. - - - for (auto thread : all_threads[process]) { - if (process_summary) { - if (const auto& thread_summary = process_summary->thread_summary(thread)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)thread_summary->total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - - if (cursor > line_end) - cursor = line_end; - - - if (globals.should_print_cpu_summaries()) { - // - // PER PROCESS per thread per cpu summary - // - for (auto& cpu_summary : per_cpu_summaries) { - if (const auto& per_cpu_process_summary = cpu_summary.process_summary(process)) { - if (const auto& per_cpu_thread_summary = per_cpu_process_summary->thread_summary(thread)) { - cursor += snprintf(cursor, line_end - cursor, ", %3.2f", - (double)per_cpu_thread_summary->total_future_run_time().nano_time(globals.timebase()).value() / 1000000.0); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - } else - cursor += snprintf(cursor, line_end - cursor, ","); - - if (cursor > line_end) - cursor = line_end; - } - } - } - } - } - } - - dprintf(globals.output_fd(), "%s\n", line); -} - -template -void print_machine_csv_summary(const Globals& globals, const Machine& machine) { - AbsInterval machine_timespan = machine.timespan(); - - AbsTime start(globals.summary_start(machine_timespan)); - AbsTime stop(globals.summary_stop(machine_timespan)); - AbsTime step(globals.summary_step(machine_timespan)); - - AbsInterval start_stop_timespan(start, stop - start); - AbsInterval clipped_start_stop_timespan(start_stop_timespan.intersection_range(machine_timespan)); - - start = clipped_start_stop_timespan.location(); - stop = clipped_start_stop_timespan.max(); - - // - // While printing a csv summary, we need to use the entire set of processes/threads/cpus - // from the range, even though they may not run in each sample. We first gather a summary - // for the entire time, to get the master list. - // - CPUSummary start_stop_summary = machine.summary_for_timespan(clipped_start_stop_timespan, NULL); - - std::vector*> all_processes; - std::vector*> all_cpus; - std::unordered_map*, std::vector*>> all_threads; - - // - // gather all processes - // - { - for (auto& process_summary : start_stop_summary.process_summaries()) { - all_processes.emplace_back(process_summary.process()); - } - - sort_processes(globals, start_stop_summary, all_processes); - } - - // - // gather all cpus - // - if (globals.should_print_cpu_summaries()) { - for (auto& cpu : start_stop_summary.cpus()) { - all_cpus.emplace_back(cpu); - } - - std::sort(all_cpus.begin(), all_cpus.end(), [](MachineCPU const* cpu0, MachineCPU const* cpu1) -> bool { - return cpu0->id() < cpu1->id(); - }); - } - - // - // gather all threads - // - if (globals.should_print_thread_summaries()) { - for (auto process : all_processes) { - ASSERT(start_stop_summary.process_summary(process), "Unable to find process summary by pointer lookup"); - if (const ProcessSummary* process_summary = start_stop_summary.process_summary(process)) { - // - // PER PROCESS per thread summary - // - auto& sorted_threads = all_threads[process]; - for (auto& thread_summary : process_summary->thread_summaries()) { - sorted_threads.emplace_back(thread_summary.thread()); - } - - sort_threads(globals, *process_summary, sorted_threads); - } - } - } - - print_machine_csv_summary_header(globals, machine, all_cpus, all_processes, all_threads, "Actual CPU/ms"); - - while (start < stop) { - AbsInterval base_interval(start, step); - AbsInterval summary_interval(base_interval.intersection_range(clipped_start_stop_timespan)); - - // - // TOTAL summary - // - CPUSummary summary = machine.summary_for_timespan(summary_interval, NULL); - - // - // Per CPU summaries... - // - std::vector> per_cpu_summaries; - if (globals.should_print_cpu_summaries()) { - for (auto cpu : all_cpus) { - per_cpu_summaries.push_back(machine.summary_for_timespan(summary_interval, cpu)); - } - } - - print_machine_csv_summary_actual_cpu_ms_line(globals, machine, summary_interval, all_cpus, all_processes, all_threads, summary, per_cpu_summaries); - - start += step; - } - - - // - // Now print Wanted CPU/ms - // - start = clipped_start_stop_timespan.location(); - stop = clipped_start_stop_timespan.max(); - - dprintf(globals.output_fd(), "\n"); - print_machine_csv_summary_header(globals, machine, all_cpus, all_processes, all_threads, "Wanted CPU/ms"); - - while (start < stop) { - AbsInterval base_interval(start, step); - AbsInterval summary_interval(base_interval.intersection_range(clipped_start_stop_timespan)); - - // - // TOTAL summary - // - CPUSummary summary = machine.summary_for_timespan(summary_interval, NULL); - - // - // Per CPU summaries... - // - std::vector> per_cpu_summaries; - if (globals.should_print_cpu_summaries()) { - for (auto cpu : all_cpus) { - per_cpu_summaries.push_back(machine.summary_for_timespan(summary_interval, cpu)); - } - } - - print_machine_csv_summary_wanted_cpu_ms_line(globals, machine, summary_interval, all_cpus, all_processes, all_threads, summary, per_cpu_summaries); - - start += step; - } -} - -template -void print_process_start_stop_timestamps(const Globals& globals, const Machine& machine) { - for (auto process : machine.processes()) { - - // - // Skip processes with no events - // - - if (process->timespan().length() == 0) { - // Skip processes with nothing in them. - // The assert may be too strong. - ASSERT(process->is_created_by_thread_map(), "Expected a zero length process to be from the thread map"); - continue; - } - - // - // Don't print the kernel process, it will occupy the entire trace - // - if (process->is_kernel()) - continue; - - // - // Time - // - char time_buffer[64]; - if (globals.beginning_of_time().value() == 0) - snprintf(time_buffer, sizeof(time_buffer), "%llumabs", process->timespan().location().value()); - else - snprintf(time_buffer, sizeof(time_buffer), "%llumabs", (process->timespan().location() - globals.beginning_of_time()).value()); - - // - // End time - // - char end_time_buffer[64]; - if (globals.beginning_of_time().value() == 0) - snprintf(end_time_buffer, sizeof(end_time_buffer), "%llumabs", process->timespan().max().value()); - else - snprintf(end_time_buffer, sizeof(end_time_buffer), "%llumabs", (process->timespan().max() - globals.beginning_of_time()).value()); - - const char* create_reason; - if (process->is_created_by_thread_map()) - create_reason = "Threadmap Entry"; - else if (process->is_created_by_previous_machine_state()) - create_reason = "Prev Machine State"; - else if (process->is_created_by_fork_exec()) - create_reason = "ForkExec"; - else if (process->is_created_by_exec()) - create_reason = "Exec"; - else - create_reason = "???"; - - if (globals.is_verbose()) { - printf(" %30s (%6d) --start %-16s --stop %-16s\tCreated by %-18s %s\n", - process->name(), - process->pid(), - time_buffer, - end_time_buffer, - create_reason, - process->is_trace_terminated() ? "EXITED" : ""); - } else { - printf(" %30s (%6d) --start %s --stop %s\n", - process->name(), - process->pid(), - time_buffer, - end_time_buffer); - } - } -} - -template -void print_verbose_machine_info(const Globals& globals, const Machine& machine, uint32_t threadmap_count, uint32_t cpumap_count) { - dprintf(globals.output_fd(), "\tEvent data is %s, and appears to be from %s\n", SIZE::is_64_bit ? "K64" : "K32", machine.is_ios() ? "iOS" : "OSX"); - dprintf(globals.output_fd(), "\tUsing a%stimebase of %d/%d\n", globals.is_timebase_set() ? " [User Set] " : " ", globals.timebase().numer, globals.timebase().denom); - - if (threadmap_count) { - dprintf(globals.output_fd(), "\tA threadmap is present, and contains %u entries\n", threadmap_count); - } else { - dprintf(globals.output_fd(), "\tA threadmap is not present"); - } - - if (cpumap_count) { - dprintf(globals.output_fd(), "\tA cpumap is present, and contains %u entries\n", cpumap_count); - - } else { - dprintf(globals.output_fd(), "\tA cpumap is not present, the system provided a default with %u cpus and %u iops\n", globals.cpu_count(), globals.iop_count()); - } - - dprintf(globals.output_fd(), "\tFound %u active cpus in trace data\n", machine.active_cpus()); - - if (globals.is_summary_start_set()) { - AbsInterval machine_timespan = machine.timespan(); - - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - dprintf(globals.output_fd(), "\tUsing a --start value of 0x%llXmabs (raw)\n", globals.summary_start(machine_timespan).value()); - else - dprintf(globals.output_fd(), "\tUsing a --start value of %llumabs\n", (globals.summary_start(machine_timespan) - machine_timespan.location()).value()); - } else { - NanoTime ntime = (globals.summary_start(machine_timespan) - machine_timespan.location()).nano_time(globals.timebase()); - dprintf(globals.output_fd(), "\tUsing a --start value of %3.2fms\n", (double)ntime.value() / 1000000.0); - } - } - - if (globals.is_summary_stop_set()) { - AbsInterval machine_timespan = machine.timespan(); - - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - dprintf(globals.output_fd(), "\tUsing a --stop value of 0x%llXmabs (raw)\n", globals.summary_stop(machine_timespan).value()); - else - dprintf(globals.output_fd(), "\tUsing a --stop value of %llumabs\n", (globals.summary_stop(machine_timespan) - machine_timespan.location()).value()); - } else { - NanoTime ntime = (globals.summary_stop(machine_timespan) - machine_timespan.location()).nano_time(globals.timebase()); - dprintf(globals.output_fd(), "\tUsing a --stop value of %3.2fms\n", (double)ntime.value() / 1000000.0); - } - } - - if (globals.is_summary_step_set()) { - AbsInterval machine_timespan = machine.timespan(); - - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - dprintf(globals.output_fd(), "\tUsing a --step value of 0x%llXmabs (raw)\n", globals.summary_step(machine_timespan).value()); - else - dprintf(globals.output_fd(), "\tUsing a --step value of %llumabs\n", globals.summary_step(machine_timespan).value()); - } else { - NanoTime ntime = globals.summary_step(machine_timespan).nano_time(globals.timebase()); - dprintf( globals.output_fd(), "\tUsing a --step value of %3.2fms\n", (double)ntime.value() / 1000000.0); - } - } -} - -#endif diff --git a/kdprof/TraceFileAction.cpp b/kdprof/TraceFileAction.cpp deleted file mode 100644 index c7ae70b..0000000 --- a/kdprof/TraceFileAction.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// -// TraceFileAction.cpp -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -#if 0 -template -static void execute_arch_specific(Globals& globals, std::string path) -{ - // - // Trace file looks roughly like: - // - // RAW_header - // threadmap[thread_count] - // wasted-space-to-align-to-next-4096-byte-boundary - // KDEvents[] - // - - MappedFile trace_data(path.c_str()); - if (TraceDataHeader* header = reinterpret_cast*>(trace_data.address())) { - - KDThreadMapEntry* threadmap = NULL; - uint32_t threadmap_count = 0; - KDCPUMapEntry* cpumap = NULL; - uint32_t cpumap_count = 0; - KDEvent* events = NULL; - - if (header->version() != RAW_VERSION1) { - // If the header is not a RAW_VERSION1, we must assume it is a - // RAW_VERSION0. The difficulty here is that RAW_VERSION0 consists - // of 4 bytes, which are the thread_count. We can't do much - // sanity checking. The first four bytes are already read into - // the existing header, reuse them. We must also reset the file - // offset. - - threadmap_count = header->version(); - threadmap = reinterpret_cast*>(trace_data.address() + 4); - - // Event data starts immediately following the threadmap - size_t offset = 4 + threadmap_count * sizeof(KDThreadMapEntry); - events = reinterpret_cast*>(trace_data.address() + offset); - } else { - // - // RAW_VERSION1 - // - threadmap_count = header->thread_count(); - threadmap = reinterpret_cast*>(trace_data.address() + sizeof(TraceDataHeader)); - - size_t threadmap_size_in_bytes = threadmap_count * sizeof(KDThreadMapEntry); - size_t offset_to_event_data = (sizeof(TraceDataHeader) + threadmap_size_in_bytes + 4095) & ~4095; - size_t offset_to_cpumap_data = sizeof(TraceDataHeader) + threadmap_size_in_bytes; - size_t cpumap_bytes = offset_to_event_data - offset_to_cpumap_data; - - // - // In a RAW_VERSION1, there *may* be a cpumap. - // If it exists, it will be between the header and the page aligned offset - // that event data begins at. - // - if (cpumap_bytes > sizeof(kd_cpumap_header) + sizeof(kd_cpumap)) { - kd_cpumap_header* cpumap_header = reinterpret_cast(trace_data.address() + offset_to_cpumap_data); - if (cpumap_header->version_no == RAW_VERSION1) { - cpumap = (KDCPUMapEntry*)&cpumap_header[1]; - cpumap_count = cpumap_header->cpu_count; - } - } - - // Event data starts at the next PAGE alignment boundary. - // - // Hmm, this could be pretty awful in iOS... - // - // Kernel page size is 4k. Userspace page size is 16kb in 64b. - // Kernel writes the data. Unless the kernel call fails, then userspace writes the data. Blech. - events = reinterpret_cast*>(trace_data.address() + offset_to_event_data); - } - - uintptr_t event_count = (uintptr_t)trace_data.size() - (reinterpret_cast(events) - reinterpret_cast(trace_data.address())); - if (event_count % sizeof(KDEvent) != 0) { - // We're probably looking at the wrong k32/k64. Throw and try the other size. - THROW("Bytes in file does not match an even multiple of Event struct"); - } - event_count /= sizeof(KDEvent); - - std::vector default_cpumap; - - if (cpumap == NULL || cpumap_count == 0) { - // No cpumap found, we need to fake one up using the default values. - for (uint32_t i=0; i> presorted_events; - if (globals.should_presort_events() && event_count) { - presorted_events.set_capacity(event_count); - memcpy(presorted_events.data(), events, event_count * sizeof(KDEvent)); - events = presorted_events.data(); - std::sort(events, events + event_count, [](KDEvent const& p0, KDEvent const& p1) -> bool { - return p0.timestamp() < p1.timestamp(); - }); - } - - Machine machine(cpumap, cpumap_count, threadmap, threadmap_count, events, event_count); - - if (!machine.lost_events()) { - if (globals.should_zero_base_timestamps() && event_count) { - globals.set_beginning_of_time(events[0].timestamp()); - } else { - globals.set_beginning_of_time(AbsTime(0)); - } - - if (!globals.is_timebase_set()) { - if (machine.is_ios()) { - globals.set_timebase({ 125, 3 }, false); - } else { - globals.set_timebase({ 1, 1 }, false); - } - } - - if (globals.is_verbose()) { - dprintf(globals.output_fd(), "\n%s\n", path.c_str()); - print_verbose_machine_info(globals, machine, threadmap_count, (default_cpumap.empty()) ? cpumap_count : 0); - } - - if (globals.should_print_events()) { - print_machine_events(globals, machine); - } - - if (globals.should_print_summary()) { - print_machine_summary(globals, machine); - } - - if (globals.should_print_csv_summary()) { - print_machine_csv_summary(globals, machine); - } - - if (globals.should_print_process_start_stop_timestamps()) { - print_process_start_stop_timestamps(globals, machine); - } - } else { - log_msg(ASL_LEVEL_WARNING, "The trace data indicates that events were lost, the file cannot be processed\n"); - } - } else { - log_msg(ASL_LEVEL_ERR, "Unable to read from %s\n", path.c_str()); - exit(1); - } -} - -void TraceFileAction::execute(Globals& globals) { - if (globals.is_kernel_size_set()) { - try { - if (globals.kernel_size() == KernelSize::k32) - execute_arch_specific(globals, _path); - else - execute_arch_specific(globals, _path); - } catch (Exception& e) { - log_msg(ASL_LEVEL_ERR, "An exception was raised: %s", e.what()); - log_msg(ASL_LEVEL_ERR, "An explicit kernel size was set, you may want to try not forcing the size to a single value\n"); - log_msg(ASL_LEVEL_ERR, "You may also want to check the number of cpus and iops configured if the file is from a device and does not have a cpumap\n"); - } - } else { - // Try em both! - try { - execute_arch_specific(globals, _path); - } catch (Exception& e) { - execute_arch_specific(globals, _path); - } - } -} - -#endif - -template -static void execute_arch_specific(Globals& globals, TraceFile& file, std::string& path) -{ - Machine machine(file); - - if (!machine.lost_events()) { - if (globals.should_zero_base_timestamps() && machine.event_count()) { - globals.set_beginning_of_time(machine.events()[0].timestamp()); - } else { - globals.set_beginning_of_time(AbsTime(0)); - } - - if (!globals.is_timebase_set()) { - if (machine.is_ios()) { - globals.set_timebase({ 125, 3 }, false); - } else { - globals.set_timebase({ 1, 1 }, false); - } - } - - if (globals.is_verbose()) { - dprintf(globals.output_fd(), "\n%s\n", path.c_str()); - print_verbose_machine_info(globals, machine, file.threadmap_count(), file.cpumap_count()); - } - - if (globals.should_print_events()) { - print_machine_events(globals, machine); - } - - if (globals.should_print_summary()) { - print_machine_summary(globals, machine); - } - - if (globals.should_print_csv_summary()) { - print_machine_csv_summary(globals, machine); - } - - if (globals.should_print_process_start_stop_timestamps()) { - print_process_start_stop_timestamps(globals, machine); - } - } else { - log_msg(ASL_LEVEL_WARNING, "The trace data indicates that events were lost, the file cannot be processed\n"); - } -} - -void TraceFileAction::execute(Globals& globals) { - TraceFile file(_path.c_str(), globals.should_presort_events(), globals.cpu_count(), globals.iop_count()); - if (globals.is_kernel_size_set()) { - try { - if (globals.kernel_size() == KernelSize::k32) - execute_arch_specific(globals, file, _path); - else - execute_arch_specific(globals, file, _path); - } catch (Exception& e) { - log_msg(ASL_LEVEL_ERR, "An exception was raised: %s", e.what()); - log_msg(ASL_LEVEL_ERR, "An explicit kernel size was set, you may want to try not forcing the size to a single value\n"); - log_msg(ASL_LEVEL_ERR, "You may also want to check the number of cpus and iops configured if the file is from a device and does not have a cpumap\n"); - } - } else { - if (file.is_valid()) { - if (file.is_64_bit()) { - execute_arch_specific(globals, file, _path); - } else { - execute_arch_specific(globals, file, _path); - } - } else { - if (file.mmap_failed()) { - log_msg(ASL_LEVEL_ERR, "Unable to mmap %s, it may exceed this devices memory limits\n", _path.c_str()); - } else { - log_msg(ASL_LEVEL_ERR, "%s does not appear to be a valid trace file\n", _path.c_str()); - } - } - } -} - diff --git a/kdprof/TraceFileAction.hpp b/kdprof/TraceFileAction.hpp deleted file mode 100644 index b91d369..0000000 --- a/kdprof/TraceFileAction.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// TraceFileAction.h -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef __kdprof__TraceFileAction__ -#define __kdprof__TraceFileAction__ - -class TraceFileAction : public Action { - protected: - std::string _path; - - public: - TraceFileAction(const char* path) : _path(path) { - ASSERT(Path::is_file(_path, TRUE), "File must exist"); - } - - virtual void execute(Globals& globals); -}; - -#endif /* defined(__kdprof__TraceFileAction__) */ diff --git a/kdprof/global.h b/kdprof/global.h deleted file mode 100644 index 6575a99..0000000 --- a/kdprof/global.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// global.h -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#ifndef kdprof_global_h -#define kdprof_global_h - -#include - -using namespace util; - -#include "KDebug.h" - -#include -#include - -#include -#include -#include - -#include "Globals.hpp" -#include "EventPrinting.hpp" -#include "SummaryPrinting.hpp" -#include "Action.hpp" -#include "InitializeAction.hpp" -#include "TraceFileAction.hpp" -#include "RemoveAction.hpp" -#include "NoWrapAction.hpp" -#include "PrintStateAction.hpp" -#include "EnableAction.hpp" -#include "DisableAction.hpp" -#include "CollectAction.hpp" -#include "SleepAction.hpp" -#include "SaveTraceAction.hpp" - -__attribute__((noreturn)) void usage(const char *); - -#endif diff --git a/kdprof/kdprof.1 b/kdprof/kdprof.1 deleted file mode 100644 index 6d7861e..0000000 --- a/kdprof/kdprof.1 +++ /dev/null @@ -1,17 +0,0 @@ -.Dd 3/8/14 -.Dt kdprof 1 -.Os Darwin -.Sh NAME -.Nm kdprof -.Nd kdebug profiler and event printer -.Sh SYNOPSIS -.Nm -.Op Fl h, -help -.Sh DESCRIPTION -The help output for kdprof is more recent than this man page. Please run -.Nm ---help -.Sh SEE ALSO -.Xr lsmp 1 , -.Xr msa 1 , -.Xr trace 1 diff --git a/kdprof/kdprof.cpp b/kdprof/kdprof.cpp deleted file mode 100644 index cd14502..0000000 --- a/kdprof/kdprof.cpp +++ /dev/null @@ -1,444 +0,0 @@ -// -// main.cpp -// kdprof -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2013 Apple. All rights reserved. -// - -#include "global.h" - -// Generated by agvtool -extern const unsigned char __kdprofVersionString[]; - -bool shouldPrintVersion = false; - -__attribute__((noreturn)) void usage(const char *errorMsg) { - if (errorMsg) { - fprintf(stderr, "%s\n", errorMsg); - exit(1); - } - - const char* BOLD = "\033[1m"; - const char* UNBOLD = "\033[0m"; - - // printf("01234567890123456789012345678901234567890123456789012345678901234567890123456789\n"); - printf("kdprof [options] [path/trace.codes ...] [path/data.trace ...]\n\n"); - printf(" GLOBAL OPTIONS\n\n"); - printf(" -h, --help Print this message\n"); - printf(" --version Print version info\n"); - printf(" -v, --verbose Print additional information\n"); - printf(" --presort-events Sort events before processing. IOP workaround\n"); - printf(" -N, --no-default-codes Do not read the default trace codes\n"); - printf("\n"); - printf(" LIVE TRACING OPTIONS\n\n"); - printf(" -i, --intialize [#] Initialize the trace buffer, with opt buf count\n"); - printf(" -r, --remove Remove the trace buffer\n"); - printf(" -n, --no-wrap Do not allow the trace buffer to wrap\n"); - printf(" -g, --print-kdbg-state Print the current kdbg state\n"); - printf(" -e, --enable Enable collection of events\n"); - printf(" -d, --disable Disable collection of events\n"); - printf(" -t, --collect Collect and print the trace buffer\n"); - printf(" --save path Collect and save the trace buffer to path\n"); - printf(" -S, --sleep # Wait for a specified interval\n"); - printf("\n"); - printf(" OUTPUT OPTIONS\n\n"); - printf(" -o, --output path Print output to path\n"); - printf(" --summary Print calculated data (default true)\n"); - printf(" --no-summary Do not print calculated data\n"); - printf(" --csv Print a csv formatted summary for use in numbers\n"); - printf(" --no-csv Do not print a csv formatted summary\n"); - printf(" --step # Step by # time units in summary output\n"); - printf(" --process Include per-process summary data\n"); - printf(" --no-process Do not include per-process summary data\n"); - printf(" --thread Include per-thread summary data\n"); - printf(" --cpu Include per-cpu summary data\n"); - printf(" --sort-by-cpu Sort process/thread lists by cpu usage\n"); - printf(" --sort-by-vmfault Sort process/thread lists by vmfault time\n"); - printf(" --sort-by-io-wait Sort process/thread lists by IO time\n"); - printf(" --sort-by-io-ops Sort process/thread lists by # IO Ops\n"); - printf(" --sort-by-io-size Sort process/thread lists by IO bytes\n"); - printf(" --sort-by-pid Sort process/thread lists by pid/tid\n"); - printf(" --events Enable individual event printing\n"); - printf(" --no-events Disable individual event printing\n"); - printf(" --raw-timestamps Print timestamps as raw values, not deltas\n"); - printf(" --mach-absolute-time Print timestamps in mach absolute time\n"); - printf(" --event-index Print the index of each event\n"); - printf(" --no-codes Print hex trace codes, not symbolic\n"); - printf(" --process-start-stop Print start/stop information about each process\n"); - printf("\n"); - printf(" DEPRECATED OPTIONS\n\n"); - printf(" -X, --k32 Trace data is from a 32 bit kernel\n"); - printf(" --k64 Trace data is from a 64 bit kernel\n"); - printf(" --codes path read trace codes from path\n"); - printf(" --trace path read trace data from path\n"); - printf(" --ios Treat data as coming from an iOS device\n"); - printf(" --timebase #/# Set the mach_timebase\n"); - printf(" --cpus # Set the # of cpus.\n"); - printf(" --iops # Set the # of iops.\n"); - printf("\n"); - printf(" OPTION ARGUMENTS\n\n"); - printf(" All arguments that specifiy a time value may use the following postfixes\n\n"); - printf(" s Seconds\n"); - printf(" ms Milliseconds\n"); - printf(" us Microseconds\n"); - printf(" ns Nanoseconds\n"); - printf(" mabs Mach Absolute Time Units\n"); - printf("\n"); - // printf("01234567890123456789012345678901234567890123456789012345678901234567890123456789\n"); - printf(" USAGE\n"); - printf("\n"); - printf(" Arguments are parsed in order. Long form flags are not case sensitive.\n"); - printf(" Live tracing and trace file arguments are pushed onto an execution stack\n"); - printf(" and processed after argument parsing has completed.\n"); - printf("\n"); - printf(" Files ending in .trace or .codes may omit the --trace or --codes flag\n"); - printf(" In most cases, you do not need to specify a kernel size or timebase, it is\n"); - printf(" determined automatically.\n"); - printf("\n"); - printf(" Modern trace(s) have an embedded ap/iop cpu count. If you need to parse\n"); - printf(" an older file, you will want to set these. Typically you would set the AP\n"); - printf(" cpu count to the number of active cpus, and the IOP cpu count to zero.\n"); - printf("\n"); - printf(" EXAMPLES\n"); - printf("\n"); - printf(" %skdprof InterestingData.trace%s\n", BOLD, UNBOLD); - printf(" Print a summary of per process cpu usage in InterestingData.trace\n"); - printf("\n"); - printf(" %skdprof --step 100ms InterestingData.trace%s\n", BOLD, UNBOLD); - printf(" Print summaries of the per process cpu usage in InterestingData.trace,\n"); - printf(" one for each 100ms of time\n"); - printf("\n"); - printf(" %skdprof --thread --step 100ms InterestingData.trace%s\n", BOLD, UNBOLD); - printf(" Print summaries of the per process and per thread cpu usage in\n"); - printf(" InterestingData.trace, one for each 100ms of time\n"); - printf("\n"); - printf(" %skdprof -r -i 100000 -e -S 1 -d -t%s\n", BOLD, UNBOLD); - printf(" Reinit the trace buffer with 100000 entries, enable it, wait 1 second,\n"); - printf(" and then collect/print the trace buffer\n"); - printf("\n"); - printf(" %skdprof --events foo.trace%s\n", BOLD, UNBOLD); - printf(" Print the events in foo.trace\n"); - printf("\n"); - exit(1); -} - -static void add_trace_codes_path(const char* path, Globals& globals) { - if (Path::is_file(path, true)) { - char resolved_path[PATH_MAX]; - if (realpath(path, resolved_path)) { - globals.append_trace_codes_at_path(resolved_path); - return; - } - } - char* errmsg = NULL; - asprintf(&errmsg, "Trace codes path %s is not valid", path); - usage(errmsg); -} - -static std::unique_ptr create_trace_file_action(const char* trace_file_path) { - if (Path::is_file(trace_file_path, true)) { - char resolved_path[PATH_MAX]; - if (realpath(trace_file_path, resolved_path)) { - return std::make_unique(resolved_path); - } - } - char* errmsg = NULL; - asprintf(&errmsg, "Trace data path %s is not valid", trace_file_path); - usage(errmsg); -} - -// -// Must take globals so it can do the timebase conversions for mabs values! -// -static NanoTime parse_time(Globals& globals, const char* arg) { - - char* units; - uint64_t value = strtoull(arg, &units, 0); - - // Unspecified units are treated as seconds - if (*units == 0 || strcmp(units, "s") == 0) { - return NanoTime(value * NANOSECONDS_PER_SECOND); - } - - if (strcmp(units, "ms") == 0) - return NanoTime(value * NANOSECONDS_PER_MILLISECOND); - - if (strcmp(units, "us") == 0) - return NanoTime(value * NANOSECONDS_PER_MICROSECOND); - - if (strcmp(units, "ns") == 0) - return NanoTime(value); - - if (strcmp(units, "mabs") == 0) { - return AbsTime(value).nano_time(globals.timebase()); - } - - usage("Unable to parse units on time value"); -} - -static std::vector> parse_arguments(int argc, const char* argv[], Globals& globals) { - int i = 1; - bool cpus_set = false; - bool iops_set = false; - - std::vector> actions; - - while (i < argc) { - const char* arg = argv[i]; - if ((strcmp(arg, "-h") == 0) || (strcasecmp(arg, "--help") == 0)) { - usage(NULL); - } else if ((strcasecmp(arg, "--version") == 0)) { - shouldPrintVersion = true; - } else if ((strcmp(arg, "-v") == 0) || strcasecmp(arg, "--verbose") == 0) { - globals.set_is_verbose(true); - } else if ((strcasecmp(arg, "--summary") == 0)) { - globals.set_should_print_summary(true); - } else if ((strcasecmp(arg, "--no-summary") == 0)) { - globals.set_should_print_summary(false); - } else if ((strcasecmp(arg, "--csv") == 0)) { - globals.set_should_print_csv_summary(true); - } else if ((strcasecmp(arg, "--no-csv") == 0)) { - globals.set_should_print_csv_summary(false); - } else if (strcasecmp(arg, "--step") == 0) { - if (++i >= argc) - usage("--step requires an argument"); - - globals.set_summary_step(argv[i]); - // Force a blow up now if the arg is unparseable - globals.summary_step(AbsInterval(AbsTime(1), AbsTime(1))); - } else if (strcasecmp(arg, "--start") == 0) { - if (++i >= argc) - usage("--start requires an argument"); - - globals.set_summary_start(argv[i]); - // Force a blow up now if the arg is unparseable - globals.summary_start(AbsInterval(AbsTime(1), AbsTime(1))); - } else if (strcasecmp(arg, "--stop") == 0) { - if (++i >= argc) - usage("--stop requires an argument"); - - globals.set_summary_stop(argv[i]); - // Force a blow up now if the arg is unparseable - globals.summary_stop(AbsInterval(AbsTime(1), AbsTime(1))); - } else if ((strcasecmp(arg, "--cpu") == 0)) { - globals.set_should_print_cpu_summaries(true); - } else if ((strcasecmp(arg, "--processes") == 0) || (strcasecmp(arg, "--process") == 0)) { - globals.set_should_print_process_summaries(true); - } else if ((strcasecmp(arg, "--no-processes") == 0) || (strcasecmp(arg, "--no-process") == 0)) { - globals.set_should_print_process_summaries(false); - } else if ((strcasecmp(arg, "--threads") == 0) || (strcasecmp(arg, "--thread") == 0)) { - globals.set_should_print_thread_summaries(true); - } else if ((strcasecmp(arg, "--sort-by-cpu") == 0)) { - globals.set_sort_key(kSortKey::CPU); - } else if ((strcasecmp(arg, "--sort-by-pid") == 0)) { - globals.set_sort_key(kSortKey::ID); - } else if ((strcasecmp(arg, "--sort-by-vmfault") == 0)) { - globals.set_sort_key(kSortKey::VMFault); - } else if ((strcasecmp(arg, "--sort-by-io") == 0)) { - globals.set_sort_key(kSortKey::IO_Wait); - } else if ((strcasecmp(arg, "--sort-by-io-wait") == 0)) { - globals.set_sort_key(kSortKey::IO_Wait); - } else if ((strcasecmp(arg, "--sort-by-io-ops") == 0)) { - globals.set_sort_key(kSortKey::IO_Ops); - } else if ((strcasecmp(arg, "--sort-by-io-size") == 0)) { - globals.set_sort_key(kSortKey::IO_Size); - } else if ((strcasecmp(arg, "--events") == 0)) { - globals.set_should_print_events(true); - } else if ((strcasecmp(arg, "--no-events") == 0)) { - globals.set_should_print_events(false); - } else if ((strcasecmp(arg, "--presort-events") == 0)) { - globals.set_should_presort_events(true); - } else if ((strcmp(arg, "-N") == 0) || strcasecmp(arg, "--no-default-codes") == 0) { - globals.set_should_read_default_trace_codes(false); - } else if (strcasecmp(arg, "--codes") == 0) { - if (++i >= argc) - usage("--codes requires an argument"); - add_trace_codes_path(argv[i], globals); - } else if (strcasecmp(arg, "--trace") == 0) { - if (++i >= argc) - usage("--trace requires an argument"); - - actions.push_back(create_trace_file_action(argv[i])); - } else if ((strcmp(arg, "-i") == 0) || strcasecmp(arg, "--initialize") == 0) { - // The buffers argument is optional - uint32_t buffers_default = 0; - - if (i + 1 < argc) { - arg = argv[i+1]; - char* endptr; - uint32_t temp = (uint32_t)strtoul(arg, &endptr, 0); - if (*endptr == 0) { - // Consume the following argument if the conversion worked - buffers_default = temp; - i++; - } - - } - actions.push_back(std::make_unique(buffers_default)); - } else if ((strcmp(arg, "-r") == 0) || strcasecmp(arg, "--remove") == 0) { - actions.push_back(std::make_unique()); - } else if ((strcmp(arg, "-n") == 0) || strcasecmp(arg, "--no-wrap") == 0) { - actions.push_back(std::make_unique()); - } else if ((strcmp(arg, "-g") == 0) || strcasecmp(arg, "--print-kdbg-state") == 0) { - actions.push_back(std::make_unique()); - } else if ((strcmp(arg, "-e") == 0) || strcasecmp(arg, "--enable") == 0) { - actions.push_back(std::make_unique()); - } else if ((strcmp(arg, "-d") == 0) || strcasecmp(arg, "--disable") == 0) { - actions.push_back(std::make_unique()); - } else if ((strcmp(arg, "-t") == 0) || strcasecmp(arg, "--collect") == 0) { - actions.push_back(std::make_unique()); - } else if (strcasecmp(arg, "--save") == 0) { - if (++i >= argc) - usage("--save requires an argument"); - - FileDescriptor desc(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (!desc.is_open()) { - char* errmsg = NULL; - asprintf(&errmsg, "Unable to create save file at %s", argv[i]); - usage(errmsg); - } - actions.push_back(std::make_unique(std::move(desc))); - } else if ((strcmp(arg, "-S") == 0) || strcasecmp(arg, "--sleep") == 0) { - if (++i >= argc) - usage("--sleep requires an argument"); - - actions.push_back(std::make_unique(parse_time(globals, argv[i]))); - } else if (strcasecmp(arg, "--ios") == 0) { - globals.set_timebase({ 125, 3 }, true); - /* - if (!cpus_set && !iops_set) { - globals.set_default_cpu_count(2); // Good guess for most devices - globals.set_default_iop_count(4); // Pure speculation... - }*/ - } else if ((strcmp(arg, "-X") == 0) || strcasecmp(arg, "--k32") == 0) { - globals.set_kernel_size(KernelSize::k32); - } else if (strcasecmp(arg, "--k64") == 0) { - globals.set_kernel_size(KernelSize::k64); - } else if (strcasecmp(arg, "--timebase") == 0) { - if (++i >= argc) - usage("--timebase requires an argument"); - arg = argv[i]; - - mach_timebase_info_data_t timebase; - if (sscanf(arg, "%u/%u", &timebase.numer, &timebase.denom) != 2) { - usage("Unable to parse --timebase argument"); - } - globals.set_timebase(timebase, true); - } else if (strcasecmp(arg, "--cpus") == 0) { - cpus_set = true; - if (++i >= argc) - usage("--cpus requires an argument"); - char* endptr; - uint32_t cpus = (uint32_t)strtoul(argv[i], &endptr, 0); - if (*endptr != 0) - usage("Unable to parse --cpus argument"); - globals.set_cpu_count(cpus); - } else if (strcasecmp(arg, "--iops") == 0) { - iops_set = true; - if (++i >= argc) - usage("--iops requires an argument"); - char* endptr; - uint32_t iops = (uint32_t)strtoul(argv[i], &endptr, 0); - if (*endptr != 0) - usage("Unable to parse --iops argument"); - globals.set_iop_count(iops); - } else if (strcasecmp(arg, "--raw-timestamps") == 0) { - globals.set_should_zero_base_timestamps(false); - } else if (strcasecmp(arg, "--mach-absolute-time") == 0) { - globals.set_should_print_mach_absolute_timestamps(true); - } else if (strcasecmp(arg, "--event-index") == 0) { - globals.set_should_print_event_index(true); - } else if (strcasecmp(arg, "--no-codes") == 0) { - globals.set_should_print_symbolic_event_codes(false); - } else if ((strcasecmp(arg, "--process-start-stop") == 0) || (strcasecmp(arg, "--process-start-stops") == 0)) { - globals.set_should_print_process_start_stop_timestamps(true); - } else if ((strcmp(arg, "-o") == 0) || strcasecmp(arg, "--output") == 0) { - if (++i >= argc) - usage("--output requires an argument"); - - FileDescriptor desc(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (!desc.is_open()) { - char* errmsg = NULL; - asprintf(&errmsg, "Unable to create output file at %s", argv[i]); - usage(errmsg); - } - globals.set_output_fd(std::move(desc)); - } else { - // - // Last attempts to divine argument type/intent. - // - std::string temp(arg); - - // Is it a .codes file? - if (ends_with(temp, ".codes")) { - add_trace_codes_path(arg, globals); - goto no_error; - } - - if (ends_with(temp, ".trace")) { - actions.push_back(create_trace_file_action(argv[i])); - goto no_error; - } - - // - // ERROR! - // - char error_buffer[PATH_MAX]; - snprintf(error_buffer, sizeof(error_buffer), "Unhandled argument: %s", arg); - usage(error_buffer); - } - no_error: - - i++; - } - - return actions; -} - -int main (int argc, const char * argv[]) -{ - // - // Use host values as defaults. - // User overrides as needed via flags. - // - Globals globals; - auto actions = parse_arguments(argc, argv, globals); - - if (shouldPrintVersion) { - printf("%s version: %s", argv[0], __kdprofVersionString); - exit(0); - } - - globals.resolve_trace_codes(); - - // 0x24000004 PPT_test - - // Validate start/stop, if they are both set. - // - // The timebase isn't set for the tracefile at this point. This - // can sometimes fail when using a desktop timebase and mixed - // units (ms & mabs, for example) - if (globals.is_summary_start_set() && globals.is_summary_stop_set()) { - AbsInterval checker(AbsTime(1), AbsTime(1)); - if (globals.summary_stop(checker) <= globals.summary_start(checker)) { - usage("The current --stop value is less than or equal to the --start value"); - } - } - - // If the user didn't ask for anything, set them up with a basic full trace summary - if (!globals.should_print_summary() && - !globals.should_print_events() && - !globals.should_print_csv_summary() && - !globals.should_print_process_start_stop_timestamps() && - !globals.is_should_print_summary_set()) - { - globals.set_should_print_summary(true); - } - - for (auto& action : actions) { - action->execute(globals); - } - - return 0; -} diff --git a/kpgo.tproj/kpgo.c b/kpgo.tproj/kpgo.c index 0b439cf..dacfc4c 100644 --- a/kpgo.tproj/kpgo.c +++ b/kpgo.tproj/kpgo.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2014 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2014-2016 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ @@ -38,6 +38,7 @@ static void usage(char **argv) 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"); + fprintf (stderr, " -R : reset all counters\n"); exit(1); } @@ -49,8 +50,11 @@ int main(int argc, char **argv) uuid_t uuid; int c; - while ((c = getopt(argc, argv, "hHwm")) != EOF) { + while ((c = getopt(argc, argv, "hHwmR")) != EOF) { switch(c) { + case 'R': + flags |= PGO_RESET_ALL; + break; case 'H': flags |= PGO_HIB; break; @@ -79,6 +83,19 @@ int main(int argc, char **argv) } } + if (flags & PGO_RESET_ALL) { + if (flags != PGO_RESET_ALL || uuidp) { + usage(argv); + } + ssize_t r = grab_pgo_data(NULL, PGO_RESET_ALL, NULL, 0); + if (r < 0) + { + perror("grab_pgo_data"); + return 1; + } + return 0; + } + ssize_t size = grab_pgo_data(uuidp, flags, NULL, 0); if (size < 0) @@ -124,5 +141,4 @@ int main(int argc, char **argv) } return 0; - } diff --git a/latency.tproj/latency.c b/latency.tproj/latency.c index 0a7e9b3..8047b2d 100644 --- a/latency.tproj/latency.c +++ b/latency.tproj/latency.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2010 Apple Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,11 +17,11 @@ * 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@ */ -/* +/* cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -o latency latency.c -lncurses -lutil */ @@ -87,8 +87,8 @@ struct i_latencies { int i_msec_1_bins[10]; int i_msec_10_bins[5]; int i_too_slow; - int i_max_latency; - int i_min_latency; + long i_max_latency; + long i_min_latency; int i_total_samples; int i_total; int i_exceeded_threshold; @@ -114,7 +114,7 @@ char *kernelpath = NULL; typedef struct { void *k_sym_addr; /* kernel symbol address from nm */ - u_int k_sym_len; /* length of kernel symbol string */ + size_t k_sym_len; /* length of kernel symbol string */ char *k_sym_name; /* kernel symbol string from nm */ } kern_sym_t; @@ -163,7 +163,7 @@ uint64_t cpu_mask; int sample_generation = 0; int num_i_latency_cpus = 1; int num_cpus; -char *my_buffer; +void *my_buffer; int num_entries; kd_buf **last_decrementer_kd; /* last DECR_TRAP per cpu */ @@ -186,7 +186,7 @@ typedef struct lookup *lookup_t; struct lookup { lookup_t lk_next; - + uintptr_t lk_thread; uintptr_t lk_dvp; long *lk_pathptr; @@ -198,7 +198,7 @@ typedef struct threadmap *threadmap_t; struct threadmap { threadmap_t tm_next; - + uintptr_t tm_thread; uintptr_t tm_pthread; char tm_command[MAXCOMLEN + 1]; @@ -210,7 +210,7 @@ typedef struct threadrun *threadrun_t; struct threadrun { threadrun_t tr_next; - + uintptr_t tr_thread; kd_buf *tr_entry; uint64_t tr_timestamp; @@ -225,7 +225,6 @@ struct thread_entry { uintptr_t te_thread; }; - #define HASH_SIZE 1024 #define HASH_MASK 1023 @@ -266,26 +265,21 @@ typedef struct { #define KERNEL_MODE 1 -#define TRACE_DATA_NEWTHREAD 0x07000004 -#define TRACE_STRING_NEWTHREAD 0x07010004 -#define TRACE_STRING_EXEC 0x07010008 - -#define INTERRUPT 0x01050000 -#define DECR_TRAP 0x01090000 -#define DECR_SET 0x01090004 -#define MACH_vmfault 0x01300008 -#define MACH_sched 0x01400000 -#define MACH_stkhandoff 0x01400008 +#define INTERRUPT 0x01050000 +#define DECR_TRAP 0x01090000 +#define DECR_SET 0x01090004 +#define MACH_vmfault 0x01300008 +#define MACH_sched 0x01400000 +#define MACH_stkhandoff 0x01400008 #define MACH_makerunnable 0x01400018 #define MACH_idle 0x01400024 -#define VFS_LOOKUP 0x03010090 -#define IES_action 0x050b0018 -#define IES_filter 0x050b001c -#define TES_action 0x050c0010 -#define CQ_action 0x050d0018 +#define IES_action 0x050b0018 +#define IES_filter 0x050b001c +#define TES_action 0x050c0010 +#define CQ_action 0x050d0018 #define CPUPM_CPUSTER_RUNCOUNT 0x05310144 -#define BSC_exit 0x040C0004 +#define BSC_exit 0x040C0004 #define BSC_thread_terminate 0x040c05a4 #define DBG_FUNC_MASK ~(DBG_FUNC_START | DBG_FUNC_END) @@ -294,7 +288,6 @@ typedef struct { #define EMPTYSTRING "" - const char *fault_name[] = { "", "ZeroFill", @@ -333,9 +326,9 @@ const char *sched_reasons[] = { static double handle_decrementer(kd_buf *, int); static kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency); static void read_command_map(void); -static void enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); -static void exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); -static void print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note); +static void enter_syscall(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); +static void exit_syscall(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); +static void print_entry(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note); static void log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf *kd_note); static char *find_code(int); static void pc_to_string(char *pcstring, uintptr_t pc, int max_len, int mode); @@ -364,7 +357,7 @@ quit(char *s) if (trace_enabled) { set_enable(0); } - /* + /* * This flag is turned off when calling * quit() due to a set_remove() failure. */ @@ -380,7 +373,7 @@ quit(char *s) } void -set_enable(int val) +set_enable(int val) { int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDENABLE, val }; size_t needed; @@ -390,8 +383,8 @@ set_enable(int val) } } -void -set_numbufs(int nbufs) +static void +set_numbufs(int nbufs) { int mib1[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETBUF, nbufs }; int mib2[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETUP }; @@ -405,8 +398,8 @@ set_numbufs(int nbufs) } } -void -set_pidexclude(int pid, int on_off) +static void +set_pidexclude(int pid, int on_off) { int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDPIDEX }; size_t needed = sizeof(kd_regtype); @@ -420,12 +413,12 @@ set_pidexclude(int pid, int on_off) sysctl(mib, ARRAYSIZE(mib), &kr, &needed, NULL, 0); } -void +static void get_bufinfo(kbufinfo_t *val) { int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDGETBUF }; size_t needed = sizeof (*val); - + if (sysctl(mib, ARRAYSIZE(mib), val, &needed, 0, 0) < 0) { quit("trace facility failure, KERN_KDGETBUF\n"); } @@ -450,7 +443,7 @@ set_remove(void) } -void +static void write_high_res_latencies(void) { int i; @@ -466,7 +459,7 @@ write_high_res_latencies(void) } } -void +static void sigintr(int signo __attribute__((unused))) { write_high_res_latencies(); @@ -481,7 +474,7 @@ sigintr(int signo __attribute__((unused))) } /* exit under normal conditions -- signal handler */ -void +static void leave(int signo __attribute__((unused))) { write_high_res_latencies(); @@ -490,17 +483,17 @@ leave(int signo __attribute__((unused))) set_pidexclude(getpid(), 0); endwin(); set_remove(); - + exit(1); } -void +static void sigwinch(int signo __attribute__((unused))) { gotSIGWINCH = 1; } -void +static void print_total(FILE *fp, char *s, int total) { int cpu; @@ -541,10 +534,10 @@ screen_update(FILE *fp) int cpu; int clen; int itotal, stotal; - int elapsed_secs; - int elapsed_mins; - int elapsed_hours; - int min_lat, max_lat; + long elapsed_secs; + long elapsed_mins; + long elapsed_hours; + long min_lat, max_lat; uint64_t tot_lat; unsigned int average_s_latency; unsigned int average_i_latency; @@ -560,7 +553,7 @@ screen_update(FILE *fp) /* * Display the current time. * "ctime" always returns a string that looks like this: - * + * * Sun Sep 16 01:03:52 1973 * 012345678901234567890123 * 1 2 @@ -568,7 +561,7 @@ screen_update(FILE *fp) * We want indices 11 thru 18 (length 8). */ if (RAW_flag) { - curr_time = sample_TOD_secs; + curr_time = (unsigned long)sample_TOD_secs; elapsed_secs = ((last_now - first_now) / divisor) / 1000000; } else { elapsed_secs = curr_time - start_time; @@ -663,7 +656,7 @@ screen_update(FILE *fp) if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + clen += sprintf(&tbuf[clen], " %9d", il->i_usec_10_bins[i]); } } @@ -768,7 +761,7 @@ screen_update(FILE *fp) if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + clen += sprintf(&tbuf[clen], " %9d", il->i_too_slow); } } @@ -785,13 +778,13 @@ screen_update(FILE *fp) min_lat = il->i_min_latency; } } - clen = sprintf(tbuf, "\n\nminimum latency(usecs) %7d %9d", s_min_latency, min_lat); + clen = sprintf(tbuf, "\n\nminimum latency(usecs) %7d %9ld", s_min_latency, min_lat); if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - - clen += sprintf(&tbuf[clen], " %9d", il->i_min_latency); + + clen += sprintf(&tbuf[clen], " %9ld", il->i_min_latency); } } if (fp) { @@ -808,13 +801,13 @@ screen_update(FILE *fp) max_lat = il->i_max_latency; } } - clen = sprintf(tbuf, "\nmaximum latency(usecs) %7d %9d", s_max_latency, max_lat); + clen = sprintf(tbuf, "\nmaximum latency(usecs) %7d %9ld", s_max_latency, max_lat); if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - - clen += sprintf(&tbuf[clen], " %9d", il->i_max_latency); + + clen += sprintf(&tbuf[clen], " %9ld", il->i_max_latency); } } if (fp) { @@ -822,7 +815,7 @@ screen_update(FILE *fp) } else { printw(tbuf); } - + if (s_total_samples) { average_s_latency = (unsigned int)(s_total_latency/s_total_samples); } else { @@ -831,7 +824,7 @@ screen_update(FILE *fp) for (itotal = 0, tot_lat = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + itotal += il->i_total_samples; tot_lat += il->i_total_latency; } @@ -846,7 +839,7 @@ screen_update(FILE *fp) if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + if (il->i_total_samples) { average_i_latency = (unsigned int)(il->i_total_latency/il->i_total_samples); } else { @@ -861,10 +854,10 @@ screen_update(FILE *fp) } else { printw(tbuf); } - + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + itotal += il->i_exceeded_threshold; } clen = sprintf(tbuf, "\nexceeded threshold %7d %9d", s_exceeded_threshold, itotal); @@ -872,7 +865,7 @@ screen_update(FILE *fp) if (i_latency_per_cpu == TRUE) { for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { il = &i_lat[cpu]; - + clen += sprintf(&tbuf[clen], " %9d", il->i_exceeded_threshold); } } @@ -882,7 +875,7 @@ screen_update(FILE *fp) fprintf(fp, "%s", tbuf); } else { printw(tbuf); - } + } if (fp == NULL) { refresh(); @@ -891,28 +884,27 @@ screen_update(FILE *fp) } } -int +static int exit_usage(void) { fprintf(stderr, "Usage: latency [-p ] [-h] [-m] [-st ] [-it ]\n"); fprintf(stderr, " [-c ] [-l ] [-R ] [-n ]\n\n"); - + fprintf(stderr, " -p specify scheduling priority to watch... default is realtime. Can also be a range, e.g. \"31-47\".\n"); fprintf(stderr, " -h Display high resolution interrupt latencies and write them to latencies.csv (truncate existing file) upon exit.\n"); fprintf(stderr, " -st set scheduler latency threshold in microseconds... if latency exceeds this, then log trace\n"); - fprintf(stderr, " -m specify per-CPU interrupt latency reporting\n"); + fprintf(stderr, " -m specify per-CPU interrupt latency reporting\n"); fprintf(stderr, " -it set interrupt latency threshold in microseconds... if latency exceeds this, then log trace\n"); fprintf(stderr, " -c specify name of codes file... default is /usr/share/misc/trace.codes\n"); fprintf(stderr, " -l specify name of file to log trace entries to when the specified threshold is exceeded\n"); fprintf(stderr, " -R specify name of raw trace file to process\n"); - fprintf(stderr, " -n specify kernel... default is /System/Library/Kernels/kernel.development\n"); + fprintf(stderr, " -n specify kernel... default is /System/Library/Kernels/kernel.development\n"); fprintf(stderr, "\nlatency must be run as root\n\n"); exit(1); } - int main(int argc, char *argv[]) { @@ -969,7 +961,7 @@ main(int argc, char *argv[]) } else if (strcmp(argv[1], "-it") == 0) { argc--; argv++; - + if (argc > 1) { i_thresh_hold = atoi(argv[1]); } else { @@ -978,7 +970,7 @@ main(int argc, char *argv[]) } else if (strcmp(argv[1], "-c") == 0) { argc--; argv++; - + if (argc > 1) { code_file = argv[1]; } else { @@ -987,7 +979,7 @@ main(int argc, char *argv[]) } else if (strcmp(argv[1], "-l") == 0) { argc--; argv++; - + if (argc > 1) { open_logfile(argv[1]); } else { @@ -1147,8 +1139,6 @@ main(int argc, char *argv[]) } } - - void read_command_map(void) { @@ -1177,7 +1167,7 @@ read_command_map(void) } } total_threads = header.thread_count; - + sample_TOD_secs = header.TOD_secs; sample_TOD_usecs = header.TOD_usecs; @@ -1190,14 +1180,14 @@ read_command_map(void) } else { total_threads = bufinfo.nkdthreads; } - + size = total_threads * sizeof(kd_threadmap); if (size == 0 || ((mapptr = (kd_threadmap *) malloc(size)) == 0)) { return; } bzero (mapptr, size); - + /* * Now read the threadmap */ @@ -1251,7 +1241,7 @@ create_map_entry(uintptr_t thread, char *command) threadmap_hash[hashid] = tme; } -void +static void delete_thread_entry(uintptr_t thread) { threadmap_t tme; @@ -1279,7 +1269,7 @@ delete_thread_entry(uintptr_t thread) } } -void +static void find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) { threadmap_t tme; @@ -1310,7 +1300,7 @@ find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) } } -void +static void create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) { threadmap_t tme; @@ -1330,7 +1320,7 @@ create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) threadmap_temp = tme; } -threadmap_t +static threadmap_t find_thread_entry(uintptr_t thread) { threadmap_t tme; @@ -1345,7 +1335,7 @@ find_thread_entry(uintptr_t thread) return 0; } -void +static void find_thread_name(uintptr_t thread, char **command) { threadmap_t tme; @@ -1357,7 +1347,7 @@ find_thread_name(uintptr_t thread, char **command) } } -void +static void add_thread_entry_to_list(thread_entry_t *list, uintptr_t thread) { thread_entry_t te; @@ -1373,7 +1363,7 @@ add_thread_entry_to_list(thread_entry_t *list, uintptr_t thread) *list = te; } -void +static void exec_thread_entry(uintptr_t thread, char *command) { threadmap_t tme; @@ -1392,13 +1382,13 @@ exec_thread_entry(uintptr_t thread, char *command) } } -void +static void record_thread_entry_for_gc(uintptr_t thread) { add_thread_entry_to_list(&thread_delete_list, thread); } -void +static void gc_thread_entries(void) { thread_entry_t te; @@ -1417,7 +1407,7 @@ gc_thread_entries(void) thread_delete_list = 0; } -void +static void gc_reset_entries(void) { thread_entry_t te; @@ -1434,7 +1424,7 @@ gc_reset_entries(void) thread_reset_list = 0; } -void +static void reset_thread_names(void) { thread_entry_t te; @@ -1460,7 +1450,7 @@ reset_thread_names(void) thread_reset_list = 0; } -void +static void delete_all_thread_entries(void) { threadmap_t tme = 0; @@ -1477,9 +1467,6 @@ delete_all_thread_entries(void) } } - - - static void insert_run_event(uintptr_t thread, int priority, kd_buf *kd, uint64_t now) { @@ -1555,7 +1542,8 @@ delete_run_event(uintptr_t thread) } static void -gc_run_events(void) { +gc_run_events(void) +{ thread_entry_t te; thread_entry_t te_next; threadrun_t trp; @@ -1679,7 +1667,7 @@ gc_start_events(void) thread_event_list = 0; } -int +static int thread_in_user_mode(uintptr_t thread, char *command) { event_t evp; @@ -1698,8 +1686,6 @@ thread_in_user_mode(uintptr_t thread, char *command) return 1; } - - static lookup_t handle_lookup_event(uintptr_t thread, int debugid, kd_buf *kdp) { @@ -1788,7 +1774,8 @@ delete_lookup_event(uintptr_t thread, lookup_t lkp_to_delete) } static void -gc_lookup_events(void) { +gc_lookup_events(void) +{ thread_entry_t te; thread_entry_t te_next; lookup_t lkp; @@ -1819,7 +1806,8 @@ sample_sc(void) { kd_buf *kd, *end_of_sample; int keep_going = 1; - int count, i; + int i; + ssize_t count; if (!RAW_flag) { /* @@ -1833,7 +1821,7 @@ sample_sc(void) need_new_map = 0; } if (RAW_flag) { - uint32_t bytes_read; + ssize_t bytes_read; bytes_read = read(RAW_fd, my_buffer, num_entries * sizeof(kd_buf)); @@ -1852,7 +1840,7 @@ sample_sc(void) first_now = kd->timestamp & KDBG_TIMESTAMP_MASK; first_read = 0; } - + } else { int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDREADTR }; size_t needed = bufinfo.nkdbufs * sizeof(kd_buf); @@ -1866,7 +1854,7 @@ sample_sc(void) if (bufinfo.flags & KDBG_WRAPPED) { need_new_map = 1; - + if (log_fp) { fprintf(log_fp, "\n\n%-19.19s sample = %d <<<<<<< trace buffer wrapped >>>>>>>\n\n", &(ctime(&curr_time)[0]), sample_generation); @@ -1925,10 +1913,8 @@ sample_sc(void) return keep_going; } - - void -enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) +enter_syscall(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) { char *p; double timestamp; @@ -1953,19 +1939,19 @@ enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_ pc_to_string(&pcstring[0], kd->arg2, 58, mode); - fprintf(fp, "%9.1f %8.1f\t\tINTERRUPT[%2lx] @ %-58.58s %8x %2d %s\n", + fprintf(fp, "%9.1f %8.1f\t\tINTERRUPT[%2lx] @ %-58.58s %8lx %2d %s\n", timestamp, delta, kd->arg1, &pcstring[0], thread, cpunum, command); } else if (type == MACH_vmfault) { - fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %8x %2d %s\n", + fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %8lx %2d %s\n", timestamp, delta, p, thread, cpunum, command); } else { - fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-16lx %-16lx %-16lx %-16lx %8x %2d %s\n", - timestamp, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-16lx %-16lx %-16lx %-16lx %8lx %2d %s\n", + timestamp, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, thread, cpunum, command); } } else { - fprintf(fp, "%9.1f %8.1f\t\t%-8x %-16lx %-16lx %-16lx %-16lx %8x %2d %s\n", - timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + fprintf(fp, "%9.1f %8.1f\t\t%-8x %-16lx %-16lx %-16lx %-16lx %8lx %2d %s\n", + timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, thread, cpunum, command); } } @@ -1974,9 +1960,8 @@ enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_ } } - void -exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) +exit_syscall(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) { char *p; uint64_t user_addr; @@ -1996,29 +1981,28 @@ exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t if ((p = find_code(type))) { if (type == INTERRUPT) { - fprintf(fp, "INTERRUPT %8x %2d %s\n", thread, cpunum, command); + fprintf(fp, "INTERRUPT %8lx %2d %s\n", thread, cpunum, command); } else if (type == MACH_vmfault && kd->arg4 <= DBG_PAGEIND_FAULT) { user_addr = ((uint64_t)kd->arg1 << 32) | (uint32_t)kd->arg2; - fprintf(fp, "%-28.28s %-10.10s %-16qx %8x %2d %s\n", + fprintf(fp, "%-28.28s %-10.10s %-16qx %8lx %2d %s\n", p, fault_name[kd->arg4], user_addr, thread, cpunum, command); } else { - fprintf(fp, "%-28.28s %-16lx %-16lx %8x %2d %s\n", + fprintf(fp, "%-28.28s %-16lx %-16lx %8lx %2d %s\n", p, kd->arg1, kd->arg2, thread, cpunum, command); } } else { - fprintf(fp, "%-8x %-16lx %-16lx %8x %2d %s\n", + fprintf(fp, "%-8x %-16lx %-16lx %8lx %2d %s\n", type, kd->arg1, kd->arg2, thread, cpunum, command); } } } - void -print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note) +print_entry(FILE *fp, kd_buf *kd, uintptr_t thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note) { char *p; @@ -2037,16 +2021,15 @@ print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t } else { fprintf(fp, "%9.1f %8.1f\t\t", timestamp, delta); } - fprintf(fp, "%-28.28s %-16lx %-16lx %-16lx %-16lx %8x %2d %s\n", + fprintf(fp, "%-28.28s %-16lx %-16lx %-16lx %-16lx %8lx %2d %s\n", p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, thread, cpunum, command); } else { - fprintf(fp, "%9.1f %8.1f\t\t%-8x %-16lx %-16lx %-16lx %-16lx %8x %2d %s\n", - timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + fprintf(fp, "%9.1f %8.1f\t\t%-8x %-16lx %-16lx %-16lx %-16lx %8lx %2d %s\n", + timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, thread, cpunum, command); } } - void check_for_thread_update(uintptr_t thread, int debugid_base, kd_buf *kbufp, char **command) { @@ -2072,13 +2055,12 @@ check_for_thread_update(uintptr_t thread, int debugid_base, kd_buf *kbufp, char } } - void log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf *kd_note) { lookup_t lkp; int mode; - int reason; + uintptr_t reason; char *p; char *command; char *command1; @@ -2091,7 +2073,7 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf double delta; char joe[32]; - int thread = kd->arg5; + uintptr_t thread = kd->arg5; int cpunum = CPU_NUMBER(kd); int debugid = kd->debugid; int type = kd->debugid & DBG_FUNC_MASK; @@ -2111,28 +2093,28 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf case CQ_action: pc_to_string(&pcstring[0], kd->arg1, 84, KERNEL_MODE); - fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-84.84s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-84.84s %8lx %2d %s\n", timestamp, delta, &pcstring[0], thread, cpunum, command); break; case TES_action: pc_to_string(&pcstring[0], kd->arg1, 83, KERNEL_MODE); - fprintf(log_fp, "%9.1f %8.1f\t\tTES_action @ %-83.83s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f\t\tTES_action @ %-83.83s %8lx %2d %s\n", timestamp, delta, &pcstring[0], thread, cpunum, command); break; case IES_action: pc_to_string(&pcstring[0], kd->arg1, 83, KERNEL_MODE); - fprintf(log_fp, "%9.1f %8.1f\t\tIES_action @ %-83.83s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f\t\tIES_action @ %-83.83s %8lx %2d %s\n", timestamp, delta, &pcstring[0], thread, cpunum, command); break; case IES_filter: pc_to_string(&pcstring[0], kd->arg1, 83, KERNEL_MODE); - fprintf(log_fp, "%9.1f %8.1f\t\tIES_filter @ %-83.83s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f\t\tIES_filter @ %-83.83s %8lx %2d %s\n", timestamp, delta, &pcstring[0], thread, cpunum, command); break; @@ -2157,12 +2139,12 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf pc_to_string(&pcstring[0], kd->arg2, 84, mode); - fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-84.84s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-84.84s %8lx %2d %s\n", timestamp, delta, i_latency, p, &pcstring[0], thread, cpunum, command); break; case DECR_SET: - fprintf(log_fp, "%9.1f %8.1f[%.1f] \t%-28.28s %8x %2d %s\n", + fprintf(log_fp, "%9.1f %8.1f[%.1f] \t%-28.28s %8lx %2d %s\n", timestamp, delta, (double)kd->arg1/divisor, "DECR_SET", thread, cpunum, command); break; @@ -2170,7 +2152,7 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf case MACH_stkhandoff: find_thread_name(kd->arg2, &command1); - + if (command1 == EMPTYSTRING) { command1 = command_buf; sprintf(command1, "%-8lx", kd->arg2); @@ -2190,12 +2172,12 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf } if (sched_reason[0] == '?') { - sprintf(joe, "%x", reason); + sprintf(joe, "%lx", reason); sched_reason = joe; } sprintf(sched_info, "%16.16s @ pri %3lu --> %16.16s @ pri %3lu%s", command, kd->arg3, command1, kd->arg4, p); - fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s[%s] %s %8x %2d\n", + fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s[%s] %s %8lx %2d\n", timestamp, delta, "MACH_SCHED", sched_reason, sched_info, thread, cpunum); break; @@ -2205,16 +2187,16 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf * print the tail end of the pathname */ p = (char *)lkp->lk_pathname; - int clen = strlen(p); + size_t clen = strlen(p); if (clen > 45) { clen -= 45; } else { clen = 0; } - - fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-59s %-16lx %8x %2d %s\n", - timestamp, delta, "VFS_LOOKUP", + + fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-59s %-16lx %8lx %2d %s\n", + timestamp, delta, "VFS_LOOKUP", &p[clen], lkp->lk_dvp, thread, cpunum, command); delete_lookup_event(thread, lkp); @@ -2233,9 +2215,7 @@ log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf } } - - -void +static void log_range(kd_buf *kd_buffer, kd_buf *kd_start, kd_buf *kd_stop, kd_buf *kd_note, char *buf1) { uint64_t last_timestamp = 0; @@ -2243,7 +2223,7 @@ log_range(kd_buf *kd_buffer, kd_buf *kd_start, kd_buf *kd_stop, kd_buf *kd_note, uint64_t start_bias = 0; uint64_t now; kd_buf *kd; - int clen; + size_t clen; char buf2[128]; clen = strlen(buf1); @@ -2270,7 +2250,7 @@ log_range(kd_buf *kd_buffer, kd_buf *kd_start, kd_buf *kd_stop, kd_buf *kd_note, last_timestamp = now; } else { int debugid = kd->debugid; - int thread = kd->arg5; + uintptr_t thread = kd->arg5; int type = kd->debugid & DBG_FUNC_MASK; if ((type >> 24) == DBG_TRACE) { @@ -2293,7 +2273,6 @@ log_range(kd_buf *kd_buffer, kd_buf *kd_start, kd_buf *kd_stop, kd_buf *kd_note, gc_lookup_events(); } - kd_buf * log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency) { @@ -2303,7 +2282,7 @@ log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_ double sample_timestamp; char buf1[128]; - int thread = kd_beg->arg5; + uintptr_t thread = kd_beg->arg5; int cpunum = CPU_NUMBER(kd_end); for (kd_count = 0, kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer); kd_start--, kd_count++) { @@ -2314,7 +2293,7 @@ log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_ if (CPU_NUMBER(kd_start) != cpunum) { continue; } - + if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP) { break; } @@ -2354,7 +2333,7 @@ log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_ sample_timestamp = (double)(now - first_now) / divisor; TOD_usecs = (uint64_t)sample_timestamp; - TOD_secs = sample_TOD_secs + ((sample_TOD_usecs + TOD_usecs) / 1000000); + TOD_secs = (unsigned long)sample_TOD_secs + (unsigned long)((sample_TOD_usecs + TOD_usecs) / 1000000); sprintf(buf1, "%-19.19s interrupt latency = %.1fus [timestamp %.1f]", ctime(&TOD_secs), i_latency, sample_timestamp); } else { @@ -2380,9 +2359,9 @@ log_scheduler(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, int s_prior for (count = 0, kd_start = kd_beg; (kd_start >= (kd_buf *)my_buffer); kd_start--) { cpunum = CPU_NUMBER(kd_start); - + cmask |= ((uint64_t)1 << cpunum); - + if (cmask == cpu_mask) { if (count++ > 100) break; @@ -2409,7 +2388,7 @@ log_scheduler(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, int s_prior sample_timestamp = (double)(now - first_now) / divisor; TOD_usecs = (uint64_t)sample_timestamp; - TOD_secs = sample_TOD_secs + ((sample_TOD_usecs + TOD_usecs) / 1000000); + TOD_secs = (unsigned long)sample_TOD_secs + (unsigned long)((sample_TOD_usecs + TOD_usecs) / 1000000); sprintf(buf1, "%-19.19s priority = %d, scheduling latency = %.1fus [timestamp %.1f]", ctime(&TOD_secs), s_priority, s_latency, sample_timestamp); } else { @@ -2419,8 +2398,6 @@ log_scheduler(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, int s_prior log_range((kd_buf *)my_buffer, kd_start, kd_stop, kd_beg, buf1); } - - int check_for_scheduler_latency(int type, uintptr_t *thread, uint64_t now, kd_buf *kd, kd_buf **kd_start, int *priority, double *latency) { @@ -2466,7 +2443,7 @@ check_for_scheduler_latency(int type, uintptr_t *thread, uint64_t now, kd_buf *k if (s_thresh_hold && s_latency > s_thresh_hold) { s_exceeded_threshold++; - + if (log_fp) { *kd_start = trp->tr_entry; *priority = trp->tr_priority; @@ -2481,7 +2458,6 @@ check_for_scheduler_latency(int type, uintptr_t *thread, uint64_t now, kd_buf *k return found_latency; } - double handle_decrementer(kd_buf *kd, int cpunum) { @@ -2505,7 +2481,7 @@ handle_decrementer(kd_buf *kd, int cpunum) if (elapsed_usecs < 100) { il->i_usec_10_bins[elapsed_usecs/10]++; } - + if (elapsed_usecs < 1000) { il->i_usec_100_bins[elapsed_usecs/100]++; } else if (elapsed_usecs < 10000) { @@ -2534,8 +2510,6 @@ handle_decrementer(kd_buf *kd, int cpunum) return latency; } - - char * find_code(int type) { @@ -2548,7 +2522,6 @@ find_code(int type) return NULL; } - void init_code_file(void) { @@ -2584,11 +2557,11 @@ init_code_file(void) fclose(fp); } - void do_kernel_nm(void) { - int i, len; + int i; + size_t len; FILE *fp = NULL; char tmp_nm_file[128]; char tmpstr[1024]; @@ -2613,7 +2586,7 @@ do_kernel_nm(void) sprintf (tmpstr, "/usr/bin/nm -f -n -s __TEXT __text %s > %s", kernelpath, tmp_nm_file); system(tmpstr); - + /* * Parse the output from the nm command */ @@ -2695,10 +2668,10 @@ do_kernel_nm(void) */ for (i = 0; i < kern_sym_count; i++) { if (kern_sym_tbl[i].k_sym_name) { - printf ("[%d] %-16p %s\n", i, + printf ("[%d] %-16p %s\n", i, kern_sym_tbl[i].k_sym_addr, kern_sym_tbl[i].k_sym_name); } else { - printf ("[%d] %-16p %s\n", i, + printf ("[%d] %-16p %s\n", i, kern_sym_tbl[i].k_sym_addr, "No symbol name"); } } @@ -2709,7 +2682,7 @@ void pc_to_string(char *pcstring, uintptr_t pc, int max_len, int mode) { int ret; - int len; + size_t len; if (mode == USER_MODE) { sprintf(pcstring, "%-16lx [usermode addr]", pc); @@ -2738,7 +2711,7 @@ int binary_search(kern_sym_t *list, int low, int high, uintptr_t addr) { int mid; - + if (kern_sym_count == 0) { return -1; } @@ -2747,7 +2720,7 @@ binary_search(kern_sym_t *list, int low, int high, uintptr_t addr) return -1; /* failed */ } - if (low + 1 == high) { + if (low + 1 == high) { if ((uintptr_t)list[low].k_sym_addr <= addr && addr < (uintptr_t)list[high].k_sym_addr) { /* * We have a range match @@ -2761,7 +2734,7 @@ binary_search(kern_sym_t *list, int low, int high, uintptr_t addr) * Failed */ return -1; - } + } mid = (low + high) / 2; if (addr < (uintptr_t)list[mid].k_sym_addr) { @@ -2771,7 +2744,6 @@ binary_search(kern_sym_t *list, int low, int high, uintptr_t addr) return binary_search(list, mid, high, addr); } - void open_logfile(const char *path) { @@ -2786,7 +2758,6 @@ open_logfile(const char *path) } } - void open_rawfile(const char *path) { @@ -2801,12 +2772,11 @@ open_rawfile(const char *path) } } - void getdivisor(void) { mach_timebase_info_data_t info; - + (void)mach_timebase_info(&info); divisor = ((double)info.denom / (double)info.numer) * 1000; diff --git a/login.tproj/klogin.c b/login.tproj/klogin.c index 3426d9c..b9f0927 100644 --- a/login.tproj/klogin.c +++ b/login.tproj/klogin.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /*- @@ -81,9 +81,7 @@ extern char *krbtkfile_env; * 1 if Kerberos failed (try local password in login) */ int -klogin(pw, instance, localhost, password) - struct passwd *pw; - char *instance, *localhost, *password; +klogin(struct passwd *pw, char *instance, char *localhost, char *password) { int kerror; AUTH_DAT authdata; @@ -162,7 +160,7 @@ klogin(pw, instance, localhost, password) kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33); if (kerror == KDC_PR_UNKNOWN) { syslog(LOG_NOTICE, - "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?", + "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?", krb_err_txt[kerror], VERIFY_SERVICE, savehost); notickets = 0; return (0); diff --git a/login.tproj/login.c b/login.tproj/login.c index 1c30fe0..d82ee2a 100644 --- a/login.tproj/login.c +++ b/login.tproj/login.c @@ -672,12 +672,12 @@ main(int argc, char *argv[]) } #if defined(__APPLE__) && TARGET_OS_EMBEDDED - /* on embedded, allow a shell to live in /var/debug_mount/bin/sh */ -#define _PATH_DEBUGSHELL "/var/debug_mount/bin/sh" + /* on embedded, allow a shell to live in /private/var/personalized_debug/bin/sh */ +#define _PATH_DEBUGSHELL "/private/var/personalized_debug/bin/sh" if (stat(pwd->pw_shell, &st) != 0) { - if (stat(_PATH_DEBUGSHELL, &st) == 0) { - pwd->pw_shell = strdup(_PATH_DEBUGSHELL); - } + if (stat(_PATH_DEBUGSHELL, &st) == 0) { + pwd->pw_shell = strdup(_PATH_DEBUGSHELL); + } } #endif @@ -882,7 +882,7 @@ main(int argc, char *argv[]) (void)setgid(pwd->pw_gid); if (initgroups(username, pwd->pw_gid) == -1) syslog(LOG_ERR, "login: initgroups() failed"); - (void) setuid(rootlogin ? 0 : pwd->pw_uid); + (void) setuid(rootlogin ? 0 : pwd->pw_uid); #else /* !__APPLE__ */ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) { @@ -967,7 +967,7 @@ main(int argc, char *argv[]) break; } - kr = task_set_exception_ports(mts, EXC_MASK_CRASH, ep, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, flavor); + kr = task_set_exception_ports(mts, EXC_MASK_RESOURCE | EXC_MASK_GUARD | EXC_MASK_CORPSE_NOTIFY, ep, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, flavor); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "task_set_exception_ports() failure: %d", kr); break; @@ -1074,7 +1074,7 @@ auth_pam(int skip_auth) int rval; rval = 0; - + if (skip_auth == 0) { pam_err = pam_authenticate(pamh, pam_silent); @@ -1160,7 +1160,7 @@ auth_pam(int skip_auth) * Export any environment variables PAM modules may have set */ static void -export_pam_environment() +export_pam_environment(void) { char **pam_env; char **pp; @@ -1210,7 +1210,7 @@ export(const char *s) #endif /* USE_PAM */ static void -usage() +usage(void) { #ifdef __APPLE__ (void)fprintf(stderr, "usage: login [-pq] [-h hostname] [username]\n"); @@ -1225,7 +1225,7 @@ usage() * Prompt user and read login name from stdin. */ static char * -getloginname() +getloginname(void) { char *nbuf, *p; int ch; @@ -1348,7 +1348,7 @@ timedout(int signo __unused) #ifdef __APPLE__ #ifndef USE_PAM void -checknologin() +checknologin(void) { int fd, nchars; char tbuf[8192]; @@ -1366,8 +1366,7 @@ checknologin() #endif /* !USE_PAM */ void -dolastlog(quiet) - int quiet; +dolastlog(int quiet) { #ifdef USE_PAM if (quiet) @@ -1406,7 +1405,6 @@ dolastlog(quiet) static void badlogin(char *name) { - if (failures == 0) return; if (hflag) { @@ -1468,9 +1466,8 @@ pam_syslog(const char *msg) * Shut down PAM */ static void -pam_cleanup() +pam_cleanup(void) { - if (pamh != NULL) { if (pam_session_established) { pam_err = pam_close_session(pamh, 0); @@ -1496,7 +1493,6 @@ pam_cleanup() void bail(int sec, int eval) { - #ifdef USE_PAM pam_cleanup(); #endif /* USE_PAM */ diff --git a/login.tproj/login_audit.c b/login.tproj/login_audit.c index e9c13b1..0186637 100644 --- a/login.tproj/login_audit.c +++ b/login.tproj/login_audit.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. - * All rights reserved. + * Copyright (c) 2005-2016 Apple Inc. All rights reserved. * * @APPLE_BSD_LICENSE_HEADER_START@ * @@ -73,7 +72,7 @@ au_login_success(int fflag) long au_cond; /* Determine whether auditing is enabled. */ - if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { if (errno == ENOSYS) return; errx(1, "login: Could not determine audit condition"); @@ -102,7 +101,7 @@ au_login_success(int fflag) if (setaudit_addr(&auinfo, sizeof(auinfo)) < 0) err(1, "login: setaudit_addr failed"); - + char *session = NULL; asprintf(&session, "%x", auinfo.ai_asid); if (NULL == session) { @@ -110,7 +109,7 @@ au_login_success(int fflag) } setenv("SECURITYSESSIONID", session, 1); free(session); - + /* If we are not auditing, don't cut an audit record; just return. */ if (au_cond == AUC_NOAUDIT) return; @@ -146,7 +145,7 @@ au_login_fail(const char *errmsg, int na) pid_t pid = getpid(); /* If we are not auditing, don't cut an audit record; just return. */ - if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { if (errno == ENOSYS) return; errx(1, "login: Could not determine audit condition"); @@ -203,7 +202,7 @@ audit_logout(void) long au_cond; /* If we are not auditing, don't cut an audit record; just return. */ - if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { if (errno == ENOSYS) return; errx(1, "login: Could not determine audit condition"); diff --git a/lskq.tproj/common.h b/lskq.tproj/common.h index eb694f6..84cb434 100644 --- a/lskq.tproj/common.h +++ b/lskq.tproj/common.h @@ -34,7 +34,12 @@ #define KN_ACTIVE 0x01 #define KN_QUEUED 0x02 #define KN_DISABLED 0x04 +#define KN_DROPPING 0x08 +#define KN_USEWAIT 0x10 +#define KN_ATTACHING 0x20 #define KN_STAYQUEUED 0x40 +#define KN_DEFERDROP 0x80 +#define KN_TOUCH 0x100 /* diff --git a/lskq.tproj/lskq.1 b/lskq.tproj/lskq.1 index 3660a3a..ff79a92 100644 --- a/lskq.tproj/lskq.1 +++ b/lskq.tproj/lskq.1 @@ -26,6 +26,8 @@ Show kqueues for all running processes. Requires root. Verbose: show opaque user data and filter-specific extension fields. .It Fl e Ignore empty kqueues. +.It Fl r +Print fields in raw hex. .It Fl h Show help and exit. .El @@ -99,6 +101,8 @@ NOTE_REVOKE NOTE_EXIT .It Sy t NOTE_EXITSTATUS +.It Sy d +NOTE_EXIT_DETAIL .It Sy f NOTE_FORK .It Sy e @@ -119,6 +123,14 @@ NOTE_CRITICAL NOTE_BACKGROUND .It Sy l NOTE_LEEWAY +.Pp +.It EVFILT_USER: +.It Sy t +NOTE_TRIGGER +.It Sy a +NOTE_FFAND +.It Sy o +NOTE_FFOR .El .It flags kevent generic flags bitmask. @@ -131,12 +143,22 @@ EV_ENABLE EV_DISABLE .It Sy x EV_DELETE +.Pp .It Sy r EV_RECEIPT .It Sy 1 EV_ONESHOT .It Sy c EV_CLEAR +.It Sy s +EV_DISPATCH +.Pp +.It Sy u +EV_UDATA_SPECIFIC +.It Sy p +EV_FLAG0 (EV_POLL) +.It Sy b +EV_FLAG1 (EV_OOBAND) .It Sy o EV_EOF .It Sy e @@ -146,13 +168,24 @@ EV_ERROR kevent status bitmask. .Bl -tag -width xxxxxxx -compact .It Sy a -Event has triggered (KN_ACTIVE). +KN_ACTIVE (event has triggered) .It Sy q -Event has been added to the active list (KN_QUEUED). +KN_QUEUED (event has been added to the active list) .It Sy d -Event is disabled (KN_DISABLED). +KN_DISABLED .It Sy s -Event is marked as always-enqueued on the active list (KN_STAYQUEUED). +KN_STAYQUEUED (event is marked as always-enqueued on the active list) +.Pp +.It Sy o +KN_DROPPING +.It Sy u +KN_USEWAIT +.It Sy c +KN_ATTACHING +.It Sy f +KN_DEFERDROP +.It Sy t +KN_TOUCH .El .It data Filter-specific data. @@ -168,6 +201,10 @@ The output of is not an atomic snapshot of system state. In cases where .Nm lskq is able to detect an inconsistency, a warning will be printed. +.Pp +Not all flags are symbolicated. Use +.Fl r +(raw mode) to inspect additional flags. .Sh SEE ALSO .Xr kqueue 2 , .Xr kevent 2 , diff --git a/lskq.tproj/lskq.c b/lskq.tproj/lskq.c index 48782d8..6a3c74d 100644 --- a/lskq.tproj/lskq.c +++ b/lskq.tproj/lskq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Apple Inc. All rights reserved. + * Copyright (c) 2015-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -43,27 +43,32 @@ static int verbose; static int all_pids; static int ignore_empty; +static int raw; static char *self = "lskq"; static inline const char * filt_name(int16_t filt) { + static char unkn_filt[32]; int idx = -filt; if (idx >= 0 && idx < ARRAYLEN(filt_strs)) { return filt_strs[idx]; } else { - return ""; + snprintf(unkn_filt, sizeof(unkn_filt), "%i (?)", idx); + return unkn_filt; } } static inline const char * fdtype_str(uint32_t type) { + static char unkn_fdtype[32]; if (type < ARRAYLEN(fdtype_strs)) { return fdtype_strs[type]; } else { - return ""; + snprintf(unkn_fdtype, sizeof(unkn_fdtype), "%i (?)", type); + return unkn_fdtype; } } @@ -105,9 +110,10 @@ fflags_build(struct kevent_extinfo *info, char *str, int len) /* 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 ", + snprintf(str, len, "%c%c%c%c%c%c%c", (ff & NOTE_EXIT) ? 'x' : '-', (ff & NOTE_EXITSTATUS) ? 't' : '-', + (ff & NOTE_EXIT_DETAIL)? 'd' : '-', (ff & NOTE_FORK) ? 'f' : '-', (ff & NOTE_EXEC) ? 'e' : '-', (ff & NOTE_SIGNAL) ? 's' : '-', @@ -130,6 +136,15 @@ fflags_build(struct kevent_extinfo *info, char *str, int len) break; } + case EVFILT_USER: { + snprintf(str, len, "%c%c%c ", + (ff & NOTE_TRIGGER) ? 't' : '-', + (ff & NOTE_FFAND) ? 'a' : '-', + (ff & NOTE_FFOR) ? 'o' : '-' + ); + break; + } + default: snprintf(str, len, ""); break; @@ -189,6 +204,11 @@ shorten_procname(const char *proc, int width) static void print_ident(uint64_t ident, int16_t filter, int width) { + if (raw) { + printf("%#*llx ", width, ident); + return; + } + switch (filter) { case EVFILT_SIGNAL: @@ -197,7 +217,7 @@ print_ident(uint64_t ident, int16_t filter, int width) char num[128]; char out[128]; int numlen = sprintf(num, "%llu", ident); - int strwidth = width - numlen - 3; // add room for brackets and space + int strwidth = width - numlen - 1; // add room for a space if (filter == EVFILT_SIGNAL) { if (ident < ARRAYLEN(sig_strs)) { @@ -212,13 +232,12 @@ print_ident(uint64_t ident, int16_t filter, int width) if (strlen(procname) == 0) { procname = bsdinfo.pbi_comm; } - snprintf(str, strwidth + 1, "%s", - shorten_procname(procname, strwidth)); + snprintf(str, strwidth + 1, "%s", shorten_procname(procname, strwidth)); } } if (str[0] != '\0') { - snprintf(out, width + 1, "(%s) %s", str, num); + snprintf(out, width + 1, "%-*s %s", strwidth, str, num); } else { snprintf(out, width + 1, "%s", num); } @@ -227,6 +246,12 @@ print_ident(uint64_t ident, int16_t filter, int width) break; } + case EVFILT_MACHPORT: + case EVFILT_TIMER: + /* hex, to match lsmp */ + printf("%#*llx ", width, ident); + break; + default: printf("%*llu ", width, ident); break; @@ -244,30 +269,39 @@ print_kqfd(int kqfd, int width) } } +#define PROCNAME_WIDTH 20 + 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' : '-' - ); + if (raw) { + printf("%5u ", pid); + print_kqfd(kqfd, 5); + printf("%#10x ", state); + } else { + char tmpstr[PROCNAME_WIDTH+1]; + strlcpy(tmpstr, shorten_procname(procname, PROCNAME_WIDTH), PROCNAME_WIDTH+1); + printf("%-*s ", PROCNAME_WIDTH, 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]; + int maxknotes = 256; /* arbitrary starting point */ + int err = 0; + bool overflow = false; /* * get the basic kqueue info @@ -282,10 +316,20 @@ process_kqueue_on_fd(int pid, const char *procname, int kqfd, struct proc_fdinfo /* * get extended kqueue info */ - struct kevent_extinfo kqextinfo[MAXENTRIES]; + struct kevent_extinfo *kqextinfo = NULL; again: + if (!kqextinfo) { + kqextinfo = malloc(sizeof(struct kevent_extinfo) * maxknotes); + } + if (!kqextinfo) { + perror("failed allocating memory"); + err = errno; + goto out; + } + errno = 0; - nknotes = proc_pidfdinfo(pid, kqfd, PROC_PIDFDKQUEUE_EXTINFO, kqextinfo, sizeof(kqextinfo)); + nknotes = proc_pidfdinfo(pid, kqfd, PROC_PIDFDKQUEUE_EXTINFO, kqextinfo, + sizeof(struct kevent_extinfo) * maxknotes); if (nknotes <= 0) { if (errno == 0) { /* proc_*() can't distinguish between error and empty list */ @@ -293,71 +337,95 @@ process_kqueue_on_fd(int pid, const char *procname, int kqfd, struct proc_fdinfo goto again; } else if (errno == EBADF) { fprintf(stderr, "WARN: FD table changed (pid %i, kq %i)\n", pid, kqfd); - return 0; + goto out; } else { perror("failed to get extended kqueue info"); - return errno; + err = errno; + goto out; } } - if (nknotes > MAXENTRIES) { - fprintf(stderr, "WARN: truncated knote list (pid %i, kq %i)\n", pid, kqfd); - nknotes = MAXENTRIES; + if (nknotes > maxknotes) { + maxknotes = nknotes + 16; /* arbitrary safety margin */ + free(kqextinfo); + kqextinfo = NULL; + goto again; + } + + if (nknotes >= PROC_PIDFDKQUEUE_KNOTES_MAX) { + overflow = true; } 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", "-"); + printf("%18s \n", "-"); } - return 0; + goto out; } 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); + print_ident(info->kqext_kev.ident, info->kqext_kev.filter, 18); 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); + if (raw) { + printf("%#10x ", info->kqext_sfflags); + printf("%#10x ", info->kqext_kev.flags); + printf("%#10x ", info->kqext_status); + } else { + + /* 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 = fd_list_getfd(fdlist, nfds, (int)info->kqext_kev.ident); + 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%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_DISPATCH) ? 's' : '-', + + (flg & EV_UDATA_SPECIFIC) ? 'u' : '-', + (flg & EV_FLAG0) ? 'p' : '-', + (flg & EV_FLAG1) ? 'b' : '-', + (flg & EV_EOF) ? 'o' : '-', + (flg & EV_ERROR) ? 'e' : '-' + ); + + unsigned st = info->kqext_status; + printf("%c%c%c%c %c%c%c%c%c", + (st & KN_ACTIVE) ? 'a' : '-', + (st & KN_QUEUED) ? 'q' : '-', + (st & KN_DISABLED) ? 'd' : '-', + (st & KN_STAYQUEUED) ? 's' : '-', + + (st & KN_DROPPING) ? 'o' : '-', + (st & KN_USEWAIT) ? 'u' : '-', + (st & KN_ATTACHING) ? 'c' : '-', + (st & KN_DEFERDROP) ? 'f' : '-', + (st & KN_TOUCH) ? 't' : '-' + ); } - 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); @@ -377,17 +445,41 @@ process_kqueue_on_fd(int pid, const char *procname, int kqfd, struct proc_fdinfo printf("\n"); } - return 0; + if (overflow) { + printf(" ***** output truncated (>=%i knotes on kq %i, proc %i) *****\n", + nknotes, kqfd, pid); + } + + out: + if (kqextinfo) { + free(kqextinfo); + kqextinfo = NULL; + } + + return err; } static int process_pid(pid_t pid) { - int i, ret, nfds; + int i, nfds; + int ret = 0; + int maxfds = 256; /* arbitrary starting point */ + struct proc_fdinfo *fdlist = NULL; /* enumerate file descriptors */ - struct proc_fdinfo fdlist[MAXENTRIES]; - nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdlist, sizeof(fdlist)); + again: + if (!fdlist) { + fdlist = malloc(sizeof(struct proc_fdinfo) * maxfds); + } + if (!fdlist) { + perror("failed to allocate"); + ret = errno; + goto out; + } + + nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdlist, + sizeof(struct proc_fdinfo) * maxfds); if (nfds <= 0) { fprintf(stderr, "%s: failed enumerating file descriptors of process %i: %s", self, pid, strerror(errno)); @@ -395,13 +487,16 @@ process_pid(pid_t pid) fprintf(stderr, " (are you root?)"); } fprintf(stderr, "\n"); - return 1; + ret = errno; + goto out; } nfds /= sizeof(struct proc_fdinfo); - if (nfds > MAXENTRIES) { - fprintf(stderr, "WARN: truncated FD list (proc %i)\n", pid); - nfds = MAXENTRIES; + if (nfds >= maxfds) { + maxfds = nfds + 16; + free(fdlist); + fdlist = NULL; + goto again; } /* get bsdinfo for the process name */ @@ -409,7 +504,8 @@ process_pid(pid_t pid) ret = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &bsdinfo, sizeof(bsdinfo)); if (ret != sizeof(bsdinfo)) { perror("failed retrieving process info"); - return 1; + ret = -1; + goto out; } char *procname = bsdinfo.pbi_name; @@ -420,65 +516,153 @@ process_pid(pid_t pid) /* handle the special workq kq */ ret = process_kqueue_on_fd(pid, procname, -1, fdlist, nfds); if (ret) { - return ret; + goto out; } 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; + goto out; } } } - return 0; -} + out: + if (fdlist) { + free(fdlist); + fdlist = NULL; + } -#define MAXPIDS 4096 + return ret; +} static int process_all_pids(void) { - int i, npids, ret; - int pids[MAXPIDS]; + int i, npids; + int ret = 0; + int maxpids = 2048; + int *pids = NULL; + + again: + if (!pids) { + pids = malloc(sizeof(int) * maxpids); + } + if (!pids) { + perror("failed allocating pids[]"); + goto out; + } - npids = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids)); + errno = 0; + npids = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(int) * maxpids); if (npids <= 0) { - perror("failed enumerating pids"); - return 1; + if (errno == 0) { + /* empty pid list */ + } else if (errno == EAGAIN) { + goto again; + } else { + perror("failed enumerating pids"); + ret = errno; + goto out; + } } + npids /= sizeof(int); + if (npids >= maxpids) { + maxpids = npids + 16; + free(pids); + pids = NULL; + goto again; + } 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; + goto out; } } } - return 0; +out: + if (pids) { + free(pids); + pids = NULL; + } + + return ret; +} + +static void +cheatsheet(void) +{ + fprintf(stderr, "\nFilter-independent flags:\n\n\ +\033[1mcommand pid kq kqst ident filter fdtype fflags flags evst\033[0m\n\ +\033[1m-------------------- ----- ----- ---- ------------------ --------- -------- ------- --------------- ----------\033[0m\n\ + ┌ EV_UDATA_SPECIFIC\n\ + EV_DISPATCH ┐ │┌ EV_FLAG0 (EV_POLL)\n\ + EV_CLEAR ┐│ ││┌ EV_FLAG1 (EV_OOBAND)\n\ + EV_ONESHOT ┐││ │││┌ EV_EOF\n\ + EV_RECEIPT ┐│││ ││││┌ EV_ERROR\n\ + ││││ │││││\n\ +\033[1mlaunchd 1 4 ks- netbiosd 250 PROC ------- andx r1cs upboe aqds oucft\033[0m \n\ + │ │││ ││││ ││││ │││││\n\ + kqueue file descriptor ┘ │││ EV_ADD ┘│││ KN_ACTIVE ┘│││ ││││└ KN_TOUCH\n\ + KQ_SLEEP ┘││ EV_ENABLE ┘││ KN_QUEUED ┘││ │││└ KN_DEFERDROP\n\ + KQ_SEL ┘│ EV_DISABLE ┘│ KN_DISABLED ┘│ ││└ KN_ATTACHING\n\ + KEV32 (3) ┤ EV_DELETE ┘ KN_STAYQUEUED ┘ │└ KN_USEWAIT\n\ + KEV64 (6) ┤ └ KN_DROPPING\n\ + KEV_QOS (q) ┘\n\ + \n"); } static void usage(void) { - fprintf(stderr, "usage: %s [-vhe] [-a | -p ]\n", self); + fprintf(stderr, "usage: %s [-vher] [-a | -p ]\n", self); +} + +static void +print_header(void) +{ + if (raw) { + printf(" pid kq kqst ident filter fflags flags evst data"); + if (verbose) { + printf(" udata ext0 ext1 ext2 ext3 xflags"); + } + printf("\n"); + printf("----- ----- ---------- ------------------ --------- ---------- ---------- ---------- ------------------"); + + } else { + 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"); } -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { pid_t pid = 0; int opt; + setlinebuf(stdout); + if (argc > 0) { self = argv[0]; } - while ((opt = getopt(argc, argv, "eahvp:")) != -1) { + while ((opt = getopt(argc, argv, "eahvrp:")) != -1) { switch (opt) { case 'a': all_pids = 1; @@ -494,7 +678,11 @@ int main(int argc, char *argv[]) break; case 'h': usage(); + cheatsheet(); return 0; + case 'r': + raw = 1; + break; case '?': default: usage(); @@ -527,16 +715,7 @@ int main(int argc, char *argv[]) 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"); + print_header(); if (all_pids) { return process_all_pids(); @@ -546,4 +725,3 @@ int main(int argc, char *argv[]) return 0; } - diff --git a/lsmp.tproj/common.h b/lsmp.tproj/common.h index cfc29fd..ea07dc2 100644 --- a/lsmp.tproj/common.h +++ b/lsmp.tproj/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-20014 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,7 +37,6 @@ struct prog_configs { boolean_t verbose; int voucher_detail_length; pid_t pid; /* if user focusing only one pid */ - }; extern struct prog_configs lsmp_config; @@ -59,6 +58,18 @@ struct my_per_thread_info { char * voucher_detail; }; +/* kobject to name hash table declarations */ +#define K2N_TABLE_SIZE 256 + +struct k2n_table_node { + natural_t kobject; /* kobject referred to by the name -- the key into the table */ + ipc_info_name_t *info_name; /* info about the name that refers to the key kobject -- value of the table */ + struct k2n_table_node *next; +}; + +struct k2n_table_node *k2n_table_lookup_next(struct k2n_table_node *node, natural_t kobject); +struct k2n_table_node *k2n_table_lookup(struct k2n_table_node **table, natural_t kobject); + /* private structure to wrap up per-task info */ typedef struct my_per_task_info { task_t task; @@ -70,6 +81,7 @@ typedef struct my_per_task_info { ipc_info_tree_name_array_t tree; mach_msg_type_number_t treeCount; boolean_t valid; /* TRUE if all data is accurately collected */ + struct k2n_table_node *k2ntable[K2N_TABLE_SIZE]; char processName[PROC_NAME_LEN]; struct exc_port_info exceptionInfo; struct my_per_thread_info * threadInfos; /* dynamically allocated in collect_per_task_info */ @@ -133,7 +145,7 @@ typedef struct my_per_task_info { (flags & MACH_PORT_STATUS_FLAG_TASKPTR) ?"P":"-" -void show_recipe_detail(mach_voucher_attr_recipe_t recipe, char * voucher_outstr, uint32_t maxlen); +uint32_t show_recipe_detail(mach_voucher_attr_recipe_t recipe, char * voucher_outstr, uint32_t maxlen); char *copy_voucher_detail(mach_port_t task, mach_port_name_t voucher); /* mach port related functions */ @@ -156,6 +168,6 @@ kern_return_t get_taskinfo_of_receiver_by_send_right(ipc_info_name_t *sendright, kern_return_t get_ipc_info_from_lsmp_spaceinfo(mach_port_t port_name, ipc_info_name_t *out_sendright); /* basic util functions */ -void print_hex_data(char *outstr, size_t maxlen, char *prefix, char *desc, void *addr, int len); +uint32_t print_hex_data(char *outstr, size_t maxlen, char *prefix, char *desc, void *addr, int len); #endif diff --git a/lsmp.tproj/lsmp.c b/lsmp.tproj/lsmp.c index 4afa36d..c2e3330 100644 --- a/lsmp.tproj/lsmp.c +++ b/lsmp.tproj/lsmp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-20014 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -29,14 +29,12 @@ #include #include "common.h" - #if TARGET_OS_EMBEDDED #define TASK_FOR_PID_USAGE_MESG "\nPlease check your boot-args to ensure you have access to task_for_pid()." #else #define TASK_FOR_PID_USAGE_MESG "" #endif - struct prog_configs lsmp_config = { .show_all_tasks = FALSE, .show_voucher_details = FALSE, @@ -66,7 +64,7 @@ int main(int argc, char *argv[]) { char *progname = "lsmp"; int i, option = 0; lsmp_config.voucher_detail_length = 128; /* default values for config */ - + while((option = getopt(argc, argv, "hvalp:")) != -1) { switch(option) { case 'a': @@ -74,17 +72,17 @@ int main(int argc, char *argv[]) { lsmp_config.pid = 0; lsmp_config.show_all_tasks = 1; break; - + case 'l': /* for compatibility with sysdiagnose's usage of -all */ lsmp_config.voucher_detail_length = 1024; /* Fall through to 'v' */ - + case 'v': lsmp_config.show_voucher_details = TRUE; lsmp_config.verbose = TRUE; break; - + case 'p': lsmp_config.pid = atoi(optarg); if (lsmp_config.pid == 0) { @@ -92,28 +90,26 @@ int main(int argc, char *argv[]) { exit(1); } break; - + default: fprintf(stderr, "Unknown argument. \n"); /* Fall through to 'h' */ - + case 'h': print_usage(progname); break; - + } } argc -= optind; argv += optind; - - + /* if privileged, get the info for all tasks so we can match ports up */ if (geteuid() == 0) { processor_set_name_array_t psets; mach_msg_type_number_t psetCount; mach_port_t pset_priv; - - + ret = host_processor_sets(mach_host_self(), &psets, &psetCount); if (ret != KERN_SUCCESS) { fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret)); @@ -123,7 +119,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Assertion Failure: pset count greater than one (%d)\n", psetCount); exit(1); } - + /* convert the processor-set-name port to a privileged port */ ret = host_processor_set_priv(mach_host_self(), psets[0], &pset_priv); if (ret != KERN_SUCCESS) { @@ -132,7 +128,7 @@ int main(int argc, char *argv[]) { } mach_port_deallocate(mach_task_self(), psets[0]); vm_deallocate(mach_task_self(), (vm_address_t)psets, (vm_size_t)psetCount * sizeof(mach_port_t)); - + /* convert the processor-set-priv to a list of tasks for the processor set */ ret = processor_set_tasks(pset_priv, &tasks, &taskCount); if (ret != KERN_SUCCESS) { @@ -140,7 +136,7 @@ int main(int argc, char *argv[]) { exit(1); } mach_port_deallocate(mach_task_self(), pset_priv); - + /* swap my current instances port to be last to collect all threads and exception port info */ int myTaskPosition = -1; for (int i = 0; i < taskCount; i++) { @@ -169,24 +165,23 @@ int main(int argc, char *argv[]) { taskCount = 1; tasks = &aTask; } - + /* convert each task to structure of pointer for the task info */ psettaskinfo = allocate_taskinfo_memory(taskCount); - + for (i = 0; i < taskCount; i++) { ret = collect_per_task_info(&psettaskinfo[i], tasks[i]); if (ret != KERN_SUCCESS) { printf("Ignoring failure of mach_port_space_info() for task %d for '-all'\n", tasks[i]); continue; } - + if (psettaskinfo[i].pid == lsmp_config.pid) taskinfo = &psettaskinfo[i]; - + ret = KERN_SUCCESS; } - - + if (lsmp_config.show_all_tasks == FALSE) { if (taskinfo == NULL) { fprintf(stderr, "Failed to find task ipc information for pid %d\n", lsmp_config.pid); @@ -198,7 +193,6 @@ int main(int argc, char *argv[]) { printf("\n"); print_task_threads_special_ports(taskinfo); - } else { for (i=0; i < taskCount; i++) { if (psettaskinfo[i].valid != TRUE) @@ -215,12 +209,12 @@ int main(int argc, char *argv[]) { printf("\n\n"); } } - + if (taskCount > 1) { vm_deallocate(mach_task_self(), (vm_address_t)tasks, (vm_size_t)taskCount * sizeof(mach_port_t)); } - + deallocate_taskinfo_memory(psettaskinfo); - + return(0); } diff --git a/lsmp.tproj/port_details.c b/lsmp.tproj/port_details.c index 985fb89..fec26d7 100644 --- a/lsmp.tproj/port_details.c +++ b/lsmp.tproj/port_details.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-20014 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include "common.h" @@ -82,15 +83,16 @@ static uint8_t voucher_contents[voucher_contents_size]; static uint32_t safesize (int len){ - return (len > 0)? len : 0; + return (len > 0) ? len : 0; } -void show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, uint32_t maxlen) { +uint32_t show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, uint32_t maxlen) { uint32_t len = 0; len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "Key: %u, ", recipe->key)); len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Command: %u, ", recipe->command)); len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Previous voucher: 0x%x, ", recipe->previous_voucher)); len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Content size: %u\n", recipe->content_size)); + switch (recipe->key) { case MACH_VOUCHER_ATTR_KEY_ATM: len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "ATM ID: %llu\n", *(uint64_t *)(uintptr_t)recipe->content)); @@ -102,10 +104,11 @@ void show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "RESOURCE ACCOUNTING INFO: %s\n", (char *)recipe->content)); break; default: - print_hex_data(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX, "Recipe Contents", (void *)recipe->content, MIN(recipe->content_size, lsmp_config.voucher_detail_length)); + len += print_hex_data(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX, "Recipe Contents", (void *)recipe->content, MIN(recipe->content_size, lsmp_config.voucher_detail_length)); break; } + return len; } @@ -144,14 +147,14 @@ char * copy_voucher_detail(mach_port_t task, mach_port_name_t voucher) { while (recipe_size > used_size) { recipe = (mach_voucher_attr_recipe_t)&voucher_contents[used_size]; if (recipe->key) { - show_recipe_detail(recipe, &voucher_outstr[plen], detail_maxlen - plen); + plen += show_recipe_detail(recipe, &voucher_outstr[plen], detail_maxlen - plen); } used_size += sizeof(mach_voucher_attr_recipe_data_t) + recipe->content_size; } } else { plen += safesize(snprintf(&voucher_outstr[plen], detail_maxlen - plen, VOUCHER_DETAIL_PREFIX "Invalid voucher: 0x%x\n", voucher)); } - + return voucher_outstr; } @@ -159,7 +162,7 @@ void get_receive_port_context(task_t taskp, mach_port_name_t portname, mach_port if (context == NULL) { return; } - + kern_return_t ret; ret = mach_port_get_context(taskp, portname, context); if (ret != KERN_SUCCESS) { @@ -189,7 +192,7 @@ int get_recieve_port_status(task_t taskp, mach_port_name_t portname, mach_port_i mach_error_string(ret)); return -1; } - + return 0; } @@ -198,7 +201,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p int i, emptycount = 0, portsetcount = 0, sendcount = 0, receivecount = 0, sendoncecount = 0, deadcount = 0, dncount = 0, vouchercount = 0, pid; kern_return_t ret; pid_for_task(taskinfo->task, &pid); - + printf(" name ipc-object rights flags boost reqs recv send sonce oref qlimit msgcount context identifier type\n"); printf("--------- ---------- ---------- -------- ----- ---- ----- ----- ----- ---- ------ -------- ------------------ ----------- ------------\n"); for (i = 0; i < taskinfo->tableCount; i++) { @@ -209,18 +212,17 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p int sendrights = 0; unsigned int kotype = 0; vm_offset_t kobject = (vm_offset_t)0; - + /* skip empty slots in the table */ if ((taskinfo->table[i].iin_type & MACH_PORT_TYPE_ALL_RIGHTS) == 0) { emptycount++; continue; } - - + if (taskinfo->table[i].iin_type == MACH_PORT_TYPE_PORT_SET) { mach_port_name_array_t members; mach_msg_type_number_t membersCnt; - + ret = mach_port_get_set_status(taskinfo->task, taskinfo->table[i].iin_name, &members, &membersCnt); @@ -268,7 +270,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p } } } - + ret = vm_deallocate(mach_task_self(), (vm_address_t)members, membersCnt * sizeof(mach_port_name_t)); if (ret != KERN_SUCCESS) { @@ -279,22 +281,23 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p portsetcount++; continue; } - + if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_SEND) { send = TRUE; sendrights = taskinfo->table[i].iin_urefs; sendcount++; } - + if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_DNREQUEST) { dnreq = TRUE; dncount++; } - + if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_RECEIVE) { mach_port_status_t status; mach_port_info_ext_t info; mach_port_context_t context = (mach_port_context_t)0; + struct k2n_table_node *k2nnode; ret = get_recieve_port_status(taskinfo->task, taskinfo->table[i].iin_name, &info); get_receive_port_context(taskinfo->task, taskinfo->table[i].iin_name, &context); /* its ok to fail in fetching attributes */ @@ -319,26 +322,31 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p status.mps_msgcount, (uint64_t)context); receivecount++; - - + /* show other rights (in this and other tasks) for the port */ for (j = 0; j < taskCount; j++) { - 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) - continue; - - printf(" + %s -------- %s%s%s %5d <- 0x%08x (%d) %s\n", - (allTaskInfos[j].table[k].iin_type & MACH_PORT_TYPE_SEND_ONCE) ? - "send-once " : "send ", - (allTaskInfos[j].table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", - "-", - "-", - allTaskInfos[j].table[k].iin_urefs, - allTaskInfos[j].table[k].iin_name, - allTaskInfos[j].pid, - allTaskInfos[j].processName); + if (allTaskInfos[j].valid == FALSE) + continue; + + k2nnode = k2n_table_lookup(allTaskInfos[j].k2ntable, taskinfo->table[i].iin_object); + + while (k2nnode) { + if (k2nnode->info_name != &taskinfo->table[i]) { + assert(k2nnode->info_name->iin_object == taskinfo->table[i].iin_object); + + printf(" + %s -------- %s%s%s %5d <- 0x%08x (%d) %s\n", + (k2nnode->info_name->iin_type & MACH_PORT_TYPE_SEND_ONCE) ? + "send-once " : "send ", + (k2nnode->info_name->iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", + "-", + "-", + k2nnode->info_name->iin_urefs, + k2nnode->info_name->iin_name, + allTaskInfos[j].pid, + allTaskInfos[j].processName); + } + + k2nnode = k2n_table_lookup_next(k2nnode, k2nnode->info_name->iin_name); } } continue; @@ -352,12 +360,12 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p deadcount++; continue; } - + if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_SEND_ONCE) { sendonce = TRUE; sendoncecount++; } - + printf("0x%08x 0x%08x %s -------- %s%s%s %5.0d ", taskinfo->table[i].iin_name, taskinfo->table[i].iin_object, @@ -366,7 +374,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p "-", "-", (send) ? sendrights : 0); - + /* converting to kobjects is not always supported */ ret = mach_port_kernel_object(taskinfo->task, taskinfo->table[i].iin_name, @@ -382,7 +390,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p printf(" (%d) %s", _found_task->pid, _found_task->processName); } } - + printf("\n"); if (kotype == IKOT_VOUCHER) { vouchercount++; @@ -394,7 +402,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p } continue; } - + /* not kobject - find the receive right holder */ my_per_task_info_t *recv_holder_taskinfo; mach_port_name_t recv_name = MACH_PORT_NULL; @@ -417,7 +425,7 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p } else printf(" 0x00000000 (-) Unknown Process\n"); - + } printf("total = %d\n", taskinfo->tableCount + taskinfo->treeCount - emptycount); printf("SEND = %d\n", sendcount); @@ -426,41 +434,43 @@ void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_p printf("PORT_SET = %d\n", portsetcount); printf("DEAD_NAME = %d\n", deadcount); printf("DNREQUEST = %d\n", dncount); - printf("VOUCHERS = %d\n", vouchercount); - + printf("VOUCHERS = %d\n", vouchercount); + } -void print_hex_data(char *outstr, size_t maxlen, char *prefix, char *desc, void *addr, int len) { +uint32_t print_hex_data(char *outstr, size_t maxlen, char *prefix, char *desc, void *addr, int len) { int i; unsigned char buff[17]; unsigned char *pc = addr; uint32_t plen = 0; - + if (desc != NULL) plen += safesize(snprintf(&outstr[len], maxlen - plen, "%s%s:\n", prefix, desc)); - + for (i = 0; i < len; i++) { - + if ((i % 16) == 0) { if (i != 0) plen += safesize(snprintf(&outstr[len], maxlen - plen, " %s\n", buff)); - + plen += safesize(snprintf(&outstr[len], maxlen - plen, "%s %04x ", prefix, i)); } - + plen += safesize(snprintf(&outstr[len], maxlen - plen, " %02x", pc[i])); - + if ((pc[i] < 0x20) || (pc[i] > 0x7e)) buff[i % 16] = '.'; else buff[i % 16] = pc[i]; buff[(i % 16) + 1] = '\0'; } - + while ((i % 16) != 0) { plen += safesize(snprintf(&outstr[len], maxlen - plen, " ")); i++; } - + plen += safesize(snprintf(&outstr[len], maxlen - plen, " %s\n", buff)); + + return plen; } diff --git a/lsmp.tproj/task_details.c b/lsmp.tproj/task_details.c index bb490f2..aeaa160 100644 --- a/lsmp.tproj/task_details.c +++ b/lsmp.tproj/task_details.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-20014 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -27,9 +27,62 @@ #include #include #include +#include #include "common.h" +#pragma mark kobject to name hash table implementation + +#if (K2N_TABLE_SIZE & (K2N_TABLE_SIZE - 1) != 0) +#error K2N_TABLE_SIZE must be a power of two +#endif + +#define K2N_TABLE_MASK (K2N_TABLE_SIZE - 1) + +static uint32_t k2n_hash(natural_t kobject) { + return (uint64_t)kobject * 2654435761 >> 32; +} + +struct k2n_table_node *k2n_table_lookup_next(struct k2n_table_node *node, natural_t kobject) { + while (node) { + if (kobject == node->kobject) + return node; + + node = node->next; + } + + return NULL; +} + +struct k2n_table_node *k2n_table_lookup(struct k2n_table_node **table, natural_t kobject) { + uint32_t hv; + struct k2n_table_node *node; + + hv = k2n_hash(kobject); + + node = table[hv & K2N_TABLE_MASK]; + + return k2n_table_lookup_next(node, kobject); +} + +static void k2n_table_enter(struct k2n_table_node **table, natural_t kobject, ipc_info_name_t *info_name) { + uint32_t hv; + struct k2n_table_node *node; + + hv = k2n_hash(kobject); + + node = malloc(sizeof (struct k2n_table_node)); + assert(node); + + node->kobject = kobject; + node->info_name = info_name; + + node->next = table[hv & K2N_TABLE_MASK]; + table[hv & K2N_TABLE_MASK] = node; +} + +#pragma mark - + static my_per_task_info_t NOT_FOUND_TASK_INFO = { .task = NULL, .task_kobject = NULL, @@ -40,6 +93,7 @@ static my_per_task_info_t NOT_FOUND_TASK_INFO = { .tree = NULL, .treeCount = 0, .valid = FALSE, + .k2ntable = {0}, .processName = "Unknown", .exceptionInfo = {0}, .threadInfos = NULL, @@ -79,10 +133,11 @@ void deallocate_taskinfo_memory(my_per_task_info_t *data){ kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_t target_task) { + int i; kern_return_t ret = KERN_SUCCESS; unsigned int kotype = 0; vm_offset_t kobject = (vm_offset_t)0; - + taskinfo->task = target_task; pid_for_task(target_task, &taskinfo->pid); @@ -156,33 +211,36 @@ kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_t target_ vm_deallocate(mach_task_self(), threadPorts, taskinfo->threadCount * sizeof(thread_act_t)); threadPorts = NULL; - + ret = mach_port_space_info(target_task, &taskinfo->info, &taskinfo->table, &taskinfo->tableCount, &taskinfo->tree, &taskinfo->treeCount); - + if (ret != KERN_SUCCESS) { fprintf(stderr, "mach_port_space_info() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret)); taskinfo->pid = 0; return ret; } - + + bzero(taskinfo->k2ntable, K2N_TABLE_SIZE * sizeof (struct k2n_table_node *)); + for (i = 0; i < taskinfo->tableCount; i++) { + k2n_table_enter(taskinfo->k2ntable, taskinfo->table[i].iin_object, &taskinfo->table[i]); + } + proc_pid_to_name(taskinfo->pid, taskinfo->processName); ret = mach_port_kernel_object(mach_task_self(), taskinfo->task, &kotype, (unsigned *)&kobject); - + if (ret == KERN_SUCCESS && kotype == IKOT_TASK) { taskinfo->task_kobject = kobject; taskinfo->valid = TRUE; } - + return ret; } - - void get_exc_behavior_string(exception_behavior_t b, char *out_string, size_t len) { out_string[0]='\0'; - + if (b & MACH_EXCEPTION_CODES) strncat(out_string, "MACH +", len); switch (b & ~MACH_EXCEPTION_CODES) { @@ -203,7 +261,7 @@ void get_exc_behavior_string(exception_behavior_t b, char *out_string, size_t le void get_exc_mask_string(exception_mask_t m, char *out_string, size_t len) { out_string[0]='\0'; - + if (m & (1<exceptionInfo.masks[i], mask_string, 200); printf(" 0x%08x 0x%03x <%s> %s \n" , taskinfo->exceptionInfo.ports[i], taskinfo->exceptionInfo.flavors[i], behavior_string, mask_string); } - + } - + return KERN_SUCCESS; } @@ -263,19 +320,19 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) boolean_t header_required = TRUE; boolean_t newline_required = TRUE; struct my_per_thread_info * info = NULL; - + for (int i = 0; i < threadcount; i++) { info = &taskinfo->threadInfos[i]; if (header_required) { printf("Thread_KObject Thread-ID Port Description."); header_required = FALSE; } - + if (newline_required) { printf("\n"); } newline_required = TRUE; - + if (info->th_kobject != 0) { /* TODO: Should print tid and stuff */ printf("0x%08x ", info->th_kobject); @@ -359,22 +416,22 @@ my_per_task_info_t * get_taskinfo_by_kobject(natural_t kobj) { kern_return_t get_taskinfo_of_receiver_by_send_right(ipc_info_name_t *sendright, my_per_task_info_t **out_taskinfo, mach_port_name_t *out_recv_info) { - kern_return_t retval = KERN_FAILURE; - boolean_t found = FALSE; *out_taskinfo = &NOT_FOUND_TASK_INFO; - - for (int j = 0; j < global_taskcount && !found; j++) { - for (int k = 0; k < global_taskinfo[j].tableCount && !found; k++) { - if ((global_taskinfo[j].table[k].iin_type & MACH_PORT_TYPE_RECEIVE) && - global_taskinfo[j].table[k].iin_object == sendright->iin_object ) { + struct k2n_table_node *k2nnode; + + for (int j = 0; j < global_taskcount; j++) { + if ((k2nnode = k2n_table_lookup(global_taskinfo[j].k2ntable, sendright->iin_object))) { + assert(k2nnode->info_name->iin_object == sendright->iin_object); + + if (k2nnode->info_name->iin_type & MACH_PORT_TYPE_RECEIVE) { *out_taskinfo = &global_taskinfo[j]; - *out_recv_info = global_taskinfo[j].table[k].iin_name; - found = TRUE; - retval = KERN_SUCCESS; + *out_recv_info = k2nnode->info_name->iin_name; + return KERN_SUCCESS; } } } - return retval; + + return KERN_FAILURE; } kern_return_t get_ipc_info_from_lsmp_spaceinfo(mach_port_t port_name, ipc_info_name_t *out_sendright){ @@ -399,5 +456,3 @@ kern_return_t get_ipc_info_from_lsmp_spaceinfo(mach_port_t port_name, ipc_info_n return retval; } - - diff --git a/ltop.tproj/ltop.c b/ltop.tproj/ltop.c index 1149d31..9a4c90d 100644 --- a/ltop.tproj/ltop.c +++ b/ltop.tproj/ltop.c @@ -20,7 +20,7 @@ int diff_mode = 0; struct proc_list { int pid; int seen; - char command[32]; + char name[2 * MAXCOMLEN]; struct ledger *ledger; struct proc_list *next; }; @@ -41,7 +41,7 @@ struct ledger { struct ledger *ledgers = NULL; static void -get_template_info() +get_template_info(void) { void *buf; @@ -76,17 +76,17 @@ top: * needs to be followed by another call to get_template_info(). */ static void -dump_template_info() +dump_template_info(void) { int i, j; const char *group = NULL; - + printf("Resources being tracked:\n"); printf("\t%10s %15s %8s\n", "GROUP", "RESOURCE", "UNITS"); for (i = 0; i < entry_cnt; i++) { if (strlen(template[i].lti_name) == 0) continue; - + group = template[i].lti_group; for (j = i; j < entry_cnt; j++) { if (strcmp(template[j].lti_group, group)) @@ -99,7 +99,7 @@ dump_template_info() } static void -validate_group() +validate_group(void) { int i; @@ -115,7 +115,7 @@ validate_group() } static void -validate_resource() +validate_resource(void) { int i; @@ -145,16 +145,6 @@ get_kern_max_proc(void) return (max); } -static int -get_proc_kinfo(pid_t pid, struct kinfo_proc *kinfo) -{ - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - size_t len; - - len = sizeof(struct kinfo_proc); - return (sysctl(mib, 4, kinfo, &len, NULL, 0) < 0); -} - static struct ledger * ledger_find(struct ledger_info *li) { @@ -176,9 +166,8 @@ ledger_find(struct ledger_info *li) l->info = NULL; l->old_info = NULL; ledgers = l; - } + } return (l); - } static void @@ -194,7 +183,7 @@ ledger_update(pid_t pid, struct ledger *l) arg = (void *)(long)pid; lei = (struct ledger_entry_info *)malloc((size_t)(cnt * sizeof (*lei))); if (ledger(LEDGER_ENTRY_INFO, arg, (caddr_t)lei, (caddr_t)&cnt) < 0) { - perror("ledger_info() failed: "); + perror("ledger_info() failed: "); exit (1); } l->info = lei; @@ -206,7 +195,6 @@ get_proc_info(int pid) struct ledger_info li; struct ledger *ledgerp; struct proc_list *proc; - struct kinfo_proc kinfo; void *arg; if (pid == 0) @@ -226,7 +214,7 @@ get_proc_info(int pid) ledgerp = ledger_find(&li); ledger_update(pid, ledgerp); ledgerp->seen = 1; - + for (proc = procs; proc; proc = proc->next) if (proc->pid == pid) break; @@ -237,11 +225,8 @@ get_proc_info(int pid) exit (1); } - if (get_proc_kinfo(pid, &kinfo)) - strlcpy(proc->command, "Error", sizeof (proc->command)); - else - strlcpy(proc->command, kinfo.kp_proc.p_comm, - sizeof (proc->command)); + if (proc_name(pid, proc->name, sizeof (proc->name)) == 0) + strlcpy(proc->name, "Error", sizeof (proc->name)); proc->pid = pid; proc->ledger = ledgerp; @@ -261,7 +246,7 @@ pid_compare(const void *a, const void *b) } static void -get_all_info() +get_all_info(void) { pid_t *pids; int sz, cnt, i; @@ -297,15 +282,16 @@ get_all_info() static void print_num(int64_t num, int64_t delta) { - char suf = ' '; + char suf = '\0'; char posneg = ' '; + int numwidth; if (diff_mode) { num = delta; } if (num == LEDGER_LIMIT_INFINITY) { - printf("%10s ", "- "); + printf("%10s ", "-"); return; } @@ -319,31 +305,33 @@ print_num(int64_t num, int64_t delta) num /= 1000; suf = 'K'; } + posneg = (delta < 0) ? '-' : ((delta > 0) ? '+' : ' '); - if (suf == ' ') { - suf = posneg; - posneg = ' '; - } - printf("%8lld%c%c ", num, suf, posneg); + numwidth = 10; + + if (suf != '\0') + numwidth--; + + printf("%*lld%c%c ", numwidth, num, suf, posneg); } static void -dump_all_info() +dump_all_info(void) { struct ledger_entry_info *info, *old; struct proc_list *p; int line, i; int64_t d; - printf("\n%5s %10s %15s %10s %10s %10s %10s %10s\n", "PID", "COMMAND", + printf("\n%5s %32s %32s %10s %10s %10s %10s %10s \n", "PID", "COMMAND", "RESOURCE", "CREDITS", "DEBITS", "BALANCE", "LIMIT", "PERIOD"); for (p = procs; p; p = p->next) { if (p->seen == 0) continue; - - printf("%5d %10.10s ", p->pid, p->command); + + printf("%5d %32s ", p->pid, p->name); line = 0; info = p->ledger->info; @@ -358,9 +346,9 @@ dump_all_info() continue; if (line++) - printf(" "); - printf("%15s ", template[i].lti_name); - + printf("%5s %32s ", "", ""); + printf("%32s ", template[i].lti_name); + d = old ? info[i].lei_credit - old[i].lei_credit : 0; print_num(info[i].lei_credit, d); @@ -371,7 +359,7 @@ dump_all_info() print_num(info[i].lei_balance, d); if (info[i].lei_limit == LEDGER_LIMIT_INFINITY) { - printf("%10s %10s", "none", "- "); + printf("%10s %10s", "none", "-"); } else { print_num(info[i].lei_limit, 0); print_num(info[i].lei_refill_period, 0); @@ -379,14 +367,14 @@ dump_all_info() printf("\n"); } } - - if (line == 0) + + if (line == 0) exit (0); } static void -cleanup() -{ +cleanup(void) +{ struct proc_list *p, *pnext, *plast; struct ledger *l, *lnext, *llast; @@ -398,7 +386,7 @@ cleanup() plast->next = pnext; else procs = pnext; - + free(p); } else { p->seen = 0; @@ -416,7 +404,7 @@ cleanup() free(l->info); if (l->old_info) free(l->old_info); - free(l); + free(l); } else { l->seen = 0; free(l->old_info); @@ -432,7 +420,7 @@ cleanup() const char *pname; static void -usage() +usage(void) { printf("%s [-hdL] [-g group] [-p pid] [-r resource] [interval]\n", pname); } @@ -442,7 +430,7 @@ main(int argc, char **argv) { int c; int interval = 0; - + pname = argv[0]; while ((c = getopt(argc, argv, "g:hdLp:r:")) != -1) { @@ -458,12 +446,12 @@ main(int argc, char **argv) case 'h': usage(); exit(0); - + case 'L': get_template_info(); dump_template_info(); exit(0); - + case 'p': pid = atoi(optarg); break; diff --git a/makekey.tproj/makekey.8 b/makekey.tproj/makekey.8 deleted file mode 100644 index ee98c57..0000000 --- a/makekey.tproj/makekey.8 +++ /dev/null @@ -1,59 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)makekey.8 8.2 (Berkeley) 12/11/93 -.\" -.Dd December 11, 1993 -.Dt MAKEKEY 8 -.Os -.Sh NAME -.Nm makekey -.Nd make encrypted keys or passwords -.Sh SYNOPSIS -.Nm makekey -.Sh DESCRIPTION -.Nm Makekey -encrypts a key and salt which it reads from the standard input, -writing the result to the standard output. -The key and salt values are expected to be ten and two bytes, -respectively, in length. -See -.Xr crypt 3 -for more information on what characters the key and salt can contain -and how the encrypted value is calculated. -.Sh SEE ALSO -.Xr crypt 1 , -.Xr login 1 , -.Xr crypt 3 -.Sh HISTORY -A -.Nm makekey -command appeared in Version 7 AT&T UNIX. diff --git a/makekey.tproj/makekey.c b/makekey.tproj/makekey.c deleted file mode 100644 index ae9ca17..0000000 --- a/makekey.tproj/makekey.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 1999 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@ - */ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__unused static char copyright[] = -"@(#) Copyright (c) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -__unused static char sccsid[] = "@(#)makekey.c 8.1 (Berkeley) 6/4/93"; -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include - -static void get __P((char *, int)); - -int -main() -{ - int len; - char *r, key[9], salt[3]; - - get(key, sizeof(key) - 1); - get(salt, sizeof(salt) - 1); - len = strlen(r = crypt(key, salt)); - if (write(STDOUT_FILENO, r, len) != len) - err(1, "stdout"); - exit(0); -} - -static void -get(bp, len) - char *bp; - register int len; -{ - register int nr; - - bp[len] = '\0'; - if ((nr = read(STDIN_FILENO, bp, len)) == len) - return; - if (nr >= 0) - errno = EFTYPE; - err(1, "stdin"); -} diff --git a/mean.tproj/mean.c b/mean.tproj/mean.c index 4ea9255..87ecdc2 100644 --- a/mean.tproj/mean.c +++ b/mean.tproj/mean.c @@ -3,7 +3,7 @@ * mean - lower process priorities with more force than nice * * Created by Lucia Ballard on 9/16/09. - * Copyright 2009 Apple Inc. All rights reserved. + * Copyright 2009-2016 Apple Inc. All rights reserved. * */ @@ -19,8 +19,7 @@ void usage(void); - -void +void usage(void) { fprintf(stderr, "Usage: mean -[r|s|u] \n"); @@ -31,7 +30,7 @@ usage(void) exit(0); } -int +int main(int argc, char **argv) { int pid, err, i, ch; @@ -39,13 +38,13 @@ main(int argc, char **argv) mach_port_t task; thread_act_array_t threads; thread_precedence_policy_data_t policy; - + boolean_t do_high = 0, do_resume = 0, do_suspend = 0; boolean_t do_low = 1; - - if (argc < 2) + + if (argc < 2) usage(); - + while ((ch = getopt(argc, argv, "rsu")) != -1) switch (ch) { case 'u': @@ -63,16 +62,16 @@ main(int argc, char **argv) default: usage(); } - + argc -= optind; argv += optind; - + if (argc == 0) usage(); pid = atoi(*argv); - if (!pid) + if (!pid) usage(); - + err = task_for_pid(mach_task_self(), pid, &task); if (err) { fprintf(stderr, "Failed to get task port (%d)\n", err); @@ -93,9 +92,9 @@ main(int argc, char **argv) policy.importance = 0; for (i = 0; i < count; i++) { - err = thread_policy_set(threads[i], - THREAD_PRECEDENCE_POLICY, - (thread_policy_t) &policy, + err = thread_policy_set(threads[i], + THREAD_PRECEDENCE_POLICY, + (thread_policy_t) &policy, THREAD_PRECEDENCE_POLICY_COUNT); if (err) { fprintf(stderr, "Failed to set thread priority (%d)\n", err); @@ -103,10 +102,10 @@ main(int argc, char **argv) } } - printf("Process %d's threads set to %s priority.\n", pid, - (do_low ? "lowest" : "highest")); + printf("Process %d's threads set to %s priority.\n", pid, + (do_low ? "lowest" : "highest")); } - + if (do_suspend) { err = task_suspend(task); if (err) { @@ -114,9 +113,8 @@ main(int argc, char **argv) } else { printf("Process %d suspended.\n", pid); } - } - + if (do_resume) { err = task_resume(task); if (err) { @@ -128,4 +126,3 @@ main(int argc, char **argv) return 0; } - diff --git a/memory_pressure.tproj/memory_pressure.c b/memory_pressure.tproj/memory_pressure.c index cd614e5..eb72738 100644 --- a/memory_pressure.tproj/memory_pressure.c +++ b/memory_pressure.tproj/memory_pressure.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All rights reserved. + * Copyright (c) 2013-2016 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, @@ -17,7 +17,7 @@ * 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@ */ @@ -73,18 +73,18 @@ void print_vm_statistics(void); void munch_for_level(unsigned int, unsigned int); void munch_for_percentage(unsigned int, unsigned int, unsigned int); -static void +static void usage(void) { fprintf(stderr, "Usage: memory_pressure [options] []\n" " Allocate memory and wait forever.\n" " Options include:\n" - " -l - allocate memory until a low memory notification is received (warn OR critical)\n" + " -l - allocate memory until a low memory notification is received (warn OR critical)\n" " -p - allocate memory until percent free is this (or less)\n" " -s - how long to sleep between checking for a set percent level\n" " -w - don't allocate, just wait until percent free is this then exit\n" " -v - print VM statistics every sampling interval\n" - " -Q - reduces the tool's output\n" + " -Q - reduces the tool's output\n" " -S - simulate the system's memory pressure level without applying any real pressure\n" " \n" ); @@ -92,7 +92,7 @@ usage(void) } static unsigned int -read_sysctl_int(const char* name) +read_sysctl_int(const char* name) { unsigned int var; size_t var_size; @@ -108,7 +108,7 @@ read_sysctl_int(const char* name) } static int -get_percent_free(unsigned int* level) +get_percent_free(unsigned int* level) { int error; @@ -150,7 +150,7 @@ print_vm_statistics(void) printf("Pages speculative: %llu \n", (uint64_t) (vm_stat.speculative_count)); printf("Pages throttled: %llu \n", (uint64_t) (vm_stat.throttled_count)); printf("Pages wired down: %llu \n", (uint64_t) (vm_stat.wire_count)); - + printf("\nCompressor Stats:\n"); printf("Pages used by compressor: %llu \n", (uint64_t) (vm_stat.compressor_page_count)); printf("Pages decompressed: %llu \n", (uint64_t) (vm_stat.decompressions)); @@ -170,7 +170,6 @@ print_vm_statistics(void) } } - static int reached_or_bypassed_desired_result(void) { @@ -188,7 +187,7 @@ reached_or_bypassed_desired_result(void) } if (tool_mode == TOOL_MODE_FOR_PERCENT) { - + unsigned int current_percent = 0; get_percent_free(¤t_percent); @@ -213,18 +212,18 @@ reference_pages(int level) error = pthread_mutex_lock(&reference_pages_mutex); addr = range_start_addr; again: - while(start_referencing_pages == 0) { + while(start_referencing_pages == 0) { error = pthread_cond_wait(&reference_pages_condvar, &reference_pages_mutex); } start_allocing_pages = 0; pthread_mutex_unlock(&reference_pages_mutex); - + num_pages = 0; for(; addr < range_current_addr;) { - + char p; - + if (reached_or_bypassed_desired_result()) { //printf("stopped referencing after %d pages\n", num_pages); break; @@ -233,9 +232,9 @@ again: p = *(char*) addr; addr += PAGE_SIZE; num_pages++; - + } - + //if (num_pages) { // printf("Referenced %d\n", num_pages); //} @@ -243,16 +242,15 @@ again: start_referencing_pages = 0; start_allocing_pages = 1; - goto again; - + goto again; } static void -process_pages(int num_pages, int page_op) +process_pages(int num_pages, int page_op) { if (num_pages > 0) { - - int error = 0, i = 0; + + int error = 0, i = 0; size_t size = num_pages * PAGE_SIZE; if (page_op == PAGE_OP_ALLOC) { @@ -262,7 +260,7 @@ process_pages(int num_pages, int page_op) if (error == -1) { perror("Failed to lock memory!"); exit(-1); - } + } memset(range_current_addr, 0xFF, size); range_current_addr += size; @@ -278,7 +276,7 @@ process_pages(int num_pages, int page_op) pthread_mutex_unlock(&reference_pages_mutex); for (i=0; i < num_pages; i++) { - + if (reached_or_bypassed_desired_result()) { //printf("stopped faulting after %d pages\n", i); break; @@ -299,8 +297,8 @@ process_pages(int num_pages, int page_op) if (error == -1) { perror("Failed to unlock memory!"); exit(-1); - } - + } + error = madvise(range_current_addr, size, MADV_FREE); if (error == -1) { perror("Failed to madv_free memory!"); @@ -316,7 +314,7 @@ process_pages(int num_pages, int page_op) sleep(1); pthread_mutex_lock(&reference_pages_mutex); } - + error = madvise(range_current_addr, size, MADV_FREE); if (error == -1) { perror("Failed to madv_free memory!"); @@ -332,7 +330,7 @@ process_pages(int num_pages, int page_op) } void -munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) +munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) { unsigned int current_level = 0; @@ -352,7 +350,7 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) } get_percent_free(¤t_percent); - + if (print_vm_stats) { print_vm_stats_on_page_processing = TRUE; } @@ -367,7 +365,7 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) } else { desired_percent = 1; } - + pages_to_process = (desired_percent * phys_pages) / 100; page_op = PAGE_OP_ALLOC; @@ -381,7 +379,7 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) printf("."); fflush(stdout); } - + if (print_vm_stats_on_page_processing == TRUE) { print_vm_statistics(); } @@ -391,21 +389,21 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) current_level = read_sysctl_int("kern.memorystatus_vm_pressure_level"); if (current_level >= desired_level) { - + while(1) { current_level = read_sysctl_int("kern.memorystatus_vm_pressure_level"); if (current_level < desired_level) { break; } - + if (current_level > desired_level) { page_op = PAGE_OP_FREE; - + get_percent_free(¤t_percent); if (stabilized_percentage > current_percent) { pages_to_process = ((stabilized_percentage - current_percent) * phys_pages) / 100; - + if (previous_page_op != page_op) { printf("\nCMD: %s pages to go from %d to %d level", (page_op == PAGE_OP_ALLOC) ? "Allocating" : "Freeing", current_level, desired_level); previous_page_op = page_op; @@ -446,7 +444,7 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) get_percent_free(¤t_percent); //printf("Percent: %d Level: %d\n", current_percent, current_level); sleep(1); - + if (print_vm_stats) { print_vm_stats_on_page_processing = TRUE; } @@ -454,8 +452,8 @@ munch_for_level(unsigned int sleep_seconds, unsigned int print_vm_stats) } /* while */ } -void -munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, unsigned int print_vm_stats) +void +munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, unsigned int print_vm_stats) { int total_pages_allocated = 0; @@ -467,10 +465,10 @@ munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, boolean_t ok_to_print_stablity_message = TRUE; /* Allocate until memory level is hit. */ - + get_percent_free(¤t_percent); - /* + /* * "wait" mode doesn't alloc, it just waits and exits. This is used * while waiting for *other* processes to allocate memory. */ @@ -512,7 +510,7 @@ munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, process_pages(pages_to_process, page_op); ok_to_print_stablity_message = TRUE; } else { - + if (total_pages_allocated >= pages_to_process) { total_pages_allocated -= pages_to_process; process_pages(pages_to_process, page_op); @@ -526,7 +524,7 @@ munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, } } } - + //printf("kernel memorystatus: %d%% free, allocated %d pages total. Requested: %d\n", current_percent, total_pages_allocated, desired_percent); if (print_vm_stats) { print_vm_stats_on_page_processing = TRUE; @@ -545,21 +543,21 @@ munch_for_percentage(unsigned int sleep_seconds, unsigned int wait_percent_free, } if (print_vm_stats_on_page_processing) { - + print_vm_statistics(); if (print_vm_stats_on_page_processing == TRUE) { print_vm_stats_on_page_processing = FALSE; } } - + sleep(sleep_seconds); get_percent_free(¤t_percent); } /* while */ } -int +int main(int argc, char * const argv[]) { int opt; @@ -577,14 +575,14 @@ main(int argc, char * const argv[]) strlcpy(level, optarg, 9); if (strncasecmp(level, "normal", 6) == 0) { - desired_level = DISPATCH_MEMORYSTATUS_PRESSURE_NORMAL; + desired_level = DISPATCH_MEMORYPRESSURE_NORMAL; percent_for_level = 90; } else if (strncasecmp(level, "warn", 4) == 0) { - desired_level = DISPATCH_MEMORYSTATUS_PRESSURE_WARN; + desired_level = DISPATCH_MEMORYPRESSURE_WARN; percent_for_level = 60; } else if (strncasecmp(level, "critical", 8) == 0) { - desired_level = DISPATCH_MEMORYSTATUS_PRESSURE_CRITICAL; + desired_level = DISPATCH_MEMORYPRESSURE_CRITICAL; percent_for_level = 30; } else { @@ -603,7 +601,7 @@ main(int argc, char * const argv[]) break; case 'v': print_vm_stats = 1; - break; + break; case 'Q': quiet_mode_on = TRUE; break; @@ -623,22 +621,22 @@ main(int argc, char * const argv[]) phys_mem = read_sysctl_int("hw.physmem"); phys_pages = (unsigned int) (phys_mem / PAGE_SIZE); - printf("The system has %ld (%d pages with a page size of %d).\n", phys_mem, phys_pages, PAGE_SIZE); + printf("The system has %lu (%d pages with a page size of %d).\n", phys_mem, phys_pages, PAGE_SIZE); print_vm_statistics(); - + get_percent_free(¤t_percent); printf("System-wide memory free percentage: %d%%\n", current_percent); if (desired_percent == 0 && wait_percent_free == 0 && desired_level == 0) { return 0; } - + if (simulate_mode_on == TRUE) { - /* + /* We use the sysctl "kern.memorypressure_manual_trigger" for this mode. Here's a blurb: - + Supported behaviors when using the manual trigger tests. #define TEST_LOW_MEMORY_TRIGGER_ONE 1 most suitable app is notified @@ -655,7 +653,7 @@ main(int argc, char * const argv[]) */ #define TEST_LOW_MEMORY_PURGEABLE_TRIGGER_ALL 6 - + unsigned int var = 0; size_t var_size = 0; int error = 0; @@ -665,22 +663,22 @@ main(int argc, char * const argv[]) var = ((TEST_LOW_MEMORY_PURGEABLE_TRIGGER_ALL << 16) | desired_level); error = sysctlbyname("kern.memorypressure_manual_trigger", NULL, 0, &var, var_size); - + if(error) { perror("sysctl: kern.memorypressure_manual_trigger failed "); exit(-1); } - + printf("Waiting %d seconds before resetting system state\n", sleep_seconds); sleep(sleep_seconds); var_size = sizeof(var); - var = ((TEST_LOW_MEMORY_PURGEABLE_TRIGGER_ALL << 16) | DISPATCH_MEMORYSTATUS_PRESSURE_NORMAL); + var = ((TEST_LOW_MEMORY_PURGEABLE_TRIGGER_ALL << 16) | DISPATCH_MEMORYPRESSURE_NORMAL); error = sysctlbyname("kern.memorypressure_manual_trigger", NULL, 0, &var, var_size); - + if(error) { perror("sysctl: kern.memorypressure_manual_trigger failed "); exit(-1); @@ -690,7 +688,7 @@ main(int argc, char * const argv[]) } else { range_start_addr = mmap(NULL, MAX_RANGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); - + if (range_start_addr == MAP_FAILED) { perror("mmap failed"); } else { diff --git a/mkfile.tproj/mkfile.c b/mkfile.tproj/mkfile.c index 19eadb9..ac05c74 100644 --- a/mkfile.tproj/mkfile.c +++ b/mkfile.tproj/mkfile.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,19 +18,17 @@ * 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@ */ /* - * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved - * + * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved + * * HISTORY * 29-Aug-97 Daniel Wade (danielw) at Apple * Created. * - */ - - + */ #include #include @@ -43,37 +41,35 @@ #include #include -#define BF_SZ 512 /* Size of write chunks */ +#define BF_SZ 512 /* Size of write chunks */ extern void usage(char *, char *); extern void create_file(char *, quad_t, int, int); extern void err_rm(char *, char *); int -main (argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { char *b_num, *prog_name; char *options = "nv"; char c; off_t multiplier = 1; off_t file_size; - int len; + size_t len; int empty = 0; int verbose = 0; char* endptr = NULL; prog_name = argv[0]; /* Get program name */ - if (1 == argc) + if (1 == argc) usage(prog_name, options); /* Get options */ opterr=1; - - while ((c=getopt(argc, argv, options)) != EOF) - switch (c) { - case 'v': /* Turn on verbose setting */ + + while ((c=getopt(argc, argv, options)) != EOF) + switch (c) { + case 'v': /* Turn on verbose setting */ verbose = 1; break; case 'n': /* Create an empty file */ @@ -89,7 +85,7 @@ main (argc, argv) argv += optind; if (*argv == NULL) /* Is there a size given? */ usage(prog_name, options); - + b_num = *argv++; /* Size of file and byte multiplier */ len = strlen(b_num) - 1; @@ -102,7 +98,7 @@ main (argc, argv) case 'K': case 'k': multiplier = 1024; - break; + break; case 'M': case 'm': multiplier = 1024 * 1024; @@ -112,12 +108,12 @@ main (argc, argv) multiplier = 1024 * 1024 * 1024; break; default: - usage(prog_name, options); + usage(prog_name, options); } } - + if (*argv == NULL) /* Was a file name given? */ - usage(prog_name, options); + usage(prog_name, options); if ((file_size = strtoll(b_num, &endptr, 10)) == 0 && (*endptr != 0 && endptr != &b_num[len])) { @@ -130,21 +126,17 @@ main (argc, argv) } return (0); - } /* Create a file and make it empty (lseek) or zero'd */ -void -create_file(file_name, size, empty, verbose) - char *file_name; - quad_t size; - int empty; - int verbose; +void +create_file(char *file_name, quad_t size, int empty, int verbose) { char buff[BF_SZ]; - int fd, bytes_written = BF_SZ; + int fd; + ssize_t bytes_written = BF_SZ; quad_t i; mode_t mode = S_IRUSR | S_IWUSR; @@ -177,7 +169,7 @@ create_file(file_name, size, empty, verbose) err_rm (file_name, "Write Error"); } for (; i > 0; i -= bytes_written) { - bytes_written = write (fd, buff, i); + bytes_written = write (fd, buff, (size_t)i); if ( bytes_written == -1 ) err_rm (file_name, "Write Error"); } @@ -191,29 +183,22 @@ create_file(file_name, size, empty, verbose) if (verbose) (void)fprintf(stderr, "%s %qd bytes\n", file_name, size); - } /* On error remove the file */ void -err_rm(filename, msg) - char *filename; - char *msg; +err_rm(char *filename, char *msg) { unlink(filename); - err(1, "(%s removed) %s", filename, msg); + err(1, "(%s removed) %s", filename, msg); } - /* Print usage string */ -void -usage (prog_name, options) - char *prog_name; - char *options; +void +usage(char *prog_name, char *options) { - (void)fprintf(stderr, + (void)fprintf(stderr, "usage: %s [-%s] size[b|k|m|g] filename ...\n", prog_name, options); exit(1); - } diff --git a/msa/Action.hpp b/msa/Action.hpp deleted file mode 100644 index 43c48ab..0000000 --- a/msa/Action.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// Action.hpp -// msa -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef msa_Action_hpp -#define msa_Action_hpp - -class Action { - public: - virtual void execute(Globals& globals) = 0; -}; - -#endif diff --git a/msa/EventProcessing.hpp b/msa/EventProcessing.hpp deleted file mode 100644 index 7998683..0000000 --- a/msa/EventProcessing.hpp +++ /dev/null @@ -1,425 +0,0 @@ -// -// EventProcessing.hpp -// msa -// -// Created by James McIlree on 2/5/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef msa_EventProcessing_hpp -#define msa_EventProcessing_hpp - -template -bool is_mach_msg_interesting(const Machine& machine, const MachineMachMsg* mach_msg) -{ - // If this message is carrying importance, it is interesting. - if ((mach_msg->has_sender() && MACH_MSGH_BITS_RAISED_IMPORTANCE(mach_msg->send_msgh_bits())) || - (mach_msg->has_receiver() && MACH_MSGH_BITS_RAISED_IMPORTANCE(mach_msg->recv_msgh_bits()))) - return true; - - // If this message has a non-null voucher, it is interesting. - if ((mach_msg->has_sender() && !mach_msg->send_voucher()->is_null()) || - (mach_msg->has_receiver() && !mach_msg->recv_voucher()->is_null())) - return true; - - // If the message does NOT have a voucher, and the sender has a voucher set, it is interesting. - if (mach_msg->has_sender()) { - if (const MachineThread* sender_thread = machine.thread(mach_msg->send_tid(), mach_msg->send_time())) { - const MachineVoucher* sender_voucher = sender_thread->voucher(mach_msg->send_time()); - if (!sender_voucher->is_unset() && !sender_voucher->is_null()) { - return true; - } - } - } - - return false; -} - -template -void reset_task_data_on_exec_or_exit(const MachineProcess& process, - std::unordered_map& task_appnap_state, - std::unordered_map& task_requested_state, - std::unordered_map>& task_effective_state, - std::unordered_map>& task_boosts) -{ - ASSERT(!process.is_kernel(), "Kernel process should not ever exec or exit"); - ASSERT(process.pid() > 0, "Process with pid less than 1 exec'd ?"); - - if (pid_t pid = process.pid()) { - auto task_appnap_it = task_appnap_state.find(pid); - if (task_appnap_it != task_appnap_state.end()) { - task_appnap_state.erase(task_appnap_it); - } - - auto task_requested_it = task_requested_state.find(pid); - if (task_requested_it != task_requested_state.end()) { - task_requested_state.erase(task_requested_it); - } - - auto task_effective_it = task_effective_state.find(pid); - if (task_effective_it != task_effective_state.end()) { - task_effective_state.erase(task_effective_it); - } - - auto task_boosts_it = task_boosts.find(pid); - if (task_boosts_it != task_boosts.end()) { - task_boosts.erase(task_boosts_it); - } - } -} - -// From osfmk/kern/task.h -#define TASK_POLICY_INTERNAL 0x0 -#define TASK_POLICY_EXTERNAL 0x1 - -#define TASK_POLICY_TASK 0x4 -#define TASK_POLICY_THREAD 0x8 - -template -void process_events(Globals& globals, - const Machine& machine, - std::unordered_map& task_appnap_state, - std::unordered_map& task_requested_state, - std::unordered_map& thread_requested_state, - std::unordered_map>& task_effective_state, - std::unordered_map>& thread_effective_state, - std::unordered_map>& task_boosts) -{ - const KDEvent* events = machine.events(); - uintptr_t count = machine.event_count(); - - ASSERT(count, "Expected at least one event"); - - // - // Filtering thoughts... - // - // Two levels of filtering. - // - // 1) global supression of events that are "uninteresting". - // - // We filter on each event "class", with a keyword, so something like - // - // --lifecycle [ all | user | none ] ;; This is fork, exec, exit, thread-create, thread-exit - // --mach-msgs [ all | user | voucher | none ] ;; This is all mach msgs - // - // 2) targetted supression of events that are not related to a user focus. - // - // We filter by process name/pid - // - // --track [ pid | name ] - // - - PrintBuffer print_buffer(8192, 1024, globals.output_fd()); - - for (uintptr_t index=0; index < count; ++index) { - const KDEvent& event = events[index]; - - // - // Printing ... - // - - switch (event.dbg_cooked()) { - case TRACE_DATA_EXEC: { - bool should_print = false; - if (globals.lifecycle_filter() >= kLifecycleFilter::User) - should_print = true; - - if (should_print) - print_generic(print_buffer, globals, machine, event, index, "exec"); - - if (const MachineThread* exec_thread = machine.thread(event.tid(), event.timestamp())) { - reset_task_data_on_exec_or_exit(exec_thread->process(), task_appnap_state, task_requested_state, task_effective_state, task_boosts); - } - break; - } - - case TRACE_DATA_NEWTHREAD: { - bool should_print = false; - auto new_thread_tid = (typename SIZE::ptr_t)event.arg1(); - if (const MachineThread* new_thread = machine.thread(new_thread_tid, event.timestamp())) { - switch (globals.lifecycle_filter()) { - case kLifecycleFilter::None: - break; - case kLifecycleFilter::User: - if (!new_thread->process().is_kernel()) - should_print = true; - break; - case kLifecycleFilter::All: - should_print = true; - break; - } - - if (should_print) { - auto& new_process = new_thread->process(); - ASSERT(new_process.pid() == (pid_t)event.arg2(), "Pid does not match"); - if (new_process.timespan().location() == event.timestamp()) { - print_fork(print_buffer, globals, machine, event, index, new_process); - } - - // We're not printing the actual event data, but instead the exiting thread's data: - print_base(print_buffer, globals, event.timestamp(), new_thread, event, index, "thread-create", true); - } - } - break; - } - - case TRACEDBG_CODE(DBG_TRACE_DATA, TRACE_DATA_THREAD_TERMINATE): { - // This event may spawn two prints - // - // 1) thread termination - // 2) task termination - bool should_print = false; - typename SIZE::ptr_t terminated_tid = event.arg1(); - if (const MachineThread* terminated_thread = machine.thread(terminated_tid, event.timestamp())) { - switch (globals.lifecycle_filter()) { - case kLifecycleFilter::None: - break; - case kLifecycleFilter::User: - if (!terminated_thread->process().is_kernel()) - should_print = true; - break; - case kLifecycleFilter::All: - should_print = true; - break; - } - - if (should_print) { - // We're not printing the actual event data, but instead the exiting thread's data: - print_base(print_buffer, globals, event.timestamp(), terminated_thread, event, index, "thread-exit", true); - } - - // Was this the last thread in the process? (Do we also need to print a process exit?) - auto& terminated_process = terminated_thread->process(); - if (terminated_process.is_trace_terminated()) { - if (event.timestamp() >= terminated_process.exit_timestamp()) { - if (should_print) { - print_exit(print_buffer, globals, event, terminated_thread, index); - } - reset_task_data_on_exec_or_exit(terminated_process, task_appnap_state, task_requested_state, task_effective_state, task_boosts); - } - } - - auto thread_requested_it = thread_requested_state.find(terminated_tid); - if (thread_requested_it != thread_requested_state.end()) { - thread_requested_state.erase(thread_requested_it); - } - - auto thread_effective_it = thread_effective_state.find(terminated_tid); - if (thread_effective_it != thread_effective_state.end()) { - thread_effective_state.erase(thread_effective_it); - } - } else - ASSERT(false, "Failed to find exit thread"); - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_SEND): { - // trace event data is: - // kmsg_addr, msgh_bits, msgh_id, voucher_addr, - - // FIX ME! - // - // For now, we aren't recording mach msg's with endpoints in - // the kernel. If we don't find a mach msg, assume its a kernel - // msg. - if (const MachineMachMsg* mach_msg = machine.mach_msg(index)) { - if (is_mach_msg_interesting(machine, mach_msg)) { - print_mach_msg(print_buffer, globals, machine, event, index, true, mach_msg); - } - } - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV): - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV_VOUCHER_REFUSED): { - // trace event data is - // kmsg_addr, msgh_bits, msgh_id, recv_voucher_addr - - // FIX ME! - // - // For now, we aren't recording mach msg's with endpoints in - // the kernel. If we don't find a mach msg, assume its a kernel - // msg. - if (const MachineMachMsg* mach_msg = machine.mach_msg(index)) { - if (is_mach_msg_interesting(machine, mach_msg)) { - print_mach_msg(print_buffer, globals, machine, event, index, false, mach_msg); - } - } - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_CREATE): { - // trace event data is - // voucher address, voucher table size, system voucher count, voucher content bytes - - if (auto voucher = machine.voucher(event.arg1(), event.timestamp())) { - print_voucher(print_buffer, globals, machine, event, index, "voucher_create", voucher, true); - - if (voucher->has_valid_contents()) { - print_voucher_contents(print_buffer, globals, machine, event, index, voucher); - } - } else { - ASSERT(false, "Failed to find voucher"); - } - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_DESTROY): { - // trace event data is - // voucher address, 0, system voucher count, 0 - if (auto voucher = machine.voucher(event.arg1(), event.timestamp())) { - print_voucher(print_buffer, globals, machine, event, index, "voucher_destroy", voucher, false); - } else { - ASSERT(false, "Failed to find voucher"); - } - break; - } - - case MACHDBG_CODE(DBG_MACH_IPC, MACH_THREAD_SET_VOUCHER): { - print_generic(print_buffer, globals, machine, event, index, "thread_adopt_voucher"); - break; - } - - case IMPORTANCE_CODE(IMP_ASSERTION, IMP_EXTERN): - print_importance_assert(print_buffer, globals, machine, event, index, "externalize_importance", task_boosts); - break; - - case IMPORTANCE_CODE(IMP_ASSERTION, IMP_HOLD | TASK_POLICY_EXTERNAL): - case IMPORTANCE_CODE(IMP_ASSERTION, IMP_HOLD | TASK_POLICY_INTERNAL): - print_importance_assert(print_buffer, globals, machine, event, index, "importance_hold", task_boosts); - break; - - case IMPORTANCE_CODE(IMP_ASSERTION, IMP_DROP | TASK_POLICY_EXTERNAL): - case IMPORTANCE_CODE(IMP_ASSERTION, IMP_DROP | TASK_POLICY_INTERNAL): - print_importance_assert(print_buffer, globals, machine, event, index, "importance_drop", task_boosts); - break; - - case IMPORTANCE_CODE(IMP_WATCHPORT, 0): - // trace data is - // proc_selfpid(), pid, boost, released_pid, 0); - if (event.arg3() > 0) { - print_watchport_importance_transfer(print_buffer, globals, machine, event, index); - } - break; - - case IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, 0): - case IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, 1): - // Trace data is - // self_pid, audit_token_pid_from_task(task), trequested_0(task, NULL), trequested_1(task, NULL) - print_appnap(print_buffer, globals, machine, event, index, (bool)event.dbg_code(), task_appnap_state, task_requested_state); - break; - - case IMPORTANCE_CODE(IMP_BOOST, IMP_BOOSTED): - case IMPORTANCE_CODE(IMP_BOOST, IMP_UNBOOSTED): - // trace data is - // proc_selfpid(), audit_token_pid_from_task(task), trequested_0(task, NULL), trequested_1(task, NULL) - if (event.is_func_start()) { - print_boost(print_buffer, globals, machine, event, index, (pid_t)event.arg2(), (event.dbg_code() == IMP_BOOSTED)); - } - break; - - // - // IMP_TASK_APPTYPE trace args are: - // - // start: - // target_pid, trequested_0, trequested_1, apptype - // end: - // target_pid, trequested_0, trequested_1, is_importance_receiver - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_NONE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_INTERACTIVE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_STANDARD): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_ADAPTIVE): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_DAEMON_BACKGROUND): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_APP_DEFAULT): - case IMPORTANCE_CODE(IMP_TASK_APPTYPE, TASK_APPTYPE_APP_TAL): - if (event.is_func_end()) { - print_importance_apptype(print_buffer, globals, machine, event, index); - } - // FIX ME, not handling trequested status. - // - // process_trequested_task(print_buffer, globals, machine, event, index, (pid_t)event.arg1(), event.arg2(), event.arg3(), task_requested_policies); - break; - - - case IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_TASK)): - // trace data is - // targetpid, teffective_0(task, NULL), teffective_1(task, NULL), tpriority(task, NULL) - print_importance_update_task(print_buffer, globals, machine, event, index, "imp_update_task_create", task_effective_state); - break; - - case IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_THREAD)): - // trace data is - // targettid, teffective_0(task, thread), teffective_1(task, thread), tpriority(thread, NULL) - print_importance_update_thread(print_buffer, globals, machine, event, index, "imp_update_thread_create", thread_effective_state); - break; - - case IMPORTANCE_CODE(IMP_UPDATE, TASK_POLICY_TASK): - // trace data is - // targetpid, teffective_0(task, NULL), teffective_1(task, NULL), tpriority(task, THREAD_NULL) - print_importance_update_task(print_buffer, globals, machine, event, index, "imp_update_task", task_effective_state); - break; - - case IMPORTANCE_CODE(IMP_UPDATE, TASK_POLICY_THREAD): - // trace data is - // targettid, teffective_0(task, thread), teffective_1(task, thread), tpriority(task, THREAD_NULL) - print_importance_update_thread(print_buffer, globals, machine, event, index, "imp_update_thread", thread_effective_state); - break; - - case IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND): - // trace data is - // current_pid, sender_pid, imp_msgh_id, (bool)importance_cleared - - // NOTE! Only end events carry "importance cleared" - if (event.is_func_end() && (event.arg4() != 0)) { - print_importance_send_failed(print_buffer, globals, machine, event, index); - } - break; - - case IMPORTANCE_CODE(IMP_MSG, IMP_MSG_DELV): { - // trace data is - // sending_pid, task_pid /* recv_pid?? */, msgh_id, impresult - // - // for impresult: - // - // 0: BOOST NOT APPLIED - // 1: BOOST EXTERNALIZED - // 2: LIVE_IMPORTANCE_LINKAGE! - print_impdelv(print_buffer, globals, machine, event, index, (pid_t)event.arg1(), (uint32_t)event.arg4()); - break; - } - - default: - if (event.dbg_class() == DBG_IMPORTANCE) { - // - // Every task policy set trace code carries "trequested" data, we would like to grab them all. - // - // This subclass spans the range of 0x20 through 0x3F - // - - uint32_t subclass = event.dbg_subclass(); - if (subclass >= 0x20 && subclass <= 0x3F) { - // Trace event data is - // targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), value - - bool is_task_event = (event.dbg_code() & TASK_POLICY_TASK) > 0; - - // Should not be both a task and thread event. - ASSERT(is_task_event != (event.dbg_code() & TASK_POLICY_THREAD), "BEWM!"); - - if (is_task_event) { - // FIX ME, not handling trequested status. - // - // process_trequested_task(print_buffer, globals, machine, event, index, (pid_t)event.arg1(), event.arg2(), event.arg3(), task_requested_policies); - } else { - // FIX ME, not handling trequested status. - // - // process_trequested_thread(print_buffer, globals, machine, event, index, event.arg1(), event.arg2(), event.arg3(), task_requested_policies, thread_requested_policies); - } - } - } - break; - } - } -} - -#endif diff --git a/msa/EventRingBuffer.hpp b/msa/EventRingBuffer.hpp deleted file mode 100644 index ebae7f2..0000000 --- a/msa/EventRingBuffer.hpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// EventRingBuffer.hpp -// msa -// -// Created by James McIlree on 10/8/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __msa__EventRingBuffer__ -#define __msa__EventRingBuffer__ - -template -class EventRingBuffer { - protected: - const Globals& _globals; // Used for printing the ringbuffer - std::vector> _events; - std::size_t _head; - std::size_t _tail; - - public: - EventRingBuffer(const Globals& globals, std::size_t size); - - // Returns: - // - // events, capacity, number_read - std::tuple*, std::size_t, std::size_t> read(); - - void print() const; - void print_event_index(std::size_t index) const; - void print_all_events() const; - void print_last_events(std::size_t lastN) const; - void print_from_timestamp(uint64_t timestamp) const; -}; - -template -EventRingBuffer::EventRingBuffer(const Globals& globals, std::size_t size) : - _globals(globals), - _events(size), - _head(0), - _tail(0) -{ - ASSERT(size, "Sanity"); - - // Force all pages into memory so the first bazillion - // trace entries aren't VM_FAULT... - bzero(_events.data(), _events.size() * sizeof(KDEvent)); -} - -template -std::tuple*, std::size_t, std::size_t> EventRingBuffer::read() { - std::size_t modulo_index = _tail % _events.size(); - std::size_t count, capacity = _events.size() - modulo_index; - KDEvent* events = &_events.data()[modulo_index]; - - if ((count = KDBG::read(events, capacity * sizeof(KDEvent)))) { - // Update head/tail as soon as we have added data. - _tail += count; - if (_tail - _head > _events.size()) { - _head += count; - } - } - - return std::make_tuple(events, count, capacity); -} - -#if 0 - -template -void EventRingBuffer::print() const { - printf("%zu events in buffer [%zu -> %zu)\n", _tail - _head, _head, _tail); -} - -template -void EventRingBuffer::print_event_index(std::size_t index) const { - const KDEvent& event = _events[index % _events.size()]; - - const char* type = event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---"); - auto trace_code_it = _globals.trace_codes().find(event.dbg_cooked()); - - if (trace_code_it == _globals.trace_codes().end()) { - printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %x, cpu=%u }\n", index, event.timestamp().value(), - (uint64_t)event.arg1(), (uint64_t)event.arg2(), (uint64_t)event.arg3(), (uint64_t)event.arg4(), (uint64_t)event.tid(), type, event.dbg_cooked(), event.cpu()); - } else { - printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %s, cpu=%u }\n", index, event.timestamp().value(), - (uint64_t)event.arg1(), (uint64_t)event.arg2(), (uint64_t)event.arg3(), (uint64_t)event.arg4(), (uint64_t)event.tid(), type, trace_code_it->second.c_str(), event.cpu()); - } -} - -template -void EventRingBuffer::print_all_events() const { - std::size_t begin = _head; - while (begin < _tail) { - print_event_index(begin++); - } -} - -template -void EventRingBuffer::print_last_events(std::size_t lastN) const { - std::size_t length = std::min(lastN, _tail - _head); - std::size_t begin = _tail - length; - ASSERT(begin <= _tail, "Sanity"); - while (begin < _tail) { - print_event_index(begin++); - } -} - -template -void EventRingBuffer::print_from_timestamp(uint64_t t) const { - std::size_t begin = _head; - while (begin < _tail) { - const KDEvent& event = _events[begin % _events.size()]; - if (event.timestamp() >= t) - break; - begin++; - } - - while (begin < _tail) { - print_event_index(begin++); - } -} - -void PrintEventRingBuffer() { - // uint64_t _timestamp; - // uint64_t _arg1; - // uint64_t _arg2; - // uint64_t _arg3; - // uint64_t _arg4; - // uint64_t _thread; - // uint32_t _debugid; - // uint32_t _cpuid; - - const KDEvent* events = (const KDEvent*)g_rb; - for (std::size_t i=ring_buffer_head_index; i& event = events[i % g_rb_size]; - printf("event[%ld] { timestamp=%llx, ", i, event.timestamp().value()); - printf("arg1=%llx, ", event.arg1()); - printf("arg2=%llx, ", event.arg2()); - printf("arg3=%llx, ", event.arg3()); - printf("arg4=%llx, ", event.arg4()); - printf("tid=%llx, ", event.tid()); - const char* type = event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---"); - auto trace_code_it = gglobals->trace_codes().find(event.dbg_cooked()); - if (trace_code_it == gglobals->trace_codes().end()) { - printf("%4s %x, ", type, event.dbg_cooked()); - } else { - printf("%4s %s, ", type, trace_code_it->second.c_str()); - } - printf("cpu=%u }\n", event.cpu()); - } - printf("%lu\n", ring_buffer_tail_index - ring_buffer_head_index); -} -#endif - -#endif /* defined(__staintracker__EventRingBuffer__) */ diff --git a/msa/Globals.cpp b/msa/Globals.cpp deleted file mode 100644 index 8d3fd08..0000000 --- a/msa/Globals.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// MachineGlobals.cpp -// msa -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "global.h" - -Globals::Globals() : - _cpu_count(0), - _iop_count(0), - _kernel_size(Kernel::is_64_bit() ? KernelSize::k64 : KernelSize::k32), - _live_update_interval("100ms"), - _is_cpu_count_set(false), - _is_iop_count_set(false), - _is_kernel_size_set(false), - _is_timebase_set(false), - _beginning_of_time(0), - _should_print_mach_absolute_timestamps(false), - _should_print_event_index(false), - _is_verbose(false), - _should_presort_events(false), - _should_zero_base_timestamps(true), - _should_trace_voucher_contents(true), - _lifecycle_filter(kLifecycleFilter::User), - _mach_msg_filter(kMachMsgFilter::Voucher) -{ - // Default to the current machine's values - mach_timebase_info(&_timebase_info); - - for (auto& entry : KDBG::cpumap()) { - if (entry.is_iop()) - _iop_count++; - else - _cpu_count++; - } - - // If we are unable to get a cpumap, - // fallback on the current # of cpus - if (_cpu_count == 0) { - _cpu_count = Kernel::active_cpu_count(); - _iop_count = 0; - } - - // This is only used as is for live tracing or capturing a trace, - // so we want to use the current # of cpus. - _trace_buffer_size = 250000 * _cpu_count; -} - -static AbsTime parse_time(const char* arg, mach_timebase_info_data_t timebase_info) { - - char* units; - uint64_t value = strtoull(arg, &units, 0); - - // Unspecified units are treated as seconds - if (*units == 0 || strcmp(units, "s") == 0) { - return NanoTime(value * NANOSECONDS_PER_SECOND).abs_time(timebase_info); - } - - if (strcmp(units, "ms") == 0) - return NanoTime(value * NANOSECONDS_PER_MILLISECOND).abs_time(timebase_info); - - if (strcmp(units, "us") == 0) - return NanoTime(value * NANOSECONDS_PER_MICROSECOND).abs_time(timebase_info); - - if (strcmp(units, "ns") == 0) - return NanoTime(value).abs_time(timebase_info); - - if (strcmp(units, "mabs") == 0) { - return AbsTime(value); - } - - usage("Unable to parse units on time value"); -} - -AbsTime Globals::live_update_interval() const { - return parse_time(_live_update_interval.c_str(), _timebase_info); -} diff --git a/msa/Globals.hpp b/msa/Globals.hpp deleted file mode 100644 index 68e007e..0000000 --- a/msa/Globals.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// Globals.hpp -// msa -// -// Created by James McIlree on 4/17/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef msa_Globals_hpp -#define msa_Globals_hpp - -// -// These are "global" values that control parsing and printing behavior. -// - -enum class kLifecycleFilter : std::uint32_t { - None = 0, - User, - All -}; - -enum class kMachMsgFilter : std::uint32_t { - None = 0, - User, - Voucher, - All -}; - -class Globals { - protected: - // Default/unknown parsing values - uint32_t _cpu_count; - uint32_t _iop_count; - KernelSize _kernel_size; - std::string _live_update_interval; - - bool _is_cpu_count_set; - bool _is_iop_count_set; - bool _is_kernel_size_set; - bool _is_timebase_set; - - // Output, printing related. - AbsTime _beginning_of_time; - mach_timebase_info_data_t _timebase_info; - FileDescriptor _output_fd; - bool _should_print_mach_absolute_timestamps; - bool _should_print_event_index; - bool _is_verbose; - bool _should_presort_events; - bool _should_zero_base_timestamps; - bool _should_trace_voucher_contents; - uint32_t _trace_buffer_size; - kLifecycleFilter _lifecycle_filter; - kMachMsgFilter _mach_msg_filter; - - - public: - Globals(); - - uint32_t cpu_count() const { return _cpu_count; } - void set_cpu_count(uint32_t num) { _cpu_count = num; _is_cpu_count_set = true; } - bool is_cpu_count_set() const { return _is_cpu_count_set; } - - uint32_t iop_count() const { return _iop_count; } - void set_iop_count(uint32_t num) { _iop_count = num; _is_iop_count_set = true; } - bool is_iop_count_set() const { return _is_iop_count_set; } - - KernelSize kernel_size() const { return _kernel_size; } - void set_kernel_size(KernelSize size) { _kernel_size = size; _is_kernel_size_set = true; } - bool is_kernel_size_set() const { return _is_kernel_size_set; } - - AbsTime beginning_of_time() const { return _beginning_of_time; } - void set_beginning_of_time(AbsTime t) { _beginning_of_time = t; } - - mach_timebase_info_data_t timebase() const { return _timebase_info; } - void set_timebase(mach_timebase_info_data_t timebase, bool is_user_set) { _timebase_info = timebase; if (is_user_set) _is_timebase_set = true; } - bool is_timebase_set() const { return _is_timebase_set; } - - int output_fd() const { return _output_fd.is_open() ? (int)_output_fd : STDOUT_FILENO; } - - // Okay, this method caused enough pain to make the final resolution worth a comment. - // - // http://thbecker.net/articles/rvalue_references/section_05.html - // - // Things that are declared as rvalue reference can be lvalues or rvalues. - // The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue. - // - // In this case, you cannot call set_output_fd with an lvalue, but fd is STILL an lvalue. - // We must still explicitly use std::move on fd! - void set_output_fd(FileDescriptor&& fd) { _output_fd = std::move(fd); } - - bool should_print_mach_absolute_timestamps() const { return _should_print_mach_absolute_timestamps; } - void set_should_print_mach_absolute_timestamps(bool value) { _should_print_mach_absolute_timestamps = value; } - - bool should_print_event_index() const { return _should_print_event_index; } - void set_should_print_event_index(bool value) { _should_print_event_index = value; } - - bool is_verbose() const { return _is_verbose; } - void set_is_verbose(bool value) { _is_verbose = value; } - - bool should_presort_events() const { return _should_presort_events; } - void set_should_presort_events(bool value) { _should_presort_events = value; } - - bool should_zero_base_timestamps() const { return _should_zero_base_timestamps; } - void set_should_zero_base_timestamps(bool value) { _should_zero_base_timestamps = value; } - - bool should_trace_voucher_contents() const { return _should_trace_voucher_contents; } - void set_should_trace_voucher_contents(bool value) { _should_trace_voucher_contents = value; } - - uint32_t trace_buffer_size() const { return _trace_buffer_size; } - void set_trace_buffer_size(uint32_t value) { _trace_buffer_size = value; } - - AbsTime live_update_interval() const; - void set_live_update_interval(const char* value) { _live_update_interval = value; } - - kLifecycleFilter lifecycle_filter() const { return _lifecycle_filter; } - void set_lifecycle_filter(kLifecycleFilter value) { _lifecycle_filter = value; } - - kMachMsgFilter mach_msg_filter() const { return _mach_msg_filter; } - void set_mach_msg_filter(kMachMsgFilter value) { _mach_msg_filter = value; } -}; - -#endif diff --git a/msa/LiveTraceAction.cpp b/msa/LiveTraceAction.cpp deleted file mode 100644 index 0989e45..0000000 --- a/msa/LiveTraceAction.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// LiveTraceAction.cpp -// msa -// -// Created by James McIlree on 2/4/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "global.h" - -// Force materialization of the ring buffer print methods, -// so they can be called from the debugger. -template class EventRingBuffer; -template class EventRingBuffer; - -static bool shouldProcessEvents; -static uint32_t sigintCount; - -static bool start_live_tracing(Globals& globals) -{ - if (!KDBG::reset()) return false; - if (!KDBG::set_buffer_capacity(globals.trace_buffer_size())) return false; - if (!KDBG::set_nowrap(false)) return false; - if (!KDBG::initialize_buffers()) return false; - if (!KDBG::set_enabled(KDEBUG_ENABLE_TRACE)) return false; - - return true; -} - -static void end_live_tracing(void) -{ - KDBG::reset(); -} - -static void signal_handler_ctrl_C(int sig) -{ - shouldProcessEvents = false; - if (++sigintCount >= 5) { - // Not responding, nuke it from orbit. - exit(1); - } -} - -template -static void live_trace_event_loop(Globals& globals) -{ - // Handle ctrl-C - shouldProcessEvents = true; - sigintCount = 0; - - while (shouldProcessEvents) { - signal(SIGINT, signal_handler_ctrl_C); - - EventRingBuffer ring_buffer(globals, globals.trace_buffer_size() * 2); - - { - char buf[PATH_MAX]; - char* buf_end = buf + sizeof(buf); - print_mach_msg_header(buf, buf_end, globals); - dprintf(globals.output_fd(), "%s", buf); - } - - VoucherContentSysctl contents(globals.should_trace_voucher_contents()); - - if (start_live_tracing(globals)) { - - // Okay, our goal is to hit specific timeposts. - // IOW, if our target is every 10ms, and we spend 3ms doing work, - // we sleep 7ms. - AbsTime traceUpdateIntervalAbs = globals.live_update_interval(); - AbsTime now, next_trace_update = AbsTime::now(); - std::unique_ptr> machine, last_machine; - - std::unordered_map task_appnap_state; - std::unordered_map task_requested_state; - std::unordered_map thread_requested_state; - std::unordered_map> task_effective_state; - std::unordered_map> thread_effective_state; - std::unordered_map> task_boosts; - - while (shouldProcessEvents) { - now = AbsTime::now(); - if (now >= next_trace_update) { - std::size_t count, capacity; - KDEvent* events; - - std::tie(events, count, capacity) = ring_buffer.read(); - if (count) { - if (last_machine) { - machine = std::make_unique>(*last_machine, events, count); - } else { - auto state = KDBG::state(); - auto threadmap = KDBG::threadmap(state); - auto cpumap = KDBG::cpumap(); - machine = std::make_unique>(cpumap.data(), (uint32_t)cpumap.size(), - threadmap.data(), (uint32_t)threadmap.size(), - events, count); - - if (globals.should_zero_base_timestamps() && count) { - globals.set_beginning_of_time(events[0].timestamp()); - } else { - globals.set_beginning_of_time(AbsTime(0)); - } - } - - if (!machine->lost_events()) { - process_events(globals, *machine, task_appnap_state, task_requested_state, thread_requested_state, task_effective_state, thread_effective_state, task_boosts); - - // We read to the end of the ring buffer, and there are - // more events to process. Do not risk an overflow, process - // them immediately. - - // If count == capacity, we read to the end of the ring buffer, - // and should immediately re-read. - if (count < capacity) { - next_trace_update += traceUpdateIntervalAbs; - if (next_trace_update <= now) { - printf("WARNING - falling behind on event processing\n"); - // Reset so if we do catch up, we don't spin on a clock - // that has fallen seconds behind. - next_trace_update = AbsTime::now(); - } - } - } else { - printf("LOST EVENTS, exiting...\n"); - shouldProcessEvents = false; - } - - last_machine = std::move(machine); - } - } - - mach_wait_until(next_trace_update.value()); - } - } else { - printf("Unable to enable tracing.\n"); - shouldProcessEvents = false; - } - - signal(SIGINT, SIG_DFL); - } - - // Final cleanup here to make sure partial initialization is - // cleaned up. - end_live_tracing(); -} - -void LiveTraceAction::execute(Globals& globals) { - // Initial state snapshot, is another program using the trace buffer, etc. - try { - KDState state = KDBG::state(); - if (state.is_initialized() || state.controlling_pid() > 0) { - if (state.controlling_pid() != getpid()) { - if (state.controlling_pid() > 0 && kill(state.controlling_pid(), 0) == -1 && errno == ESRCH) { - if (globals.is_verbose()) { - printf("Reclaiming trace buffer control from pid %d\n", state.controlling_pid()); - } - } else { - printf("Another process is using the trace facility, possibly pid %d\n", state.controlling_pid()); - exit(1); - } - } - } - - try { - if (state.is_lp64()) { - live_trace_event_loop(globals); - } else { - live_trace_event_loop(globals); - } - } catch (const std::exception& e) { - log_msg(ASL_LEVEL_WARNING, "Caught exception in %s:\n %s\n", __PRETTY_FUNCTION__, e.what()); - KDBG::reset(); - } - - } catch (Exception& e) { - if (getuid() != 0) { - printf("Unable to acquire trace buffer state. You must be root.\n"); - exit(1); - } else { - usage(e.what()); - } - } -} diff --git a/msa/LiveTraceAction.hpp b/msa/LiveTraceAction.hpp deleted file mode 100644 index 5f0a291..0000000 --- a/msa/LiveTraceAction.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// LiveTraceAction.h -// msa -// -// Created by James McIlree on 2/4/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __msa__LiveTraceAction__ -#define __msa__LiveTraceAction__ - -class LiveTraceAction : public Action { - public: - LiveTraceAction() {} - - virtual void execute(Globals& globals); -}; - -#endif /* defined(__msa__LiveTraceAction__) */ diff --git a/msa/PrintBuffer.hpp b/msa/PrintBuffer.hpp deleted file mode 100644 index 3755519..0000000 --- a/msa/PrintBuffer.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// PrintBuffer.hpp -// system_cmds -// -// Created by James McIlree on 5/7/14. -// -// - -#ifndef __system_cmds__PrintBuffer__ -#define __system_cmds__PrintBuffer__ - -// -// Okay, here is how snprintf works. -// -// char buf[2]; -// -// snprintf(buf, 0, "a"); // Returns 1, buf is unchanged. -// snprintf(buf, 1, "a"); // Returns 1, buf = \0 -// snprintf(buf, 2, "a"); // Returns 1, buf = 'a', \0 -// -// So... For a buffer of size N, each print is valid if and only if -// it consumes N-1 bytes. -// - -class PrintBuffer { - protected: - char* _buffer; - size_t _buffer_size; - size_t _buffer_capacity; - size_t _flush_boundary; - int _flush_fd; - - public: - PrintBuffer(size_t capacity, size_t flush_boundary, int flush_fd) : - _buffer((char*)malloc(capacity)), - _buffer_size(0), - _buffer_capacity(capacity), - _flush_boundary(flush_boundary), - _flush_fd(flush_fd) - { - ASSERT(capacity > 0, "Sanity"); - ASSERT(_buffer, "Sanity"); - ASSERT(flush_boundary < capacity, "Sanity"); - ASSERT(flush_fd != 0, "Must be a valid fd"); - } - - ~PrintBuffer() { - flush(); - free(_buffer); - } - - void set_capacity(size_t capacity) { - ASSERT(_buffer_size == 0, "Attempt to reallocate buffer while it still contains data"); - - if (_buffer) { - free(_buffer); - } - - _buffer = (char*)malloc(capacity); - _buffer_size = 0; - _buffer_capacity = capacity; - } - - void flush() { - if (_buffer_size) { - write(_flush_fd, _buffer, _buffer_size); - _buffer_size = 0; - } - } - - void printf(const char* format, ...) __attribute__((format(printf, 2, 3))) { - repeat: - size_t remaining_bytes = _buffer_capacity - _buffer_size; - - va_list list; - va_start(list, format); - int bytes_needed = vsnprintf(&_buffer[_buffer_size], remaining_bytes, format, list); - va_end(list); - - // There are three levels of "end" detection. - // - // 1) If bytes_needed is >= capacity, we must flush, grow capacity, and repeat. - // 2) If bytes_needed is >= remaining_bytes, we must flush, and repeat. - // 3) If bytes_needed + _buffer_size comes within _flush_boundary bytes of the end, flush. - // - // NOTE snprintf behavior, we need bytes_needed+1 bytes - // to actually fully output all string characters. - // - // NOTE for any repeat condition, we do not commit the bytes that were written to the buffer. - // - - // Condition 2 - if (bytes_needed >= remaining_bytes) { - flush(); - - // Save a common path if test by checking this only inside Condition 2 - // - // Condition 1 - if (bytes_needed >= _buffer_capacity) { - set_capacity(bytes_needed+1); - } - - goto repeat; - } - - // Commit the snprintf - _buffer_size += bytes_needed; - - // Condition 3 - if (remaining_bytes - bytes_needed <= _flush_boundary) { - flush(); - } - } -}; - -#endif /* defined(__system_cmds__PrintBuffer__) */ diff --git a/msa/Printing.cpp b/msa/Printing.cpp deleted file mode 100644 index 3c5c2b4..0000000 --- a/msa/Printing.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// -// MessagePrinting.cpp -// msa -// -// Created by James McIlree on 2/5/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "global.h" - -const char* qos_to_string(uint32_t qos) { - static_assert(THREAD_QOS_LAST == 7, "QOS tiers need updating"); - - switch (qos) { - case THREAD_QOS_UNSPECIFIED: - return "unspecified"; - - case THREAD_QOS_MAINTENANCE: - return "maintenance"; - - case THREAD_QOS_BACKGROUND: - return "background"; - - case THREAD_QOS_UTILITY: - return "utility"; - - case THREAD_QOS_LEGACY: - return "legacy"; - - case THREAD_QOS_USER_INITIATED: - return "user-initiated"; - - case THREAD_QOS_USER_INTERACTIVE: - return "user-interactive"; - - default: - ASSERT(false, "Unhandled QoS"); - return "QOS_???"; - } -} - -const char* qos_to_short_string(uint32_t qos) { - static_assert(THREAD_QOS_LAST == 7, "QOS tiers need updating"); - - switch (qos) { - case THREAD_QOS_UNSPECIFIED: - return "Unspec"; - - case THREAD_QOS_MAINTENANCE: - return "Maint"; - - case THREAD_QOS_BACKGROUND: - return "BG"; - - case THREAD_QOS_UTILITY: - return "Util"; - - case THREAD_QOS_LEGACY: - return "Legacy"; - - case THREAD_QOS_USER_INITIATED: - return "UInit"; - - case THREAD_QOS_USER_INTERACTIVE: - return "UI"; - - default: - ASSERT(false, "Unhandled QoS"); - return "???"; - } -} - -const char* role_to_short_string(uint32_t role) { - switch (role) { - // This is seen when apps are terminating - case TASK_UNSPECIFIED: - return "unspec"; - - case TASK_FOREGROUND_APPLICATION: - return "fg"; - - case TASK_BACKGROUND_APPLICATION: - return "bg"; - - case TASK_CONTROL_APPLICATION: - case TASK_GRAPHICS_SERVER: - case TASK_THROTTLE_APPLICATION: - case TASK_NONUI_APPLICATION: - ASSERT(false, "These should be obsolete"); - return "obsolete"; - - case TASK_DEFAULT_APPLICATION: - // Is this obsolete too? - return "defapp"; - - default: - ASSERT(false, "Unexpected app role"); - return "???"; - } -} - -const char* role_to_string(uint32_t role) { - switch (role) { - // This is seen when apps are terminating - case TASK_UNSPECIFIED: - return "unspecified"; - - case TASK_FOREGROUND_APPLICATION: - return "foreground"; - - case TASK_BACKGROUND_APPLICATION: - return "background"; - - case TASK_CONTROL_APPLICATION: - return "control-application"; - - case TASK_GRAPHICS_SERVER: - return "graphics-server"; - - case TASK_THROTTLE_APPLICATION: - return "throttle-app"; - - case TASK_NONUI_APPLICATION: - return "nonui-app"; - - case TASK_DEFAULT_APPLICATION: - // Is this obsolete too? - return "default-app"; - - default: - ASSERT(false, "Unexpected app role"); - return "???"; - } -} - -void print_base_empty(PrintBuffer& buffer, - const Globals& globals, - uintptr_t event_index, - const char* type, - bool should_newline) -{ - // Base Header is... (32) - // - // Time(µS) Type Thread ThreadVoucher AppType Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789abcdef0 12345678901234567 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB voucher-133 AdaptiveDaemon TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 InteractiveDaemon configd (19981) ;; - - // Base Header is... (64) - // - // Time(µS) Type Thread ThreadVoucher AppType Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789abcdef0 12345678901234567 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB voucher-133 AdaptiveDaemon TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 InteractiveDaemon configd (19981) ;; - - // - // [Index] - // - if (globals.should_print_event_index()) { - buffer.printf("%8llu ", (uint64_t)event_index); - } - - // - // Time Type Code Thread ThreadVoucher AppType Process - // - // This assert doesn't handle utf8... - ASSERT(strlen(type) <= 22, "Sanity"); - - buffer.printf("%16s %3s %22s %10s %16s %17s %24s ;;", "-", "-", type, "-", "-", "-", "- (-)"); - - // - // Process - // - if (should_newline) - buffer.printf("\n"); - else - buffer.printf(" "); -} - -static char* print_base_header(char* buf, char* buf_end, const Globals& globals) { - // Base Header is... (32) - // - // Time(µS) Type Thread ThrVoucher Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789a 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB FFFF8E44 TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 configd (19981) ;; - - // Base Header is... (64) - // - // Time(µS) Type Thread ThreadVoucher Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789abcdef0 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB BBBBAAEE55778234 TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 configd (19981) ;; - - // - // If we cannot print successfully, we return the orignal pointer. - // - char* orig_buf = buf; - - if (globals.should_print_event_index()) - buf += snprintf(buf, buf_end - buf,"%8s ", "Event#"); - - if (buf >= buf_end) - return orig_buf; - - // The character counting for "Time(µS)" is OBO, it treats the µ as two characters. - // This means the %16s misaligns. We force it by making the input string 16 printable chars long, - // which overflows the %16s to the correct actual output length. - const char* time = globals.should_print_mach_absolute_timestamps() ? "Time(mach-abs)" : " Time(µS)"; - - if (globals.kernel_size() == KernelSize::k32) - buf += snprintf(buf, buf_end - buf, "%s %22s %10s %10s %24s ;; ", time, "Type", "Thread", "ThrVoucher", "Process"); - else - buf += snprintf(buf, buf_end - buf, "%s %22s %10s %16s %24s ;; ", time, "Type", "Thread", "ThreadVoucher", "Process"); - - return (buf >= buf_end) ? orig_buf : buf; -} - -char* print_mach_msg_header(char* buf, char* buf_end, const Globals& globals) { - - // MachMsg Header is... (32) - // - // ;; Message From/To MsgID MsgVoucher DeliveryTime FLAGS - // 12 123456789012345678901234567 123456789 123456789a 1234567890123 ... - // ;; -> configd (19981) 55 - - ONEWAY, IMP-DONATING - // ;; <- TextEdit (231) 55 FFFF8E44 120080 VOUCHER-PROVIDED-BY-KERNEL, VOUCHER-REFUSED - - // MachMsg Header is... (64) - // - // ;; Message From/To MsgID MsgVoucher DeliveryTime FLAGS - // 12 123456789012345678901234567 123456789 123456789abcdef0 1234567890123 ... - // ;; -> configd (19981) 55 - - ONEWAY, IMP-DONATING - // ;; <- TextEdit (231) 55 FFFFAAEE55778234 120080 VOUCHER-PROVIDED-BY-KERNEL, VOUCHER-REFUSED - - char* orig_buf = buf; - - // - // Base Header - // - buf = print_base_header(buf, buf_end, globals); - - if (buf == orig_buf) - return orig_buf; - - // - // Mach Msg Header - // - if (globals.kernel_size() == KernelSize::k32) - buf += snprintf(buf, buf_end - buf, "%-27s %9s %10s %13s %s\n", "Message-From/To", "MsgID", "MsgVoucher", "DeliveryTime", "FLAGS"); - else - buf += snprintf(buf, buf_end - buf, "%-27s %9s %16s %13s %s\n", "Message-From/To", "MsgID", "MsgVoucher", "DeliveryTime", "FLAGS"); - - return (buf >= buf_end) ? orig_buf : buf; -} diff --git a/msa/Printing.hpp b/msa/Printing.hpp deleted file mode 100644 index 3ebb0a4..0000000 --- a/msa/Printing.hpp +++ /dev/null @@ -1,1318 +0,0 @@ -// -// MessagePrinting.h -// msa -// -// Created by James McIlree on 2/5/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __msa__MessagePrinting__ -#define __msa__MessagePrinting__ - -char* print_mach_msg_header(char*, char*, const Globals&); -char* print_thread_set_voucher_header(char* buf, char* buf_end, const Globals& globals); -const char* qos_to_string(uint32_t qos); -const char* qos_to_short_string(uint32_t qos); -const char* role_to_string(uint32_t role); -const char* role_to_short_string(uint32_t role); -void print_base_empty(PrintBuffer& buffer, const Globals& globals, uintptr_t event_index, const char* type, bool should_newline); - -template -void print_base(PrintBuffer& buffer, - const Globals& globals, - AbsTime timestamp, - const MachineThread* thread, - const KDEvent& event, - uintptr_t event_index, - const char* type, - bool should_newline) -{ - // Base Header is... (32) - // - // Time(µS) Type Thread ThreadVoucher AppType Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789abcdef0 12345678901234567 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB voucher-133 AdaptiveDaemon TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 InteractiveDaemon configd (19981) ;; - - // Base Header is... (64) - // - // Time(µS) Type Thread ThreadVoucher AppType Process ;; - // 123456789abcdef0 1234567890123456789012 1234567890 123456789abcdef0 12345678901234567 123456789012345678901234 12 - // 14.11 mach_msg_send 18FB voucher-133 AdaptiveDaemon TextEdit (231) ;; - // 18.11 mach_msg_recv 18FB 0 InteractiveDaemon configd (19981) ;; - - // - // [Index] - // - if (globals.should_print_event_index()) { - buffer.printf("%8llu ", (uint64_t)event_index); - } - - // - // Time - // - if (globals.should_print_mach_absolute_timestamps()) { - if (globals.beginning_of_time().value() == 0) - buffer.printf("%16llX ", (timestamp - globals.beginning_of_time()).value()); - else - buffer.printf("%16llu ", (timestamp - globals.beginning_of_time()).value()); - } else { - NanoTime ntime = (timestamp - globals.beginning_of_time()).nano_time(globals.timebase()); - buffer.printf("%16.2f ", (double)ntime.value() / 1000.0); - } - - // - // beg/end/--- - // - buffer.printf("%3s ", event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---")); - - // - // Type Code, Thread - // - - // This assert doesn't handle utf8... - ASSERT(strlen(type) <= 22, "Sanity"); - if (SIZE::is_64_bit) - buffer.printf("%22s %10llX ", type, (uint64_t)thread->tid()); - else - buffer.printf("%22s %10llX ", type, (uint64_t)thread->tid()); - - // - // ThreadVoucher - // - auto thread_voucher = (thread) ? thread->voucher(timestamp) : &Machine::UnsetVoucher; - - if (thread_voucher->is_unset()) { - buffer.printf("%16s ", "-"); - } else if (thread_voucher->is_null()) { - buffer.printf("%16s ", "0"); - } else { - char voucher_id[32]; - snprintf(voucher_id, sizeof(voucher_id), "voucher-%u", thread_voucher->id()); - buffer.printf("%16s ", voucher_id); - } - - // - // AppType - // - const char* apptype_string = nullptr; - switch (thread->process().apptype()) { - case -1: - apptype_string = "-"; - break; - case TASK_APPTYPE_NONE: - apptype_string = "None"; - break; - case TASK_APPTYPE_DAEMON_INTERACTIVE: - apptype_string = "InteractiveDaemon"; - break; - case TASK_APPTYPE_DAEMON_STANDARD: - apptype_string = "StandardDaemon"; - break; - case TASK_APPTYPE_DAEMON_ADAPTIVE: - apptype_string = "AdaptiveDaemon"; - break; - case TASK_APPTYPE_DAEMON_BACKGROUND: - apptype_string = "BackgroundDaemon"; - break; - case TASK_APPTYPE_APP_DEFAULT: - apptype_string = "App"; - break; - case TASK_APPTYPE_APP_TAL: - apptype_string = "TALApp"; - break; - default: - apptype_string = "???"; - break; - } - buffer.printf("%17s ", apptype_string); - - // - // Process - // - char process_name[32]; - - // Should not ever fail, but... - if (thread) { - const MachineProcess& process = thread->process(); - snprintf(process_name, sizeof(process_name), "%s (%d)", process.name(), process.pid()); - } else { - snprintf(process_name, sizeof(process_name), "???"); - } - - if (should_newline) - buffer.printf("%24s ;;\n", process_name); - else - buffer.printf("%24s ;; ", process_name); -} - -template -void print_mach_msg(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - bool is_send, - const MachineMachMsg* mach_msg) -{ - // Mach Msg Header is... (32) - // - // ;; Message From/To MsgID MsgVoucher DeliveryTime FLAGS - // 12 123456789012345678901234567 123456789ab 123456789abcdef0 1234567890123 ... - // ;; -> configd (19981) 55 - - ONEWAY, IMP-DONATING - // ;; <- TextEdit (231) 55 voucher-133 120080 VOUCHER-PROVIDED-BY-KERNEL, VOUCHER-REFUSED - - // Mach Msg Header is... (64) - // - // ;; Message From/To MsgID MsgVoucher DeliveryTime FLAGS - // 12 123456789012345678901234567 123456789ab 123456789abcdef0 1234567890123 ... - // ;; -> configd (19981) 55 - - ONEWAY, IMP-DONATING - // ;; <- TextEdit (231) 55 voucher-133 120080 VOUCHER-PROVIDED-BY-KERNEL, VOUCHER-REFUSED - - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, is_send ? "mach_msg_send" : "mach_msg_recv", false); - - // - // Message From/To - // - { - char from_to_name[32]; - const MachineThread* from_to_thread = NULL; - const char* from_to_direction; - - if (is_send) { - from_to_direction = "->"; - if (mach_msg->has_receiver()) - from_to_thread = machine.thread(mach_msg->recv_tid(), mach_msg->recv_time()); - } else { - from_to_direction = "<-"; - if (mach_msg->has_sender()) - from_to_thread = machine.thread(mach_msg->send_tid(), mach_msg->send_time()); - } - - if (from_to_thread) { - const MachineProcess& from_to_process = from_to_thread->process(); - snprintf(from_to_name, sizeof(from_to_name), "%s %s (%d)", from_to_direction, from_to_process.name(), from_to_process.pid()); - } else { - // (???) is a trigraph, break up by escaping one of the ? - snprintf(from_to_name, sizeof(from_to_name), "%s ??? (??\?)", from_to_direction); - } - - buffer.printf("%-27s ", from_to_name); - } - - // - // MsgID - // - - char msg_id[32]; - snprintf(msg_id, sizeof(msg_id), "msg-%u", mach_msg->id()); - buffer.printf("%11s ", msg_id); - - // - // MsgVoucher - // - // We want to differentiate between sending a NULL voucher and not having msgh_bits set. - // We will show a NULL voucher as 0, but if msgh_bits says no voucher was sent, we will show "-" - // - - MachineVoucher* msg_voucher = (is_send) ? mach_msg->send_voucher() : mach_msg->recv_voucher(); - - if (msg_voucher->is_unset()) { - buffer.printf("%16s ", "-"); - } else if (msg_voucher->is_null()) { - buffer.printf("%16s ", "0"); - } else { - char voucher_id[32]; - snprintf(voucher_id, sizeof(voucher_id), "voucher-%u", msg_voucher->id()); - buffer.printf("%16s ", voucher_id); - } - - // - // DeliveryTime - // - - if (!is_send) { - if (mach_msg->has_sender()) { - NanoTime ntime = (mach_msg->recv_time() - mach_msg->send_time()).nano_time(globals.timebase()); - buffer.printf("%13.2f ", (double)ntime.value() / 1000.0); - } else { - buffer.printf("%13s ", "?"); - } - } else { - buffer.printf("%13s ", "-"); - } - - // - // FLAGS - // - const char* separator = ""; - - if (is_send) { - if (!MACH_MSGH_BITS_HAS_LOCAL(mach_msg->send_msgh_bits())) { - buffer.printf("%sONEWAY", separator); - separator = ", "; - } - - if (MACH_MSGH_BITS_RAISED_IMPORTANCE(mach_msg->send_msgh_bits())) { - buffer.printf("%sMSGH_BITS_RAISED_IMPORTANCE", separator); - separator = ", "; - } - - if (MACH_MSGH_BITS_HOLDS_IMPORTANCE_ASSERTION(mach_msg->send_msgh_bits())) { - buffer.printf("%sMSGH_BITS_HOLDS_IMPORTANCE_ASSERTION", separator); - separator = ", "; - } - } else { - if (mach_msg->is_voucher_refused()) { - // FIX ME! - // Need to test this... Can we tell if a voucher was refused without the - // send voucher? - // - if (mach_msg->has_non_null_send_voucher() || mach_msg->has_non_null_recv_voucher()) { - buffer.printf("%sVOUCHER-REFUSED", separator); - } - - separator = ", "; - } - if (MACH_MSGH_BITS_RAISED_IMPORTANCE(mach_msg->recv_msgh_bits())) { - buffer.printf("%sMSGH_BITS_RAISED_IMPORTANCE", separator); - separator = ", "; - } - - if (MACH_MSGH_BITS_HOLDS_IMPORTANCE_ASSERTION(mach_msg->recv_msgh_bits())) { - buffer.printf("%sMSGH_BITS_HOLDS_IMPORTANCE_ASSERTION", separator); - separator = ", "; - } - } - - // - // MsgVoucher transformation - // - { - char transformed_voucher[32]; - - if (mach_msg->has_sender() && mach_msg->has_receiver()) { - auto send_voucher = mach_msg->send_voucher(); - auto recv_voucher = mach_msg->recv_voucher(); - - if (send_voucher != recv_voucher) { - auto changed_voucher = (is_send) ? recv_voucher : send_voucher; - auto changed_tense = (is_send) ? "becomes" : "was"; - - if (changed_voucher->is_unset()) { - snprintf(transformed_voucher, sizeof(transformed_voucher), "(%s -)", changed_tense); - } else if (changed_voucher->is_null()) { - snprintf(transformed_voucher, sizeof(transformed_voucher), "(%s 0)", changed_tense); - } else { - snprintf(transformed_voucher, sizeof(transformed_voucher), "(%s voucher-%u)", changed_tense, changed_voucher->id()); - } - - buffer.printf("%sVOUCHER_CHANGED %s", separator, transformed_voucher); - } - } - } - - buffer.printf("\n"); -} - -template -void print_boost(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - pid_t boost_receiver_pid, - bool is_boost) -{ - - // Base Header is... (32) - // - // ;; - // 12 - // ;; BOOST foobard (338) - - // Base Header is... (64) - // - // ;; - // 12 - // ;; BOOST foobard (338) - - - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, is_boost ? "boost" : "unboost", false); - - // - // Boost target - // - - const MachineProcess* target = machine.process(boost_receiver_pid, event.timestamp()); - const char* target_name; - - if (target) { - target_name = target->name(); - } else { - target_name = "???"; - } - - const char* action = is_boost ? "BOOST" : "UNBOOST"; - - buffer.printf("%s %s (%d)\n", action, target_name, boost_receiver_pid); -} - -template -void print_impdelv(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - pid_t sender_pid, - uint32_t importance_delivery_result) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, "importance_delivered", false); - - // - // Importance sender - // - const char* sender_name = "???"; - if (const MachineProcess* sender = machine.process(sender_pid, event.timestamp())) { - sender_name = sender->name(); - } - - // 0: BOOST NOT APPLIED - // 1: BOOST EXTERNALIZED - // 2: LIVE_IMPORTANCE_LINKAGE! - - switch (importance_delivery_result) { - case 0: - buffer.printf("importance from %s (%d) was not applied\n", sender_name, sender_pid); - break; - case 1: - buffer.printf("importance from %s (%d) was externalized\n", sender_name, sender_pid); - break; - case 2: - buffer.printf("linked to %s (%d)'s live importance chain\n", sender_name, sender_pid); - break; - - default: - ASSERT(false, "Unknown importance delivery result value"); - buffer.printf("Unknown importance delivery result value\n"); - break; - } -} - -template -void print_generic(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const char* type) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, type, true); -} - -template -void print_importance_assert(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const char* type, - std::unordered_map>& task_importance) -{ - // All callers must have the following trace event data: - // - // ignored, target_pid, internal_count, external_count - - // First check if anything changed - pid_t target_pid = (pid_t)event.arg2(); - if (target_pid < 1) - return; - - bool must_print = false; - auto it = task_importance.find(target_pid); - if (it == task_importance.end()) { - it = task_importance.emplace(target_pid, std::pair(0, 0)).first; - // The very first time we see data for an app, we always want to print it. - must_print = true; - } - - auto old_importance = it->second; - auto new_importance = std::pair((uint32_t)event.arg3(), (uint32_t)event.arg4()); - if (must_print || old_importance != new_importance) { - const MachineThread* event_thread = machine.thread(event.tid(), event.timestamp()); - print_base(buffer, globals, event.timestamp(), event_thread, event, event_index, type, false); - - const MachineProcess* target = machine.process(target_pid, event.timestamp()); - const char* target_name; - - if (target) { - target_name = target->name(); - } else { - target_name = "???"; - } - - int internal_delta = new_importance.first - old_importance.first; - int external_delta = new_importance.second - old_importance.second; - - char internal_sign = internal_delta >= 0 ? '+' : '-'; - char external_sign = external_delta >= 0 ? '+' : '-'; - - char internal_changed_buf[32]; - char external_changed_buf[32]; - - if (internal_delta != 0) { - snprintf(internal_changed_buf, sizeof(internal_changed_buf), " (%c%u)", internal_sign, abs(internal_delta)); - } else { - internal_changed_buf[0] = 0; - } - - if (external_delta != 0) { - snprintf(external_changed_buf, sizeof(external_changed_buf), " (%c%u)", external_sign, abs(external_delta)); - } else { - external_changed_buf[0] = 0; - } - - buffer.printf("%s (%d) internal: %u%s external: %u%s\n", - target_name, target_pid, - new_importance.first, internal_changed_buf, - new_importance.second, external_changed_buf); - - it->second = new_importance; - } -} - -template -void print_watchport_importance_transfer(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index) -{ - // event data is - // - // proc_selfpid(), pid, boost, released_pid, 0); - - // Did any importance transfer? - if (event.arg3() == 0) - return; - - // Do we have a valid pid? - pid_t dest_pid = (pid_t)event.arg2(); - if (dest_pid < 1) - return; - - const MachineThread* event_thread = machine.thread(event.tid(), event.timestamp()); - print_base(buffer, globals, event.timestamp(), event_thread, event, event_index, "importance_watchport", false); - - const char* dest_name; - if (const MachineProcess* dest = machine.process(dest_pid, event.timestamp())) { - dest_name = dest->name(); - } else { - dest_name = "???"; - } - - buffer.printf("%s (%d) receives %d importance via watchport\n", - dest_name, dest_pid, (int)event.arg3()); -} - -template -void print_importance_send_failed(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, "impsend", false); - - // - // Currently, the IMP_MSG_SEND trace data is not accurate. - // - - buffer.printf("Backed out importance (may be resent) - TIMED_OUT, NO_BUFFER, or SEND_INTERRUPTED\n"); -} - -#if 0 - -template -void print_trequested_task(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - pid_t pid, - struct task_requested_policy new_task_requested, - struct task_requested_policy original_task_requested) -{ - // Many of these events would print nothing, we want to make sure there is something to print first. - - char description[512]; - char* cursor = description; - char* cursor_end = cursor + sizeof(description); - uint32_t description_count = 0; - - if (new_task_requested.t_role != original_task_requested.t_role) { - const char* role = "???"; - switch (new_task_requested.t_role) { - // This is seen when apps are terminating - case TASK_UNSPECIFIED: - role = "unspecified"; - break; - - case TASK_FOREGROUND_APPLICATION: - role = "foreground"; - break; - - case TASK_BACKGROUND_APPLICATION: - role = "background"; - break; - - case TASK_CONTROL_APPLICATION: - role = "control-application"; - break; - - case TASK_GRAPHICS_SERVER: - role = "graphics-server"; - break; - - case TASK_THROTTLE_APPLICATION: - role = "throttle-application"; - break; - - case TASK_NONUI_APPLICATION: - role = "nonui-application"; - break; - - case TASK_DEFAULT_APPLICATION: - role = "default-application"; - break; - - default: - ASSERT(false, "Unexpected app role"); - break; - } - cursor += snprintf(cursor, cursor_end - cursor, "%sROLE:%s", description_count++ == 0 ? "" : ", ", role); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.int_darwinbg != original_task_requested.int_darwinbg) { - cursor += snprintf(cursor, cursor_end - cursor, "%s%sINT_DARWINBG", description_count++ == 0 ? "" : ", ", new_task_requested.int_darwinbg ? "" : "!"); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.ext_darwinbg != original_task_requested.ext_darwinbg) { - cursor += snprintf(cursor, cursor_end - cursor, "%s%sEXT_DARWINBG", description_count++ == 0 ? "" : ", ", new_task_requested.ext_darwinbg ? "" : "!"); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_int_gpu_deny != original_task_requested.t_int_gpu_deny) { - cursor += snprintf(cursor, cursor_end - cursor, "%sINT_GPU_DENY", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_ext_gpu_deny != original_task_requested.t_ext_gpu_deny) { - cursor += snprintf(cursor, cursor_end - cursor, "%sEXT_GPU_DENY", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_tal_enabled != original_task_requested.t_tal_enabled) { - cursor += snprintf(cursor, cursor_end - cursor, "%sTAL_ENABLED", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_sfi_managed != original_task_requested.t_sfi_managed) { - cursor += snprintf(cursor, cursor_end - cursor, "%sSFI_MANAGED", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_sup_active != original_task_requested.t_sup_active) { - cursor += snprintf(cursor, cursor_end - cursor, "%sAPPNAP", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_base_latency_qos != original_task_requested.t_base_latency_qos) { - cursor += snprintf(cursor, cursor_end - cursor, "%sBASE_LATENCY_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_task_requested.t_base_latency_qos)); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_over_latency_qos != original_task_requested.t_over_latency_qos) { - cursor += snprintf(cursor, cursor_end - cursor, "%sOVERRIDE_LATENCY_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_task_requested.t_over_latency_qos)); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_base_through_qos != original_task_requested.t_base_through_qos) { - cursor += snprintf(cursor, cursor_end - cursor, "%sBASE_THROUGHPUT_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_task_requested.t_base_through_qos)); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_over_through_qos != original_task_requested.t_over_through_qos) { - cursor += snprintf(cursor, cursor_end - cursor, "%sOVERRIDE_THROUGHPUT_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_task_requested.t_over_through_qos)); - GUARANTEE(cursor < cursor_end); - } - - if (new_task_requested.t_qos_clamp != original_task_requested.t_qos_clamp) { - cursor += snprintf(cursor, cursor_end - cursor, "%sQOS_CLAMP:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_task_requested.t_qos_clamp)); - GUARANTEE(cursor < cursor_end); - } - - if (description_count) { - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event_index, "task_trequested", false); - - ASSERT(pid != -1, "Sanity"); - - const char* target_name; - if (const MachineProcess* target = machine.process(pid, event.timestamp())) { - target_name = target->name(); - } else { - target_name = "???"; - } - - buffer.printf("%s (%d) requests %s\n", target_name, pid, description); - } -} - -struct task_requested_policy { - /* Task and thread policy (inherited) */ - uint64_t int_darwinbg :1, /* marked as darwinbg via setpriority */ - ext_darwinbg :1, - int_iotier :2, /* IO throttle tier */ - ext_iotier :2, - int_iopassive :1, /* should IOs cause lower tiers to be throttled */ - ext_iopassive :1, - bg_iotier :2, /* what IO throttle tier should apply to me when I'm darwinbg? (pushed to threads) */ - terminated :1, /* all throttles should be removed for quick exit or SIGTERM handling */ - - /* Thread only policy */ - th_pidbind_bg :1, /* thread only: task i'm bound to is marked 'watchbg' */ - th_workq_bg :1, /* thread only: currently running a background priority workqueue */ - thrp_qos :3, /* thread only: thread qos class */ - thrp_qos_relprio :4, /* thread only: thread qos relative priority (store as inverse, -10 -> 0xA) */ - thrp_qos_override :3, /* thread only: thread qos class override */ - - /* Task only policy */ - t_apptype :3, /* What apptype did launchd tell us this was (inherited) */ - t_boosted :1, /* Has a non-zero importance assertion count */ - t_int_gpu_deny :1, /* don't allow access to GPU */ - t_ext_gpu_deny :1, - t_role :3, /* task's system role */ - t_tal_enabled :1, /* TAL mode is enabled */ - t_base_latency_qos :3, /* Timer latency QoS */ - t_over_latency_qos :3, /* Timer latency QoS override */ - t_base_through_qos :3, /* Computation throughput QoS */ - t_over_through_qos :3, /* Computation throughput QoS override */ - t_sfi_managed :1, /* SFI Managed task */ - t_qos_clamp :3, /* task qos clamp */ - - /* Task only: suppression policies (non-embedded only) */ - t_sup_active :1, /* Suppression is on */ - t_sup_lowpri_cpu :1, /* Wants low priority CPU (MAXPRI_THROTTLE) */ - t_sup_timer :3, /* Wanted timer throttling QoS tier */ - t_sup_disk :1, /* Wants disk throttling */ - t_sup_cpu_limit :1, /* Wants CPU limit (not hooked up yet)*/ - t_sup_suspend :1, /* Wants to be suspended */ - t_sup_throughput :3, /* Wants throughput QoS tier */ - t_sup_cpu :1, /* Wants suppressed CPU priority (MAXPRI_SUPPRESSED) */ - t_sup_bg_sockets :1, /* Wants background sockets */ - - reserved :2; -}; -#endif - -template -void print_appnap(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - bool is_appnap_active, - std::unordered_map& task_appnap_state, - std::unordered_map& task_requested_state) -{ - // - // event args are: - // - // self_pid, audit_token_pid_from_task(task), trequested_0(task, NULL), trequested_1(task, NULL) - // - auto pid = (pid_t)event.arg2(); - auto trequested_0 = event.arg3(); - auto trequested_1 = event.arg4(); - auto task_requested = (SIZE::is_64_bit) ? TaskRequestedPolicy(trequested_0) : TaskRequestedPolicy((Kernel32::ptr_t)trequested_0, (Kernel32::ptr_t)trequested_1); - auto should_print = false; - - ASSERT(pid != -1, "Sanity"); - - // If the appnap state changed, we want to print this event. - auto appnap_it = task_appnap_state.find(pid); - if (appnap_it == task_appnap_state.end()) { - should_print = true; - task_appnap_state.emplace(pid, is_appnap_active); - } else { - if (appnap_it->second != is_appnap_active) { - should_print = true; - appnap_it->second = is_appnap_active; - } - } - - // If the task_requested state changed, we want to print this event. - auto requested_it = task_requested_state.find(pid); - if (requested_it == task_requested_state.end()) { - should_print = true; - task_requested_state.emplace(pid, task_requested); - } else { - if (requested_it->second != task_requested) { - should_print = true; - requested_it->second = task_requested; - } - } - - if (should_print) { - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, "imp_supression", false); - - const char* name; - if (auto target = machine.process(pid, event.timestamp())) { - name = target->name(); - } else { - name = "???"; - } - buffer.printf("%s (%d) AppNap is %s\n", name, pid, is_appnap_active ? "ON" : "OFF"); - print_trequested_task(buffer, globals, machine, event, event_index, pid, task_requested); - } -} - -template -void print_trequested_task(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - pid_t pid, - TaskRequestedPolicy task_requested) -{ - - ASSERT(pid != -1, "Sanity"); - const char* target_name; - if (const MachineProcess* target = machine.process(pid, event.timestamp())) { - target_name = target->name(); - } else { - target_name = "???"; - } - - struct task_requested_policy trp = task_requested.as_struct(); - - print_base_empty(buffer, globals, event_index, "task_trequested", false); - buffer.printf("%s (%d) requests%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - target_name, pid, - trp.int_darwinbg ? " IntDBG" : "", - trp.ext_darwinbg ? " ExtDBG" : "", - trp.int_iopassive ? " IntIOPass" : "", - trp.ext_iopassive ? " ExtIOPass" : "", - trp.terminated ? " Term" : "", - trp.t_boosted ? " Boost" : "", - trp.t_int_gpu_deny ? " IntDenyGPU" : "", - trp.t_ext_gpu_deny ? " ExtDenyGPU" : "", - trp.t_tal_enabled ? " TAL" : "", - trp.t_sfi_managed ? " SFI" : "", - // Below here is AppNap only... - trp.t_sup_active ? " AppNap" : "", - trp.t_sup_lowpri_cpu ? " SupLowPriCPU" : "", - trp.t_sup_disk ? " SupDisk" : "", - trp.t_sup_cpu_limit ? " SupCPULim" : "", - trp.t_sup_suspend ? " SupSusp" : "", - trp.t_sup_cpu ? " SupCPU" : "", - trp.t_sup_bg_sockets ? " SupBGSck" : ""); - - print_base_empty(buffer, globals, event_index, "task_trequested", false); - buffer.printf("%s (%d) requests QOS (SupTHR/SupTMR/LAT/OVERLAT/THR/OVERTHR/CLAMP) %s/%s/%s/%s/%s/%s/%s int_IOTier:%d ext_IOTier:%d bg_IOTier:%d\n", - target_name, pid, - qos_to_string(trp.t_sup_throughput), - qos_to_string(trp.t_sup_timer), - qos_to_string(trp.t_base_latency_qos), - qos_to_string(trp.t_over_latency_qos), - qos_to_string(trp.t_base_through_qos), - qos_to_string(trp.t_over_through_qos), - qos_to_string(trp.t_qos_clamp), - trp.int_iotier, - trp.ext_iotier, - trp.bg_iotier); -} - -template -void print_trequested_thread(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const MachineThread* thread, - struct task_requested_policy new_thread_requested, - struct task_requested_policy original_thread_requested) -{ - ASSERT(thread, "Sanity"); - - // Many of these events would print nothing, we want to make sure there is something to print first. - - char description[512]; - char* cursor = description; - char* cursor_end = cursor + sizeof(description); - uint32_t description_count = 0; - - if (new_thread_requested.int_darwinbg != original_thread_requested.int_darwinbg) { - cursor += snprintf(cursor, cursor_end - cursor, "%sINT_DARWINBG", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.ext_darwinbg != original_thread_requested.ext_darwinbg) { - cursor += snprintf(cursor, cursor_end - cursor, "%sEXT_DARWINBG", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.th_pidbind_bg != original_thread_requested.th_pidbind_bg) { - cursor += snprintf(cursor, cursor_end - cursor, "%sPIDBIND_BG", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.th_workq_bg != original_thread_requested.th_workq_bg) { - cursor += snprintf(cursor, cursor_end - cursor, "%sWORKQ_BG", description_count++ == 0 ? "" : ", "); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.thrp_qos != original_thread_requested.thrp_qos) { - cursor += snprintf(cursor, cursor_end - cursor, "%sTHREAD_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_thread_requested.thrp_qos)); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.thrp_qos_relprio != original_thread_requested.thrp_qos_relprio) { - cursor += snprintf(cursor, cursor_end - cursor, "%sTHREAD_QOS_RELATIVE_PRIORITY:%d", description_count++ == 0 ? "" : ", ", -new_thread_requested.thrp_qos_relprio); - GUARANTEE(cursor < cursor_end); - } - - if (new_thread_requested.thrp_qos_override != original_thread_requested.thrp_qos_override) { - cursor += snprintf(cursor, cursor_end - cursor, "%sTHREAD_OVERRIDE_QOS:%s", description_count++ == 0 ? "" : ", ", qos_to_string(new_thread_requested.thrp_qos_override)); - GUARANTEE(cursor < cursor_end); - } - - if (description_count) { - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event_index, "thread_trequested", false); - ASSERT(thread->process().pid() != -1, "Sanity"); - buffer.printf("%s (%d) %llX requests %s\n", thread->process().name(), thread->process().pid(), (uint64_t)thread->tid(), description); - } -} - -template -void print_teffective_task(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - pid_t pid, - TaskEffectivePolicy task_effective) -{ - ASSERT(pid != -1, "Sanity"); - const char* target_name; - if (const MachineProcess* target = machine.process(pid, event.timestamp())) { - target_name = target->name(); - } else { - target_name = "???"; - } - - struct task_effective_policy tep = task_effective.as_struct(); - - print_base_empty(buffer, globals, event_index, "task_teffective", false); - buffer.printf("%s (%d) is%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - target_name, pid, - tep.darwinbg ? " DarwinBG" : "", - tep.t_sup_active ? " AppNap" : "", - tep.lowpri_cpu ? " LowPri" : "", - tep.io_passive ? " IOPass" : "", - tep.all_sockets_bg ? " ASckBG" : "", - tep.new_sockets_bg ? " NSckBG" : "", - tep.terminated ? " Term" : "", - tep.qos_ui_is_urgent ? " QOSUiIsUrg" : "", - tep.t_gpu_deny ? " GPUDeny" : "", - tep.t_suspended ? " SupSusp" : "", - tep.t_watchers_bg ? " WchrsBG" : "", - tep.t_suppressed_cpu ? " SupCPU" : "", - tep.t_sfi_managed ? " SFI" : "", - tep.t_live_donor ? " LiveImpDnr" : ""); - - print_base_empty(buffer, globals, event_index, "task_teffective", false); - buffer.printf("%s (%d) is Role:%s LAT/THR/CLAMP/CEIL:%s/%s/%s/%s IOTier:%d BG_IOTier:%d\n", - target_name, pid, - role_to_string(tep.t_role), - qos_to_string(tep.t_latency_qos), - qos_to_string(tep.t_through_qos), - qos_to_string(tep.t_qos_clamp), - qos_to_string(tep.t_qos_ceiling), - tep.io_tier, - tep.bg_iotier); -} - -template -void print_teffective_thread(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const MachineThread* thread, - TaskEffectivePolicy thread_effective) -{ - ASSERT(thread, "Sanity"); - - const char* target_name = thread->process().name(); - - struct task_effective_policy tep = thread_effective.as_struct(); - - print_base_empty(buffer, globals, event_index, "thread_teffective", false); - buffer.printf("%s (%d) %llX is%s%s%s%s%s%s%s%s\n", - target_name, thread->process().pid(), (uint64_t)thread->tid(), - tep.darwinbg ? " DarwinBG" : "", - tep.t_sup_active ? " AppNap" : "", - tep.lowpri_cpu ? " LowPri" : "", - tep.io_passive ? " IOPass" : "", - tep.all_sockets_bg ? " ASckBG" : "", - tep.new_sockets_bg ? " NSckBG" : "", - tep.terminated ? " Term" : "", - tep.qos_ui_is_urgent ? " QOSUiIsUrg" : ""); - - print_base_empty(buffer, globals, event_index, "thread_teffective", false); - buffer.printf("%s (%d) %llX is QOS:%s QOS_relprio:%d\n", - target_name, thread->process().pid(), (uint64_t)thread->tid(), - qos_to_string(tep.thep_qos), - tep.thep_qos_relprio); -} - -template -void print_importance_apptype(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, "set_apptype", false); - - // - // trace args are: - // - // selfpid, targetpid, trequested(targetpid, NULL), is_importance_receiver - - // - // QoS clamp - // - // Can only be determined on K64, the bits needed are trimmed off in - // K32 tracepoints. - - char qos_clamp[32]; - qos_clamp[0] = 0; - if (SIZE::is_64_bit) { - uint32_t qos_level = (event.arg3() & POLICY_REQ_QOS_CLAMP_MASK) >> POLICY_REQ_QOS_CLAMP_SHIFT; - if (qos_level != THREAD_QOS_UNSPECIFIED) { - snprintf(qos_clamp, sizeof(qos_clamp), ", clamped to %s", qos_to_string(qos_level)); - } - } - - pid_t target_pid = (pid_t)event.arg2(); - const char* target_name; - - if (target_pid != -1 ) { - if (const MachineProcess* target = machine.process(target_pid, event.timestamp())) { - target_name = target->name(); - } else { - target_name = "???"; - } - } else { - target_name = "NULL-Task"; - } - - const char* apptype = "???"; - switch (event.dbg_code()) { - case TASK_APPTYPE_NONE: - apptype = "None"; - break; - case TASK_APPTYPE_DAEMON_INTERACTIVE: - apptype = "InteractiveDaemon"; - break; - case TASK_APPTYPE_DAEMON_STANDARD: - apptype = "StandardDaemon"; - break; - case TASK_APPTYPE_DAEMON_ADAPTIVE: - apptype = "AdaptiveDaemon"; - break; - case TASK_APPTYPE_DAEMON_BACKGROUND: - apptype = "BackgroundDaemon"; - break; - case TASK_APPTYPE_APP_DEFAULT: - apptype = "App"; - break; - case TASK_APPTYPE_APP_TAL: - apptype = "TALApp"; - break; - default: - break; - } - - const char* imp_recv = ""; - if (event.arg4()) { - imp_recv = ", receives importance"; - } - buffer.printf("Set %s (%d) to %s%s%s\n", target_name, target_pid, apptype, imp_recv, qos_clamp); -} - -template -void print_importance_update_task(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const char* type, - std::unordered_map>& task_effective_state) -{ - // - // event args are: - // - // targetpid, teffective_0(task, NULL), teffective_1(task, NULL), tpriority(task, THREAD_NULL) - // - auto pid = (pid_t)event.arg1(); - auto teffective_0 = event.arg2(); - auto teffective_1 = event.arg3(); - auto priority = (uint32_t)event.arg4(); - auto task_effective_policy = (SIZE::is_64_bit) ? TaskEffectivePolicy(teffective_0) : TaskEffectivePolicy((Kernel32::ptr_t)teffective_0, (Kernel32::ptr_t)teffective_1); - auto state = std::pair(task_effective_policy, priority); - auto should_print = false; - - ASSERT(pid != -1, "Sanity"); - - // Verify that some state changed before printing. - auto it = task_effective_state.find(pid); - if (it == task_effective_state.end()) { - should_print = true; - task_effective_state.emplace(pid, state); - } else { - if (it->second != state) { - should_print = true; - it->second = state; - } - } - - if (should_print) { - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, type, false); - - const char* name; - if (auto target = machine.process(pid, event.timestamp())) { - name = target->name(); - } else { - name = "???"; - } - - buffer.printf("%s (%d) base priority is %d\n", name, pid, priority); - - print_teffective_task(buffer, globals, machine, event, event_index, pid, task_effective_policy); - } -} - -template -void print_importance_update_thread(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const char* type, - std::unordered_map>& thread_effective_state) -{ - // - // event args are: - // - // targettid, teffective_0(task, thread), teffective_1(task, thread), tpriority(task, thread) - // - - if (const MachineThread* thread = machine.thread(event.arg1(), event.timestamp())) { - auto pid = thread->process().pid(); - auto teffective_0 = event.arg2(); - auto teffective_1 = event.arg3(); - auto priority = (uint32_t)event.arg4(); - auto thread_effective_policy = (SIZE::is_64_bit) ? TaskEffectivePolicy(teffective_1) : TaskEffectivePolicy((Kernel32::ptr_t)teffective_0, (Kernel32::ptr_t)teffective_1); - auto state = std::pair(thread_effective_policy, priority); - auto should_print = false; - - // Verify that some state changed before printing. - auto it = thread_effective_state.find(thread->tid()); - if (it == thread_effective_state.end()) { - should_print = true; - thread_effective_state.emplace(thread->tid(), state); - } else { - if (it->second != state) { - should_print = true; - it->second = state; - } - } - - if (should_print) { - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, type, false); - buffer.printf("%s (%d) %llX base priority is %d\n", thread->process().name(), pid, (uint64_t)thread->tid(), priority); - - print_teffective_thread(buffer, globals, machine, event, event_index, thread, thread_effective_policy); - } - } -} - -template -void print_fork(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const MachineProcess& child_process) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, "fork", false); - - // - // Other process - // - - buffer.printf("Create %s (%d)\n", child_process.name(), child_process.pid()); -} - -template -void print_exit(PrintBuffer& buffer, - const Globals& globals, - const KDEvent& event, - const MachineThread* thread, - uintptr_t event_index) -{ - ASSERT(thread, "Sanity"); - - print_base(buffer, globals, event.timestamp(), thread, event, event_index, "exit", false); - - // - // exit code - // - - int exit_status = thread->process().exit_status(); - - if (WIFEXITED(exit_status)) { - buffer.printf("returned %d\n", WEXITSTATUS(exit_status)); - } else if (WIFSIGNALED(exit_status)) { - buffer.printf("SIGNAL: %s\n", strsignal(WTERMSIG(exit_status))); - } else { - buffer.printf("Unhandled exit status %x\n", (uint32_t)exit_status); - } -} - -template -void print_voucher(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const char* type, - const MachineVoucher* voucher, - bool is_create) -{ - print_base(buffer, globals, event.timestamp(), machine.thread(event.tid(), event.timestamp()), event, event_index, type, false); - - // - // Calculate lifetime - // - - char lifetime[32]; - AbsInterval timespan = voucher->timespan(); - - // - // Voucher created before the trace starts will have a starting time - // of 0; Vouchers that are still alive will have a max of UINT64_MAX. - // - if (timespan.location() == AbsTime(0) || timespan.max() == AbsTime(UINT64_MAX)) { - snprintf(lifetime, sizeof(lifetime), "???"); - } else { - NanoTime t1 = timespan.length().nano_time(globals.timebase()); - snprintf(lifetime, sizeof(lifetime), "%0.2f", (double)t1.value() / NANOSECONDS_PER_MICROSECOND); - } - - - // - // Voucher addr - // - if (is_create) { - buffer.printf("Create voucher-%u @ %llX, lifetime will be %s µs, now %u vouchers\n", voucher->id(), (uint64_t)voucher->address(), lifetime, (uint32_t)event.arg3()); - } else { - buffer.printf("Destroy voucher-%u @ %llX, lifetime was %s µs, now %u vouchers\n", voucher->id(), (uint64_t)voucher->address(), lifetime, (uint32_t)event.arg3()); - } -} - -template -void print_voucher_contents(PrintBuffer& buffer, - const Globals& globals, - const Machine& machine, - const KDEvent& event, - uintptr_t event_index, - const MachineVoucher* voucher) -{ - const uint8_t* bytes = voucher->content_bytes(); - uint32_t bytes_required = voucher->content_size(); - - ASSERT(bytes_required, "Printing empty voucher"); - - unsigned int used_size = 0; - mach_voucher_attr_recipe_t recipe = NULL; - while (bytes_required > used_size) { - recipe = (mach_voucher_attr_recipe_t)&bytes[used_size]; - - switch (recipe->key) { - case MACH_VOUCHER_ATTR_KEY_NONE: - ASSERT(false, "No key in recipe"); - break; - - case MACH_VOUCHER_ATTR_KEY_ATM: - print_base_empty(buffer, globals, event_index, "voucher_create", false); - buffer.printf(" voucher-%u | ATM ID %llu\n", voucher->id(), *(uint64_t *)(uintptr_t)recipe->content); - break; - - case MACH_VOUCHER_ATTR_KEY_IMPORTANCE: - print_base_empty(buffer, globals, event_index, "voucher_create", false); - buffer.printf(" voucher-%u | %s\n", voucher->id(), (char *)recipe->content); - break; - - case MACH_VOUCHER_ATTR_KEY_BANK: - // Spacing and newline is different because that is how BANK formats it :-( - print_base_empty(buffer, globals, event_index, "voucher_create", false); - buffer.printf(" voucher-%u |%s", voucher->id(), (char *)recipe->content); - break; - - case MACH_VOUCHER_ATTR_KEY_USER_DATA: - for (uint32_t offset=0; offsetcontent_size; offset += 16) { - uint8_t* data = ((uint8_t*)recipe->content) + offset; - size_t data_remaining = std::min(recipe->content_size - offset, (uint32_t)16); - - print_base_empty(buffer, globals, event_index, "voucher_create", false); - buffer.printf(" voucher-%u | UserData: %04u ", voucher->id(), offset); - - // 16 * 3 == 48, 16 chars to spare - char hex_buffer[64]; - // Hex data. - for (uint32_t cursor = 0; cursorid(), recipe->key, recipe->command, recipe->content_size); - break; - } - - used_size += sizeof(mach_voucher_attr_recipe_data_t) + recipe->content_size; - } -} - -#endif /* defined(__msa__MessagePrinting__) */ diff --git a/msa/ReadTraceFileAction.cpp b/msa/ReadTraceFileAction.cpp deleted file mode 100644 index a1e0746..0000000 --- a/msa/ReadTraceFileAction.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// ReadTraceFileAction.cpp -// msa -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include "global.h" - -template -static void execute_arch_specific(Globals& globals, TraceFile& file) -{ - Machine machine(file); - - if (!machine.lost_events()) { - if (globals.should_zero_base_timestamps() && machine.event_count()) { - globals.set_beginning_of_time(machine.events()[0].timestamp()); - } else { - globals.set_beginning_of_time(AbsTime(0)); - } - - if (!globals.is_timebase_set()) { - if (machine.is_ios()) { - globals.set_timebase({ 125, 3 }, false); - } else { - globals.set_timebase({ 1, 1 }, false); - } - } - - char buf[PATH_MAX]; - char* buf_end = buf + sizeof(buf); - print_mach_msg_header(buf, buf_end, globals); - dprintf(globals.output_fd(), "%s", buf); - - std::unordered_map task_appnap_state; - std::unordered_map task_requested_state; - std::unordered_map thread_requested_state; - std::unordered_map> task_effective_state; - std::unordered_map> thread_effective_state; - std::unordered_map> task_boosts; - - process_events(globals, machine, task_appnap_state, task_requested_state, thread_requested_state, task_effective_state, thread_effective_state, task_boosts); - } else { - log_msg(ASL_LEVEL_WARNING, "The trace data indicates that events were lost, the file cannot be processed\n"); - } -} - -void ReadTraceFileAction::execute(Globals& globals) { - TraceFile file(_path.c_str(), globals.should_presort_events(), globals.cpu_count(), globals.iop_count()); - if (globals.is_kernel_size_set()) { - try { - if (globals.kernel_size() == KernelSize::k32) - execute_arch_specific(globals, file); - else - execute_arch_specific(globals, file); - } catch (Exception& e) { - log_msg(ASL_LEVEL_ERR, "An exception was raised: %s", e.what()); - log_msg(ASL_LEVEL_ERR, "An explicit kernel size was set, you may want to try not forcing the size to a single value\n"); - log_msg(ASL_LEVEL_ERR, "You may also want to check the number of cpus and iops configured if the file is from a device and does not have a cpumap\n"); - } - } else { - if (file.is_valid()) { - if (file.is_64_bit()) { - execute_arch_specific(globals, file); - } else { - execute_arch_specific(globals, file); - } - } else { - if (file.mmap_failed()) { - log_msg(ASL_LEVEL_ERR, "Unable to mmap %s, it may exceed this devices memory limits\n", _path.c_str()); - } else { - log_msg(ASL_LEVEL_ERR, "%s does not appear to be a valid trace file\n", _path.c_str()); - } - } - } -} diff --git a/msa/ReadTraceFileAction.hpp b/msa/ReadTraceFileAction.hpp deleted file mode 100644 index 3577bfb..0000000 --- a/msa/ReadTraceFileAction.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// ReadTraceFileAction.hpp -// msa -// -// Created by James McIlree on 4/15/13. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef __kdprof__TraceFileAction__ -#define __kdprof__TraceFileAction__ - -class ReadTraceFileAction : public Action { - protected: - std::string _path; - - public: - ReadTraceFileAction(const char* path) : _path(path) { - ASSERT(Path::is_file(_path, TRUE), "File must exist"); - } - - virtual void execute(Globals& globals); -}; - -#endif /* defined(__msa__TraceFileAction__) */ diff --git a/msa/VoucherContentSysctl.cpp b/msa/VoucherContentSysctl.cpp deleted file mode 100644 index c2282e8..0000000 --- a/msa/VoucherContentSysctl.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// -// VoucherContentSysctl.cpp -// system_cmds -// -// Created by James McIlree on 4/29/14. -// -// - -#include "global.h" - -VoucherContentSysctl::VoucherContentSysctl(bool is_enabled) : - _original_value(0), - _new_value(is_enabled ? 1 : 0) -{ - size_t original_value_size = sizeof(_original_value); - if (sysctlbyname("kern.ipc_voucher_trace_contents", &_original_value, &original_value_size, &_new_value, sizeof(_new_value))) { - log_msg(ASL_LEVEL_ERR, "Unable to %s kern.ipc_voucher_trace_contents sysctl", is_enabled ? "set" : "clear"); - } -} - -VoucherContentSysctl::~VoucherContentSysctl() { - if (_original_value != _new_value) { - if (sysctlbyname("kern.ipc_voucher_trace_contents", NULL, 0, &_original_value, sizeof(_original_value))) { - log_msg(ASL_LEVEL_ERR, "Unable to restore original value of kern.ipc_voucher_trace_contents sysctl"); - } - } -} diff --git a/msa/VoucherContentSysctl.hpp b/msa/VoucherContentSysctl.hpp deleted file mode 100644 index 8909a9d..0000000 --- a/msa/VoucherContentSysctl.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// VoucherContentSysctl.hpp -// system_cmds -// -// Created by James McIlree on 4/29/14. -// -// - -#ifndef __system_cmds__VoucherContentSysctl__ -#define __system_cmds__VoucherContentSysctl__ - -// -// This class is used to manage the voucher contents sysctl -class VoucherContentSysctl { - protected: - int _original_value; - int _new_value; - - public: - VoucherContentSysctl(bool is_enabled); - ~VoucherContentSysctl(); -}; - -#endif /* defined(__system_cmds__VoucherContentSysctl__) */ diff --git a/msa/WriteTraceFileAction.cpp b/msa/WriteTraceFileAction.cpp deleted file mode 100644 index 65c63c8..0000000 --- a/msa/WriteTraceFileAction.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// WriteTraceFileAction.cpp -// system_cmds -// -// Created by James McIlree on 4/29/14. -// -// - -#include "global.h" - -static bool shouldProcessEvents; -static uint32_t sigintCount; - -static bool start_tracing(Globals& globals) -{ - if (!KDBG::reset()) return false; - if (!KDBG::set_buffer_capacity(globals.trace_buffer_size())) return false; - if (!KDBG::set_nowrap(false)) return false; - if (!KDBG::initialize_buffers()) return false; - if (!KDBG::set_enabled(KDEBUG_ENABLE_TRACE)) return false; - - return true; -} - -static void end_tracing(void) -{ - KDBG::reset(); -} - -static void signal_handler_ctrl_C(int sig) -{ - shouldProcessEvents = false; - if (++sigintCount >= 5) { - // Not responding, nuke it from orbit. - exit(1); - } -} - -void WriteTraceFileAction::execute(Globals& globals) { - FileDescriptor fd(open(_path.c_str(), O_TRUNC|O_WRONLY|O_CREAT, 0777)); - if (!fd.is_open()) { - log_msg(ASL_LEVEL_ERR, "Unable to write to %s\n", _path.c_str()); - return; - } - - shouldProcessEvents = true; - sigintCount = 0; - - VoucherContentSysctl contents(globals.should_trace_voucher_contents()); - - AbsTime t1 = AbsTime::now(); - if (start_tracing(globals)) { - // We cannot write the "maps" until after tracing has started. - if (KDBG::write_maps(fd)) { - signal(SIGINT, signal_handler_ctrl_C); - - while (shouldProcessEvents) { - int events_written = KDBG::write_events(fd); - AbsTime t2 = AbsTime::now(); - if (events_written != -1) { - printf("wrote %d events - elapsed time = %.1f secs\n", events_written, (double)(t2 - t1).nano_time().value() / (double)NANOSECONDS_PER_SECOND); - } else { - log_msg(ASL_LEVEL_WARNING, "write events returned -1\n"); - break; - } - t1 = t2; - } - - signal(SIGINT, SIG_DFL); - } - } - - end_tracing(); -} diff --git a/msa/WriteTraceFileAction.hpp b/msa/WriteTraceFileAction.hpp deleted file mode 100644 index 74fb83e..0000000 --- a/msa/WriteTraceFileAction.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// WriteTraceFileAction.hpp -// system_cmds -// -// Created by James McIlree on 4/29/14. -// -// - -#ifndef __system_cmds__WriteTraceFileAction__ -#define __system_cmds__WriteTraceFileAction__ - -class WriteTraceFileAction : public Action { - protected: - std::string _path; - - public: - WriteTraceFileAction(const char* path) : - _path(path) - { - ASSERT(path, "Sanity"); - } - - virtual void execute(Globals& globals); -}; - -#endif /* defined(__system_cmds__WriteTraceFileAction__) */ diff --git a/msa/global.h b/msa/global.h deleted file mode 100644 index 6011940..0000000 --- a/msa/global.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// global.h -// msa -// -// Created by James McIlree on 2/1/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#ifndef msa_global_h -#define msa_global_h - -#include - -using namespace util; - -#include - -#include - -#include - -#include -#include -#include -#include - -__attribute__((noreturn)) void usage(const char *); - -#include "Globals.hpp" -#include "EventRingBuffer.hpp" -#include "PrintBuffer.hpp" -#include "Action.hpp" -#include "ReadTraceFileAction.hpp" -#include "WriteTraceFileAction.hpp" -#include "LiveTraceAction.hpp" -#include "Printing.hpp" -#include "EventProcessing.hpp" -#include "VoucherContentSysctl.hpp" - -#endif diff --git a/msa/main.cpp b/msa/main.cpp deleted file mode 100644 index 7780850..0000000 --- a/msa/main.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// -// main.cpp -// msa -// -// Created by James McIlree on 1/30/14. -// Copyright (c) 2014 Apple. All rights reserved. -// - -#include - -#include "global.h" - -bool isVerbose = true; -bool shouldPrintVersion = true; -std::vector procsOfInterest; -bool interestedInEverything = false; - -__attribute__((noreturn)) void usage(const char *errorMsg) { - if (errorMsg) { - printf("%s\n", errorMsg); - exit(1); - } - - // const char* BOLD = "\033[1m"; - // const char* UNBOLD = "\033[0m"; - - // printf("01234567890123456789012345678901234567890123456789012345678901234567890123456789\n"); - printf("msa [options]\n\n"); - printf(" GLOBAL OPTIONS\n\n"); - printf(" -h, --help Print this message\n"); - printf(" --verbose Print additional information\n"); - printf(" --version Print version info\n"); - printf("\n"); - printf(" TRACE COLLECTION OPTIONS\n\n"); - printf(" -i, --initialize # Set the size of the kernel trace buffer\n"); - printf(" --no-voucher-contents Disable collecting voucher contents\n"); - printf(" -L path Capture and save trace output to path\n"); - printf("\n"); - printf(" OUTPUT OPTIONS\n\n"); - printf(" --lifecycle all|user|none\n"); - printf(" Set filter level for lifecycle events\n"); - printf(" --mach-msg all|user|voucher|none\n"); - printf(" Set filter level for mach msg events\n"); - printf(" -o, --output path Print output to path\n"); - printf(" --raw-timestamps Print timestamps as raw values, not deltas\n"); - printf(" --mach-absolute-time Print timestamps in mach absolute time\n"); - printf(" --event-index Print the index of each event\n"); - printf("\n"); - exit(1); -} - -template -static bool check_interest_name(const MachineProcess& process) { - if (interestedInEverything) - return true; - - const char* name = process.name(); - for (auto& proc : procsOfInterest) { - if (strcmp(name, proc.c_str()) == 0) - return true; - } - - return false; -} - -static std::unique_ptr create_read_trace_file_action(const char* trace_file_path) { - if (Path::is_file(trace_file_path, true)) { - char resolved_path[PATH_MAX]; - if (realpath(trace_file_path, resolved_path)) { - return std::make_unique(resolved_path); - } - } - char* errmsg = NULL; - asprintf(&errmsg, "%s does not exist or is not a file", trace_file_path); - usage(errmsg); -} - -static std::vector> parse_arguments(int argc, const char* argv[], Globals& globals) { - int i = 1; - - std::vector> actions; - - while (i < argc) { - const char* arg = argv[i]; - if ((strcmp(arg, "-h") == 0) || (strcasecmp(arg, "--help") == 0)) { - usage(NULL); - } else if ((strcmp(arg, "-v") == 0) || strcasecmp(arg, "--verbose") == 0) { - globals.set_is_verbose(true); - } else if (strcasecmp(arg, "--version") == 0) { - shouldPrintVersion = true; - } else if ((strcmp(arg, "-i") == 0) || strcasecmp(arg, "--initialize") == 0) { - if (++i >= argc) - usage("--initialize requires an argument"); - - arg = argv[i]; - char* endptr; - uint32_t temp = (uint32_t)strtoul(arg, &endptr, 0); - if (*endptr == 0) { - globals.set_trace_buffer_size(temp); - } else { - usage("Unable to parse --initialize argument"); - } - } else if (strcasecmp(arg, "--no-voucher-contents") == 0) { - globals.set_should_trace_voucher_contents(false); - } else if (strcasecmp(arg, "-L") == 0) { - if (++i >= argc) - usage("-L requires an argument"); - - arg = argv[i]; - actions.push_back(std::make_unique(arg)); - } else if (strcasecmp(arg, "--lifecycle") == 0) { - if (++i >= argc) - usage("--lifecycle requires an argument"); - - arg = argv[i]; - if (strcasecmp(arg, "all") == 0) { - globals.set_lifecycle_filter(kLifecycleFilter::All); - } else if (strcasecmp(arg, "user") == 0) { - globals.set_lifecycle_filter(kLifecycleFilter::User); - } else if (strcasecmp(arg, "none") == 0) { - globals.set_lifecycle_filter(kLifecycleFilter::None); - } else { - usage("Unrecognized --lifecycle value"); - } - } else if (strcasecmp(arg, "--mach-msg") == 0) { - if (++i >= argc) - usage("--mach-msg requires an argument"); - - arg = argv[i]; - if (strcasecmp(arg, "all") == 0) { - globals.set_mach_msg_filter(kMachMsgFilter::All); - } else if (strcasecmp(arg, "user") == 0) { - globals.set_mach_msg_filter(kMachMsgFilter::User); - } else if (strcasecmp(arg, "voucher") == 0) { - globals.set_mach_msg_filter(kMachMsgFilter::Voucher); - } else if (strcasecmp(arg, "none") == 0) { - globals.set_mach_msg_filter(kMachMsgFilter::None); - } else { - usage("Unrecognized --mach-msg value"); - } - } else if ((strcmp(arg, "-o") == 0) || strcasecmp(arg, "--output") == 0) { - if (++i >= argc) - usage("--output requires an argument"); - - FileDescriptor desc(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (!desc.is_open()) { - char* errmsg = NULL; - asprintf(&errmsg, "Unable to create output file at %s", argv[i]); - usage(errmsg); - } - globals.set_output_fd(std::move(desc)); - } else if (strcasecmp(arg, "--raw-timestamps") == 0) { - globals.set_should_zero_base_timestamps(false); - } else if (strcasecmp(arg, "--mach-absolute-time") == 0) { - globals.set_should_print_mach_absolute_timestamps(true); - } else if (strcasecmp(arg, "--event-index") == 0) { - globals.set_should_print_event_index(true); - } else { - // - // Last attempts to divine argument type/intent. - // - std::string temp(arg); - - if (ends_with(temp, ".trace")) { - actions.push_back(create_read_trace_file_action(argv[i])); - goto no_error; - } - - // - // ERROR! - // - char error_buffer[PATH_MAX]; - snprintf(error_buffer, sizeof(error_buffer), "Unhandled argument: %s", arg); - usage(error_buffer); - } - - no_error: - - i++; - } - - if (actions.empty()) { - actions.push_back(std::make_unique()); - } - - return actions; -} - -int main(int argc, const char * argv[]) -{ - // - // Use host values as defaults. - // User overrides as needed via flags. - // - Globals globals; - auto actions = parse_arguments(argc, argv, globals); - - interestedInEverything = procsOfInterest.empty(); - - // globals.set_should_print_mach_absolute_timestamps(true); - - for (auto& action : actions) { - action->execute(globals); - } - - return 0; -} - diff --git a/msa/msa.1 b/msa/msa.1 deleted file mode 100644 index 27f011d..0000000 --- a/msa/msa.1 +++ /dev/null @@ -1,154 +0,0 @@ -.Dd 3/7/14 -.Dt msa 1 -.Os Darwin -.Sh NAME -.Nm msa -.Nd Mach spy agency. Shows mach ipc, vouchers, importance boosts, etc. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl ho -.Op Fl -help -.Op Fl -verbose -.Op Fl -version -.Op Fl -lifecycle Ar all | user | none -.Op Fl -mach-msg Ar all | user | voucher | none -.Op Fl -ouput Ar file -.Op Fl -raw-timestamps -.Op Fl -mach-absolute-time -.Op Fl -event-index -.Op Ar -.Sh DESCRIPTION -The -.Nm -command is used to observe voucher and importance propagation. -.Nm -displays mach message senders and receivers, message state (voucher, importance, reply expected, etc.) and receiver behavior such as refusing a voucher. -.Nm -shows process & thread lifecycle events, adoption & clearing of vouchers by threads, process importance count changes, and process DarwinBG state. -.Nm -uses the kernel trace facility and can be run live or against saved trace files. -.Pp -Options are as follows: -.Pp - -.Bl -tag -width -indent -.It Fl h, -help -Print help. -.It Fl -verbose -Print additional details and output. -.It Fl -version -Print version info. -.It Fl -lifecycle Ar all | user | none -Set the process and thread lifecycle filter level. The default is "user". -.Bl -tag -width -indent -.It all -Show kernel & userspace process and thread events -.It user -Show userspace process and thread events -.It none -Show no process and thread events -.El -.It Fl -mach-msg Ar all | user | voucher | none -Set the mach message sender/receiver filter level. The default is "voucher". -.Bl -tag -width -indent -.It all -Show all mach message senders/receivers -.It user -Show mach message senders/receivers where both the sender and receiver are in userspace -.It voucher -Show "interesting" mach message senders/receivers. An "interesting" message is any message containing a voucher, any message not containing a voucher if the sending thread has adopted a voucher, and any message carrying importance. -.It none -Show no mach message senders/receivers -.El -.It Fl o, -output Ar file -Write output to -.Ar file -.It Fl -raw-timestamps -Do not show time as a delta from the first trace event, print the actual time offsets. -.It Fl -mach-absolute-time -Do not translate time from mach absolute units to nanoseconds. -.It Fl -event-index -Print the index of each event. -.El -.Sh OUTPUT -.Nm -displays columns of data, the first five columns are fixed. The data after the fifth column depends on the type of event. Example output below (your terminal will need to be at least 200 characters wide to display this correctly): - - Time(uS) Type Thread ThreadVoucher Process ;; Message-From/To MsgID MsgVoucher DeliveryTime FLAGS - 9304.56 send 8C2 - coreaudiod (236) ;; -> coreaudiod (236) 2 - - ONEWAY - 9346.52 impdelv 8A6 - coreaudiod (236) ;; linked to coreaudiod (236)'s live importance chain - 9349.02 recv 8A6 - coreaudiod (236) ;; <- coreaudiod (236) 2 5EBD6CB68FF6401F 44.46 - 9361.50 adopt 8A6 5EBD6CB68FF6401F coreaudiod (236) ;; - -.Bl -tag -width -indent -.It The column headers have the following meanings: -.Bl -tag -width -indent -.It Time -The Time column displays the number of microseconds elapsed since -.Nm -started, or since the first event in the trace file. This value may be modified by -.Fl -raw-timestamps -or -.Fl -mach-absolute-time. -You might set these flags in order to correlate timestamps with output from another process that was printing mach_absolute_time() based timestamps. -.It Type -This describes the type of event being reported. Information to the right of the ';;' will vary based on this type. -.It Thread -The Thread column shows the thread id of the thread that generated the event. This is the thread id as displayed by -.Xr trace 1 -and -.Xr kdprof 1 -and may be cross correlated with trace events shown by either. Note that in some cases a thread in process A may cause changes in process B, for example a thread in Safari might raise the importance of a daemon. -.It ThreadVoucher -The ThreadVoucher column shows the id of any voucher currently adopted by the thread. This voucher id is the same identifier as shown by -.Xr lsmp 1 . -A '-' means that -.Nm -has not yet seen a voucher adopt for the thread. A NULL voucher is displayed as '0'. -.It Process -The Process column shows the name and pid of the process executing. The name is limited to 16 characters and may appear truncated. -.El -.It Mach message send/recv have the following additional column headers: -.Bl -tag -width -indent -.It Message-From/To -This field shows either the sender or the recipient of the message. The arrow at the beginning will indicate the direction the message is flowing. A '->' means sent to, a '<-' means received from. The name of the sender or recipient is limited to 16 characters and may appear truncated. Rarely, you may see '???' as the name, which means -.Nm -was unable to determine the source or destination of the message. -.It MsgID -The MsgID is a unique identifier for each mach message. A mach message has exactly one sender, and one receiver. However, a sending process may send several messages to a receiver before any are received. The MsgID allows disambiguation of exact message send and receipt time. -.It MsgVoucher -If this field is set, it shows the id of the voucher being carried by the mach message. Note that in some cases, the sender will show no voucher, but the receiver will have a voucher. This is the kernel providing a voucher for a process sending "old style" importance to a process that wants to receive vouchers. -.It DeliveryTime -This is the time it took to deliver the message, in uS. If the time cannot be calculated, it will show as '-'. -.It FLAGS -The FLAGS field will indicate various mach message behaviors: -.Bl -tag -width -indent -.It ONEWAY -This message cannot be replied to -.It MSGH_BITS_RAISED_IMPORTANCE -This message carries "old style" importance -.It VOUCHER-REFUSED -The message carried a voucher, and the receiver refused to accept it -.El -.El -.El -.Sh EXAMPLES -.Bl -tag -width -indent -.It Here are several examples of usage: -.Bl -tag -width -indent -.It msa | grep BOOST -This will show live boost/unboost behavior. Useful for watching what UI interactions will cause boosting. -.It msa | grep -e APP-NAME -e DAEMON-NAME -e OTHER-DAEMON-NAME -This will restrict output to only events dealing with an app and targetted daemons. This is useful to reduce the amount of data you need to watch. -.It trace -L /tmp/temp.trace; msa /tmp/temp.trace -This uses trace to capture a trace file for later analysis by msa. -.El -.El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr kdprof 1 , -.Xr lsmp 1, -.Xr trace 1 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/newgrp.tproj/newgrp.c b/newgrp.tproj/newgrp.c index d0004f7..3a4f412 100644 --- a/newgrp.tproj/newgrp.c +++ b/newgrp.tproj/newgrp.c @@ -158,7 +158,9 @@ addgroup(const char *grpname) gid_t egid; struct group *grp; char *ep, *pass; +#ifndef __APPLE__ char **p; +#endif char *grp_passwd; #ifdef __APPLE__ uuid_t user_uuid; @@ -218,7 +220,7 @@ addgroup(const char *grpname) ngrps_max = sysconf(_SC_NGROUPS_MAX) + 1; if ((grps = malloc(sizeof(gid_t) * ngrps_max)) == NULL) err(1, "malloc"); - if ((ngrps = getgroups(ngrps_max, (gid_t *)grps)) < 0) { + if ((ngrps = getgroups((int)ngrps_max, (gid_t *)grps)) < 0) { warn("getgroups"); goto end; } diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index fc6a24a..96d2c0b 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,7 @@ cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall #include #include #include +#include // Prototypes static void UsageMessage(char *message); @@ -62,23 +63,24 @@ int main(int argc, char **argv) char *str, errorMessage[256]; kern_return_t result; mach_port_t masterPort; - + int argcount = 0; + // Get the name of the command. gToolName = strrchr(argv[0], '/'); if (gToolName != 0) gToolName++; else gToolName = argv[0]; - + result = IOMasterPort(bootstrap_port, &masterPort); if (result != KERN_SUCCESS) { errx(1, "Error getting the IOMaster port: %s", mach_error_string(result)); } - + gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options"); if (gOptionsRef == 0) { errx(1, "nvram is not supported on this system"); } - + for (cnt = 1; cnt < argc; cnt++) { str = argv[cnt]; if (str[0] == '-' && str[1] != 0) { @@ -101,7 +103,7 @@ int main(int argc, char **argv) UsageMessage("missing filename"); } break; - + case 'd': cnt++; if (cnt < argc && *argv[cnt] != '-') { @@ -110,7 +112,7 @@ int main(int argc, char **argv) UsageMessage("missing name"); } break; - + case 'c': ClearOFVariables(); break; @@ -127,12 +129,18 @@ int main(int argc, char **argv) } } else { // Other arguments will be firmware variable requests. + argcount++; SetOrGetOFVariable(str); } } - + + // radar:25206371 + if (argcount == 0 && gUseForceSync == true) { + NVRamSyncNow(""); + } + IOObjectRelease(gOptionsRef); - + return 0; } @@ -143,7 +151,7 @@ int main(int argc, char **argv) static void UsageMessage(char *message) { warnx("(usage: %s)", message); - + printf("%s [-x] [-p] [-f filename] [-d name] [-c] name[=value] ...\n", gToolName); printf("\t-x use XML format for printing or reading variables\n"); printf("\t (must appear before -p or -f)\n"); @@ -154,7 +162,7 @@ static void UsageMessage(char *message) printf("\tname=value set named variable\n"); printf("\tname print variable\n"); printf("Note that arguments and options are executed in order.\n"); - + exit(1); } @@ -169,7 +177,7 @@ enum { kCollectValue, kContinueValue, kSetenv, - + kMaxStringSize = 0x800, kMaxNameSize = 0x100 }; @@ -181,7 +189,8 @@ enum { // static void ParseFile(char *fileName) { - long state, tc, ni = 0, vi = 0; + long state, ni = 0, vi = 0; + int tc; char name[kMaxNameSize]; char value[kMaxStringSize]; FILE *patches; @@ -191,15 +200,15 @@ static void ParseFile(char *fileName) ParseXMLFile(fileName); return; } - + patches = fopen(fileName, "r"); if (patches == 0) { err(1, "Couldn't open patch file - '%s'", fileName); } - + state = kFirstColumn; while ((tc = getc(patches)) != EOF) { - if(ni==(kMaxNameSize-1)) + if(ni==(kMaxNameSize-1)) errx(1, "Name exceeded max length of %d", kMaxNameSize); if(vi==(kMaxStringSize-1)) errx(1, "Value exceeded max length of %d", kMaxStringSize); @@ -218,7 +227,7 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kScanComment : if (tc == '\n') { state = kFirstColumn; @@ -226,7 +235,7 @@ static void ParseFile(char *fileName) // state stays kScanComment. } break; - + case kFindName : if (tc == '\n') { state = kFirstColumn; @@ -237,7 +246,7 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kCollectName : if (tc == '\n') { name[ni] = 0; @@ -250,7 +259,7 @@ static void ParseFile(char *fileName) // state staus kCollectName. } break; - + case kFindValue : case kContinueValue : if (tc == '\n') { @@ -262,7 +271,7 @@ static void ParseFile(char *fileName) value[vi++] = tc; } break; - + case kCollectValue : if (tc == '\n') { if (value[vi-1] == '\\') { @@ -277,7 +286,7 @@ static void ParseFile(char *fileName) } break; } - + if (state == kSetenv) { name[ni] = 0; value[vi] = 0; @@ -288,13 +297,12 @@ static void ParseFile(char *fileName) state = kFirstColumn; } } - + if (state != kFirstColumn) { errx(1, "Last line ended abruptly"); } } - // ParseXMLFile(fileName) // // Open and parse the specified file in XML format, @@ -303,55 +311,64 @@ static void ParseFile(char *fileName) static void ParseXMLFile(char *fileName) { CFPropertyListRef plist; - CFURLRef fileURL = NULL; - CFStringRef filePath = NULL; - CFStringRef errorString = NULL; - CFDataRef data = NULL; - SInt32 errorCode = 0; - - filePath = CFStringCreateWithCString(kCFAllocatorDefault, fileName, kCFStringEncodingUTF8); - if (filePath == NULL) { - errx(1, "Could not create file path string"); + int fd; + struct stat sb; + char *buffer; + CFReadStreamRef stream; + CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0; + + fd = open(fileName, O_RDONLY | O_NOFOLLOW, S_IFREG); + if (fd == -1) { + errx(1, "Could not open %s: %s", fileName, strerror(errno)); } - // Create a URL that specifies the file we will create to - // hold the XML data. - fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, - filePath, - kCFURLPOSIXPathStyle, - false /* not a directory */ ); - if (fileURL == NULL) { - errx(1, "Could not create file path URL"); + if (fstat(fd, &sb) == -1) { + errx(1, "Could not fstat %s: %s", fileName, strerror(errno)); } - CFRelease(filePath); + if (sb.st_size > UINT32_MAX) { + errx(1, "too big for our purposes"); + } - if (! CFURLCreateDataAndPropertiesFromResource( - kCFAllocatorDefault, - fileURL, - &data, - NULL, - NULL, - &errorCode) || data == NULL ) { - errx(1, "Error reading XML file (%d)", (int)errorCode); + buffer = malloc((size_t)sb.st_size); + if (buffer == NULL) { + errx(1, "Could not allocate buffer"); } - CFRelease(fileURL); + if (read(fd, buffer, (size_t)sb.st_size) != sb.st_size) { + errx(1, "Could not read %s: %s", fileName, strerror(errno)); + } - plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, - data, - kCFPropertyListImmutable, - &errorString); + close(fd); - CFRelease(data); + stream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, + (const UInt8 *)buffer, + (CFIndex)sb.st_size, + kCFAllocatorNull); + if (stream == NULL) { + errx(1, "Could not create stream from serialized data"); + } + + if (!CFReadStreamOpen(stream)) { + errx(1, "Could not open the stream"); + } + + plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, + stream, + (CFIndex)sb.st_size, + kCFPropertyListImmutable, + &format, + NULL); if (plist == NULL) { errx(1, "Error parsing XML file"); } - if (errorString != NULL) { - errx(1, "Error parsing XML file: %s", CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8)); - } + CFReadStreamClose(stream); + + CFRelease(stream); + + free(buffer); CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0); @@ -371,10 +388,10 @@ static void SetOrGetOFVariable(char *str) CFStringRef nameRef; CFTypeRef valueRef; kern_return_t result; - + // OF variable name is first. name = str; - + // Find the equal sign for set while (*str) { if (*str == '=') { @@ -384,11 +401,11 @@ static void SetOrGetOFVariable(char *str) } str++; } - + if (set == 1) { // On sets, the OF variable's value follows the equal sign. value = str; - + result = SetOFVariable(name, value); NVRamSyncNow(name); /* Try syncing the new data to device, best effort! */ if (result != KERN_SUCCESS) { @@ -401,7 +418,7 @@ static void SetOrGetOFVariable(char *str) errx(1, "Error getting variable - '%s': %s", name, mach_error_string(result)); } - + PrintOFVariable(nameRef, valueRef, 0); CFRelease(nameRef); CFRelease(valueRef); @@ -422,10 +439,10 @@ static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef, if (*nameRef == 0) { errx(1, "Error creating CFString for key %s", name); } - + *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0); if (*valueRef == 0) return kIOReturnNotFound; - + return KERN_SUCCESS; } @@ -440,56 +457,56 @@ static kern_return_t SetOFVariable(char *name, char *value) CFTypeRef valueRef; CFTypeID typeID; kern_return_t result = KERN_SUCCESS; - + nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if (nameRef == 0) { errx(1, "Error creating CFString for key %s", name); } - + valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, nameRef, 0, 0); if (valueRef) { typeID = CFGetTypeID(valueRef); CFRelease(valueRef); - + valueRef = ConvertValueToCFTypeRef(typeID, value); if (valueRef == 0) { errx(1, "Error creating CFTypeRef for value %s", value); } result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); } else { while (1) { - // In the default case, try data, string, number, then boolean. - + // In the default case, try data, string, number, then boolean. + valueRef = ConvertValueToCFTypeRef(CFDataGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFStringGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFNumberGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFBooleanGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + break; } } - + CFRelease(nameRef); - + return result; } @@ -497,7 +514,7 @@ static kern_return_t SetOFVariable(char *name, char *value) // DeleteOFVariable(name) // // Delete the named firmware variable. -// +// // static void DeleteOFVariable(char *name) { @@ -517,11 +534,11 @@ static void NVRamSyncNow(char *name) // // Print all of the firmware variables. // -static void PrintOFVariables() +static void PrintOFVariables(void) { kern_return_t result; CFMutableDictionaryRef dict; - + result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0); if (result != KERN_SUCCESS) { errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); @@ -530,7 +547,7 @@ static void PrintOFVariables() if (gUseXML) { CFDataRef data; - data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict ); + data = CFPropertyListCreateData( kCFAllocatorDefault, dict, kCFPropertyListXMLFormat_v1_0, 0, NULL ); if (data == NULL) { errx(1, "Error converting variables to xml"); } @@ -544,7 +561,7 @@ static void PrintOFVariables() CFDictionaryApplyFunction(dict, &PrintOFVariable, 0); } - + CFRelease(dict); } @@ -565,9 +582,10 @@ static void PrintOFVariable(const void *key, const void *value, void *context) CFIndex valueLen; char *valueBuffer = 0; const char *valueString = 0; - uint32_t number, length; + uint32_t number; + long length; CFTypeID typeID; - + // Get the OF variable's name. nameLen = CFStringGetLength(key) + 1; nameBuffer = malloc(nameLen); @@ -577,10 +595,10 @@ static void PrintOFVariable(const void *key, const void *value, void *context) warnx("Unable to convert property name to C string"); nameString = ""; } - + // Get the OF variable's type. typeID = CFGetTypeID(value); - + if (typeID == CFBooleanGetTypeID()) { if (CFBooleanGetValue(value)) valueString = "true"; else valueString = "false"; @@ -622,10 +640,10 @@ static void PrintOFVariable(const void *key, const void *value, void *context) } else { valueString=""; } - + if ((nameString != 0) && (valueString != 0)) printf("%s\t%s\n", nameString, valueString); - + if (dataBuffer != 0) free(dataBuffer); if (nameBuffer != 0) free(nameBuffer); if (valueBuffer != 0) free(valueBuffer); @@ -668,7 +686,7 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) CFTypeRef valueRef = 0; long cnt, cnt2, length; unsigned long number, tmp; - + if (typeID == CFBooleanGetTypeID()) { if (!strcmp("true", value)) valueRef = kCFBooleanTrue; else if (!strcmp("false", value)) valueRef = kCFBooleanFalse; @@ -696,7 +714,7 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value, cnt2, kCFAllocatorDefault); } else return 0; - + return valueRef; } @@ -706,7 +724,7 @@ static void SetOFVariableFromFile(const void *key, const void *value, void *cont result = IORegistryEntrySetCFProperty(gOptionsRef, key, value); if ( result != KERN_SUCCESS ) { - int nameLen; + long nameLen; char *nameBuffer; char *nameString; diff --git a/passwd.tproj/file_passwd.c b/passwd.tproj/file_passwd.c index a522730..62d27f3 100644 --- a/passwd.tproj/file_passwd.c +++ b/passwd.tproj/file_passwd.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2010 Apple Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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 @@ -132,7 +132,7 @@ rewrite_file(char *path, FILE *fp, struct passwd *newpw) char *tempname = NULL; // temporary master.passwd file asprintf(&tempname, "%s.XXXXXX", path); - + fd = mkstemp(tempname); if (fd == -1) { err(EXIT_FAILURE, "%s", tempname); @@ -144,7 +144,7 @@ rewrite_file(char *path, FILE *fp, struct passwd *newpw) errno = save; err(EXIT_FAILURE, "%s", tempname); } - + while ((line = fgetln(fp, &len)) != NULL) { struct passwd *pw = parse_user(line, len); @@ -188,10 +188,10 @@ file_passwd(char *uname, char *locn) char *fname; struct passwd *pw; struct passwd newpw; - + fname = _PASSWD_FILE; if (locn != NULL) fname = locn; - + fd = open(fname, O_RDONLY | O_EXLOCK); if (fd == -1) { err(EXIT_FAILURE, "%s", fname); diff --git a/passwd.tproj/nis_passwd.c b/passwd.tproj/nis_passwd.c index 2ab2000..1525096 100644 --- a/passwd.tproj/nis_passwd.c +++ b/passwd.tproj/nis_passwd.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,10 +18,10 @@ * 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@ */ -/* +/* * Portions Copyright (c) 1998 by Apple Computer, Inc. * Portions Copyright (c) 1988 by Sun Microsystems, Inc. * Portions Copyright (c) 1988 The Regents of the University of California. @@ -90,7 +90,7 @@ static struct passwd *ypgetpwnam(char *name, char *domain); static struct passwd *interpret(struct passwd *pwent, char *line); int nis_passwd(char *uname, char *domain) -{ +{ int ans, port, ok = -1; char *master; char *ne; /* new encrypted password */ @@ -110,13 +110,13 @@ int nis_passwd(char *uname, char *domain) exit(1); } } - + if (yp_master(domain, "passwd.byname", &master) != 0) { (void)fprintf(stderr, "can't get master for passwd file\n"); exit(1); } - + port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); if (port == 0) @@ -138,16 +138,16 @@ int nis_passwd(char *uname, char *domain) (void)fprintf(stderr, "user %s not found\n", uname); exit(1); } - + uid = getuid(); if (uid != 0 && uid != pwd->pw_uid) { (void)fprintf(stderr, "you may only change your own password\n"); exit(1); } - + getpasswd(uname, 0, 5, 0, 0, pwd->pw_passwd, &ne, &oc, &nc); - + yppasswd.oldpass = oc; yppasswd.newpw.pw_name = pwd->pw_name; yppasswd.newpw.pw_passwd = ne; @@ -155,8 +155,8 @@ int nis_passwd(char *uname, char *domain) yppasswd.newpw.pw_gid = pwd->pw_gid; yppasswd.newpw.pw_gecos = pwd->pw_gecos; yppasswd.newpw.pw_dir = pwd->pw_dir; - yppasswd.newpw.pw_shell = pwd->pw_shell; - + yppasswd.newpw.pw_shell = pwd->pw_shell; + cl = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (cl == NULL) { diff --git a/passwd.tproj/od_passwd.c b/passwd.tproj/od_passwd.c index 2f113b3..02df631 100644 --- a/passwd.tproj/od_passwd.c +++ b/passwd.tproj/od_passwd.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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 @@ -70,10 +70,10 @@ show_error(CFErrorRef error) { } desc = CFErrorCopyFailureReason(error); if (desc) cfprintf(stderr, " %@", desc); - + desc = CFErrorCopyRecoverySuggestion(error); if (desc) cfprintf(stderr, " %@", desc); - + fprintf(stderr, "\n"); } } @@ -90,7 +90,7 @@ od_passwd(char* uname, char* locn, char* aname) ODRecordRef rec = NULL; CFStringRef oldpass = NULL; CFStringRef newpass = NULL; - + if (uname == NULL) return -1; @@ -147,7 +147,7 @@ od_passwd(char* uname, char* locn, char* aname) CFArrayRef values = NULL; values = ODRecordCopyValues(rec, kODAttributeTypeMetaNodeLocation, &error); location = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : location; - + printf("Changing password for %s.\n", uname); /* @@ -178,7 +178,7 @@ od_passwd(char* uname, char* locn, char* aname) printf("Password unchanged.\n"); exit(0); } - + p = getpass("Retype new password:"); if (p) { CFStringRef verify = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8); @@ -209,19 +209,19 @@ od_passwd(char* uname, char* locn, char* aname) case eDSAuthPasswordTooShort: errMsgStr = "The new password is too short."; break; - + case eDSAuthPasswordTooLong: errMsgStr = "The new password is too long."; break; - + case eDSAuthPasswordNeedsLetter: errMsgStr = "The new password must contain a letter."; break; - + case eDSAuthPasswordNeedsDigit: errMsgStr = "The new password must contain a number."; break; - + default: errMsgStr = "Sorry"; } diff --git a/passwd.tproj/pam_passwd.c b/passwd.tproj/pam_passwd.c index 10497d2..aabf2f1 100644 --- a/passwd.tproj/pam_passwd.c +++ b/passwd.tproj/pam_passwd.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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 @@ -48,7 +48,7 @@ pam_passwd(char* uname) /* Authorize. */ if (PAM_SUCCESS != (retval = pam_acct_mgmt(pamh, 0)) && PAM_NEW_AUTHTOK_REQD != retval) goto pamerr; - + printf("Changing password for %s.\n", uname); /* Change the password. */ @@ -61,8 +61,8 @@ pam_passwd(char* uname) /* Open the session. */ if (PAM_SUCCESS != (retval = pam_open_session(pamh, 0))) - goto pamerr; - + goto pamerr; + /* Close the session. */ if (PAM_SUCCESS != (retval = pam_close_session(pamh, 0))) goto pamerr; diff --git a/passwd.tproj/passwd.c b/passwd.tproj/passwd.c index 67ee59f..5d243f6 100644 --- a/passwd.tproj/passwd.c +++ b/passwd.tproj/passwd.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 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, @@ -17,7 +17,7 @@ * 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 @@ -70,7 +70,7 @@ getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha, } //strcpy(obuf, p); snprintf( obuf, sizeof(obuf), "%s", p ); - + tries = 0; nbuf[0] = '\0'; for (;;) @@ -106,12 +106,12 @@ getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha, * An insistent root may override security options. */ if ((isroot == 1) && (tries > 2)) pw_ok = 1; - + /* * A very insistent user may override security options. */ if (tries > 4) pw_ok = 1; - + if (pw_ok == 0) { if (len < minlen) @@ -125,7 +125,7 @@ getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha, //strcpy(nbuf, p); snprintf( nbuf, sizeof(nbuf), "%s", p ); - + if (!strcmp(nbuf, getpass("Retype new password:"))) break; printf("Mismatch; try again, EOF to quit.\n"); @@ -170,7 +170,7 @@ main(int argc, char *argv[]) char* auth = NULL; int infosystem, ch; int free_user = 0; - + #ifdef INFO_PAM infosystem = INFO_PAM; #else @@ -243,24 +243,24 @@ main(int argc, char *argv[]) * Verify that the login name exists. * lukeh 24 Dec 1997 */ - + /* getlogin() is the wrong thing to use here because it returns the wrong user after su */ /* sns 5 Jan 2005 */ - + struct passwd * userRec = getpwuid(getuid()); if (userRec != NULL && userRec->pw_name != NULL) { /* global static mem is volatile; must strdup */ user = strdup(userRec->pw_name); free_user = 1; } - + if (user == NULL) { fprintf(stderr, "you don't have a login name\n"); exit(1); } } - + switch (infosystem) { case INFO_FILE: @@ -282,10 +282,9 @@ main(int argc, char *argv[]) break; #endif } - + if (free_user == 1) free(user); - + exit(0); } - diff --git a/passwd.tproj/passwd.h b/passwd.tproj/passwd.h index 444b042..4e70b62 100644 --- a/passwd.tproj/passwd.h +++ b/passwd.tproj/passwd.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2011 Apple Inc. All rights reserved. + * Copyright (c) 2011-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ diff --git a/proc_uuid_policy.tproj/proc_uuid_policy.1 b/proc_uuid_policy.tproj/proc_uuid_policy.1 new file mode 100644 index 0000000..53d8a87 --- /dev/null +++ b/proc_uuid_policy.tproj/proc_uuid_policy.1 @@ -0,0 +1,54 @@ +.\" Copyright (c) 2016, Apple Inc. All rights reserved. +.\" +.Dd March 14, 2016 +.Dt PROC_UUID_POLICY 1 +.Os "Mac OS X" +.Sh NAME +.Nm proc_uuid_policy +.Nd Set UUID policy with the kernel +.Sh SYNOPSIS +.Nm +.Ar verb +.Ar policy +.Ar uuid +.Sh DESCRIPTION +.Nm +sets policy for a specific UUID or mach-o file with the kernel +.Pp +The uuid may be a uuid of the form 1A213FB4-B430-333F-AC63-891678070AFE +or a path to a valid mach-o executable. +.Nm +will extract the LC_UUID load commands from the executable. +.Pp +.Sh VERBS +The verbs are as follows: +.Bl -tag -width indent +.\" ========== +.It clear +Clear the policy for the given UUID with PROC_UUID_POLICY_OPERATION_CLEAR. +.\" ========== +.It add +Add the policy for the given UUID with PROC_UUID_POLICY_OPERATION_ADD. +.\" ========== +.It remove +Add the policy for the given UUID with PROC_UUID_POLICY_OPERATION_REMOVE. +.\" ========== +.Sh POLICIES +The policies are as follows: +.Bl -tag -width indent +.\" ========== +.It none +PROC_UUID_POLICY_FLAGS_NONE +.\" ========== +.It no_cellular +PROC_UUID_NO_CELLULAR +.\" ========== +.It necp +PROC_UUID_NO_CELLULAR +.\" ========== +.It alt-dyld +PROC_UUID_ALT_DYLD_POLICY +.\" ========== +.El +.Sh SEE ALSO +.Xr otool 1 diff --git a/proc_uuid_policy.tproj/proc_uuid_policy.c b/proc_uuid_policy.tproj/proc_uuid_policy.c new file mode 100644 index 0000000..dfa8a8c --- /dev/null +++ b/proc_uuid_policy.tproj/proc_uuid_policy.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2016 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@ + */ + +/* Header Declarations */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Constant Declarations */ +#define SUCCESS 0 +#define FAILURE -1 +#define MAX_CHUNK_SIZE 1024 * 1024 * 16 + +#ifndef PROC_UUID_ALT_DYLD_POLICY +#define PROC_UUID_ALT_DYLD_POLICY 0x00000004 +#endif + +/* UUID bucket */ +struct uuid_bucket +{ + unsigned int num_uuids; + uuid_t *binary_uuids; +}; + +/* Static Function Definitions */ +static +void +usage(); + +static +int +parse_macho_uuids( + const char *path, + struct uuid_bucket *uuid_bucket); + +static +int +parse_macho_slice( + const void *mapped, + const unsigned int offset, + const unsigned int slice_index, + struct uuid_bucket *uuid_bucket); + +/* Function Definitions */ +int +main( + int argc, + char **argv) +{ + int exit_status = EXIT_FAILURE; + const char *verb_string; + const char *policy_string; + const char *uuid_path_string; + int operation = 0; + const char *operation_string = NULL; + int policy = 0; + uuid_t uuid; + struct stat sb; + struct uuid_bucket uuid_bucket = {0, NULL}; + unsigned int i; + uuid_string_t uuid_string = ""; + + /* + * Parse the arguments. + */ + + if (argc != 4) { + + usage(); + goto BAIL; + } + + verb_string = argv[1]; + policy_string = argv[2]; + uuid_path_string = argv[3]; + + if (strcmp(verb_string, "clear") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_CLEAR; + operation_string = "Clearing"; + } else if (strcmp(verb_string, "add") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_ADD; + operation_string = "Adding"; + } else if (strcmp(verb_string, "remove") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_REMOVE; + operation_string = "Removing"; + } else { + + fprintf(stderr, "Unknown verb: %s\n", verb_string); + usage(); + goto BAIL; + } + + if (strcmp(policy_string, "none") == 0) { + + policy = PROC_UUID_POLICY_FLAGS_NONE; + } else if (strcmp(policy_string, "no_cellular") == 0) { + + policy = PROC_UUID_NO_CELLULAR; + } else if (strcmp(policy_string, "necp") == 0) { + + policy = PROC_UUID_NECP_APP_POLICY; + } else if (strcmp(policy_string, "alt-dyld") == 0) { + + policy = PROC_UUID_ALT_DYLD_POLICY; + } else { + + fprintf(stderr, "Unknown policy: %s\n", policy_string); + usage(); + goto BAIL; + } + + if (uuid_parse(uuid_path_string, uuid) == -1) { + + /* Is this a path to a macho file? */ + if (stat(uuid_path_string, &sb) == -1) { + + fprintf(stderr, "%s is not a UUID nor path: %s\n", uuid_path_string, strerror(errno)); + goto BAIL; + } else { + + /* Parse the UUID from the macho file. */ + if (parse_macho_uuids(uuid_path_string, &uuid_bucket)) { + + fprintf(stderr, "Could not parse %s for its UUID\n", uuid_path_string); + goto BAIL; + } + } + } else { + + uuid_bucket.num_uuids = 1; + uuid_bucket.binary_uuids = calloc(1, sizeof(uuid_t)); + if (uuid_bucket.binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate single UUID bucket\n"); + goto BAIL; + } + + memcpy(uuid_bucket.binary_uuids[0], uuid, sizeof(uuid_t)); + } + + for (i = 0; i < uuid_bucket.num_uuids; i++) { + + uuid_unparse(uuid_bucket.binary_uuids[i], uuid_string); + printf("%s the %s policy for %s\n", operation_string, policy_string, uuid_string); + + if (proc_uuid_policy(operation, uuid_bucket.binary_uuids[i], sizeof(uuid_t), policy) == -1) { + + fprintf(stderr, "Could not enable the UUID policy: %s\n", strerror(errno)); + goto BAIL; + } + } + + /* Set the exit status to success. */ + exit_status = EXIT_SUCCESS; + +BAIL: + + /* + * Clean up. + */ + + if (uuid_bucket.binary_uuids != NULL) { + + free(uuid_bucket.binary_uuids); + } + + return exit_status; +} + +/* Static Function Definitions */ +static +void +usage(void) +{ + fprintf(stderr, "usage: %s \n", getprogname()); + fprintf(stderr, "Verbs:\n"); + fprintf(stderr, "\tclear\tClear all policies for a given UUID\n"); + fprintf(stderr, "\tadd\tAdd a specific policy\n"); + fprintf(stderr, "\tremove\tRemove a specific policy\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Policies:\n"); + fprintf(stderr, "\tnone\t\tPROC_UUID_POLICY_FLAGS_NONE\n"); + fprintf(stderr, "\tno_cellular\tPROC_UUID_NO_CELLULAR\n"); + fprintf(stderr, "\tnecp\t\tPROC_UUID_NECP_APP_POLICY\n"); + fprintf(stderr, "\talt-dyld\tPROC_UUID_ALT_DYLD_POLICY\n"); +} + +static +int +parse_macho_uuids( + const char *path, + struct uuid_bucket *uuid_bucket) +{ + int result = FAILURE; + int fd = -1; + struct stat sb; + void *mapped = MAP_FAILED; + + struct fat_header *fat_header_pointer; + struct fat_arch *fat_arch_pointer; + bool swapped = false; + + uint32_t nfat_arch = 0; + unsigned int i; + uint32_t arch_offset; + uint32_t arch_size; + + /* Open the file and determine its size. */ + fd = open(path, O_RDONLY); + if (fd == -1) { + + fprintf(stderr, "Could not open %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + if (fstat(fd, &sb) == -1) { + + fprintf(stderr, "Could not fstat %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + /* Memory map the file. */ + mapped = mmap (0, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) { + + fprintf(stderr, "Could not memory map %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + /* + * Determine the file type. + */ + + fat_header_pointer = (struct fat_header *) mapped; + + switch (fat_header_pointer->magic) { + + case FAT_MAGIC: { + + nfat_arch = fat_header_pointer->nfat_arch; + }break; + + case FAT_CIGAM: { + + swapped = true; + nfat_arch = OSSwapInt32(fat_header_pointer->nfat_arch); + }break; + + case MH_MAGIC: + case MH_CIGAM: + case MH_MAGIC_64: + case MH_CIGAM_64: { + + uuid_bucket->num_uuids = 1; + + uuid_bucket->binary_uuids = calloc(1, sizeof(uuid_t)); + if (uuid_bucket->binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate a UUID\n"); + goto BAIL; + } + + if (parse_macho_slice(mapped, 0, 0, uuid_bucket)) { + + fprintf(stderr, "Could not parse slice\n"); + goto BAIL; + } + }break; + + default: { + + fprintf(stderr, "Unknown magic: %d\n", fat_header_pointer->magic); + goto BAIL; + } + } + + if (nfat_arch > 0) { + + uuid_bucket->num_uuids = nfat_arch; + + uuid_bucket->binary_uuids = calloc(nfat_arch, sizeof(uuid_t)); + if (uuid_bucket->binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate %d UUIDs\n", nfat_arch); + goto BAIL; + } + + for (i = 0; i < nfat_arch; i++) { + + fat_arch_pointer = (struct fat_arch *)(mapped + sizeof(struct fat_header) + (sizeof(struct fat_arch) * i)); + + if (swapped) { + + arch_offset = OSSwapInt32(fat_arch_pointer->offset); + arch_size = OSSwapInt32(fat_arch_pointer->size); + } else { + + arch_offset = fat_arch_pointer->offset; + arch_size = fat_arch_pointer->size; + } + + if (parse_macho_slice(mapped, arch_offset, i, uuid_bucket)) { + + fprintf(stderr, "Could not parse slice %d of %d\n", i, nfat_arch); + goto BAIL; + } + } + } + + /* Set the result to success. */ + result = SUCCESS; + +BAIL: + + /* + * Clean up. + */ + + if (mapped != MAP_FAILED) { + + (void) munmap(mapped, (size_t)sb.st_size); + mapped = MAP_FAILED; + } + + if (fd != -1) { + + (void) close(fd); + fd = -1; + } + + return result; +} + +static +int +parse_macho_slice( + const void *mapped, + const unsigned int offset, + const unsigned int slice_index, + struct uuid_bucket *uuid_bucket) +{ + int result = FAILURE; + + struct mach_header *mach_header_pointer; + struct mach_header_64 *mach_header_64_pointer; + struct load_command *load_command_pointer; + + bool swapped = false; + + unsigned int number_load_commands = 0; + unsigned int i; + + bool found_uuid_load_command = false; + struct uuid_command *uuid_load_command_pointer = NULL; + + mach_header_pointer = (struct mach_header *)(mapped + offset); + + switch (mach_header_pointer->magic) { + + case FAT_MAGIC: { + + fprintf(stderr, "FAT_MAGIC\n"); + goto BAIL; + }break; + + case FAT_CIGAM: { + + fprintf(stderr, "FAT_CIGAM\n"); + goto BAIL; + }break; + + case MH_MAGIC: { + + number_load_commands = mach_header_pointer->ncmds; + load_command_pointer = (struct load_command *)(void *)(mach_header_pointer + 1); + }break; + + case MH_CIGAM: { + + swapped = true; + + number_load_commands = OSSwapInt32(mach_header_pointer->ncmds); + load_command_pointer = (struct load_command *)(void *)(mach_header_pointer + 1); + }break; + + case MH_MAGIC_64: { + + mach_header_64_pointer = (struct mach_header_64 *)(mapped + offset); + number_load_commands = mach_header_64_pointer->ncmds; + + load_command_pointer = (struct load_command *)(void *)(mach_header_64_pointer + 1); + }break; + + case MH_CIGAM_64: { + + swapped = true; + + mach_header_64_pointer = (struct mach_header_64 *)(mapped + offset); + number_load_commands = OSSwapInt32(mach_header_64_pointer->ncmds); + + load_command_pointer = (struct load_command *)(void *)(mach_header_64_pointer + 1); + }break; + + default: { + + fprintf(stderr, "Unknown magic: %d\n", mach_header_pointer->magic); + goto BAIL; + } + } + + /* Walk the load commands looking for LC_UUID. */ + for (i = 0; i < number_load_commands; i++) { + + if (load_command_pointer->cmd == LC_UUID) { + + found_uuid_load_command = true; + uuid_load_command_pointer = (struct uuid_command *)load_command_pointer; + memcpy(uuid_bucket->binary_uuids[slice_index], uuid_load_command_pointer->uuid, sizeof(uuid_t)); + } + + load_command_pointer = (struct load_command *)((uintptr_t)load_command_pointer + load_command_pointer->cmdsize); + } + + if (found_uuid_load_command == false) { + + fprintf(stderr, "Could not find LC_UUID\n"); + goto BAIL; + } + + /* Set the result to success. */ + result = SUCCESS; + +BAIL: + + return result; +} diff --git a/purge.tproj/purge.c b/purge.tproj/purge.c index 8343905..38fb8f4 100644 --- a/purge.tproj/purge.c +++ b/purge.tproj/purge.c @@ -22,14 +22,15 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include #include #include +extern int vfs_purge(void); + int main(int argc, char **argv) { - int rv = syscall(SYS_vfs_purge); + int rv = vfs_purge(); if (rv) { perror("Unable to purge disk buffers"); diff --git a/pwd_mkdb.tproj/pw_scan.c b/pwd_mkdb.tproj/pw_scan.c index bb400ef..2bd8409 100644 --- a/pwd_mkdb.tproj/pw_scan.c +++ b/pwd_mkdb.tproj/pw_scan.c @@ -53,6 +53,7 @@ static const char rcsid[] = "$OpenBSD: passwd.c,v 1.42 2003/06/26 16:34:42 deraa #include #include "util.h" +#include "pw_scan.h" int pw_scan(char *bp, struct passwd *pw, int *flags) diff --git a/pwd_mkdb.tproj/pw_scan.h b/pwd_mkdb.tproj/pw_scan.h index 51c9a44..357226a 100644 --- a/pwd_mkdb.tproj/pw_scan.h +++ b/pwd_mkdb.tproj/pw_scan.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /*- diff --git a/pwd_mkdb.tproj/pwd_mkdb.c b/pwd_mkdb.tproj/pwd_mkdb.c index 075200a..7d02422 100644 --- a/pwd_mkdb.tproj/pwd_mkdb.c +++ b/pwd_mkdb.tproj/pwd_mkdb.c @@ -77,12 +77,12 @@ __unused static const char rcsid[] = "$OpenBSD: pwd_mkdb.c,v 1.36 2003/06/08 21: #define SHADOW_GROUP "wheel" HASHINFO openinfo = { - 4096, /* bsize */ - 32, /* ffactor */ - 256, /* nelem */ - 2048 * 1024, /* cachesize */ - NULL, /* hash() */ - 0 /* lorder */ + .bsize = 4096, + .ffactor = 32, + .nelem = 256, + .cachesize = 2048 * 1024, + .hash = NULL, + .lorder = 0 }; static char *pname; /* password file name */ @@ -110,7 +110,7 @@ main(int argc, char **argv) struct passwd pwd; struct group *grp; sigset_t set; - uid_t olduid; + uid_t olduid = UID_MAX; gid_t shadow; int ch, tfd, makeold, secureonly, flags, checkonly; char *username, buf[MAX(MAXPATHLEN, LINE_MAX * 2)]; @@ -150,7 +150,7 @@ main(int argc, char **argv) if (argc != 1 || (makeold && secureonly) || (username && (*username == '+' || *username == '-'))) usage(); - + if ((grp = getgrnam(SHADOW_GROUP)) == NULL) errx(1, "cannot find `%s' in the group database, aborting", SHADOW_GROUP); @@ -194,9 +194,9 @@ main(int argc, char **argv) /* Tweak openinfo values for large passwd files. */ if (st.st_size > (off_t)100*1024) - openinfo.cachesize = MIN(st.st_size * 20, (off_t)12*1024*1024); + openinfo.cachesize = (u_int)MIN(st.st_size * 20, (off_t)12*1024*1024); if (st.st_size / 128 > openinfo.nelem) - openinfo.nelem = st.st_size / 128; + openinfo.nelem = (u_int)(st.st_size / 128); /* If only updating a single record, stash the old uid */ if (username) { @@ -384,11 +384,12 @@ fmt: errno = EFTYPE; /* XXX */ return (1); } -void -cp(char *from, char *to, mode_t mode) -{ +void +cp(char *from, char *to, mode_t mode) +{ static char buf[MAXBSIZE]; - int from_fd, rcount, to_fd, wcount; + int from_fd, to_fd; + ssize_t rcount, wcount; if ((from_fd = open(from, O_RDONLY, 0)) < 0) error(from); @@ -414,8 +415,7 @@ cp(char *from, char *to, mode_t mode) } void -mv(from, to) - char *from, *to; +mv(char *from, char *to) { char buf[MAXPATHLEN * 2]; @@ -429,27 +429,23 @@ mv(from, to) } void -error(name) - char *name; +error(char *name) { - warn("%s", name); cleanup(); exit(1); } void -errorx(name) - char *name; +errorx(char *name) { - warnx("%s", name); cleanup(); exit(1); } void -cleanup() +cleanup(void) { char buf[MAXPATHLEN]; @@ -472,7 +468,6 @@ cleanup() void usage(void) { - (void)fprintf(stderr, "usage: pwd_mkdb [-c] [-p | -s] [-d basedir] [-u username] file\n"); exit(1); diff --git a/reboot.tproj/reboot.c b/reboot.tproj/reboot.c index e9aa380..da9cb6f 100644 --- a/reboot.tproj/reboot.c +++ b/reboot.tproj/reboot.c @@ -28,8 +28,10 @@ * SUCH DAMAGE. */ +#include + #ifndef lint -static const char copyright[] = +__unused static const char copyright[] = "@(#) Copyright (c) 1980, 1986, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ @@ -38,7 +40,7 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)reboot.c 8.1 (Berkeley) 6/5/93"; #endif -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/sbin/reboot/reboot.c,v 1.17 2002/10/06 16:24:36 thomas Exp $"; #endif /* not lint */ @@ -262,7 +264,7 @@ main(int argc, char *argv[]) #ifdef __APPLE__ // launchd(8) handles reboot. This call returns NULL on success. - exit(reboot2(howto) == NULL ? EXIT_SUCCESS : EXIT_FAILURE); + exit(reboot3(howto) == 0 ? EXIT_SUCCESS : EXIT_FAILURE); #else /* __APPLE__ */ reboot(howto); /* FALLTHROUGH */ @@ -276,7 +278,7 @@ restart: } void -usage() +usage(void) { #ifndef __APPLE__ (void)fprintf(stderr, "usage: %s [-dnpq] [-k kernel]\n", @@ -288,7 +290,7 @@ usage() } u_int -get_pageins() +get_pageins(void) { u_int pageins; size_t len; @@ -310,7 +312,7 @@ get_pageins() * contact kextd to lock for reboot */ int -reserve_reboot() +reserve_reboot(void) { int rval = ELAST + 1; kern_return_t macherr = KERN_FAILURE; @@ -353,7 +355,7 @@ finish: warnx("WARNING: couldn't lock kext manager for reboot: %s", mach_error_string(macherr)); rval = 0; - } + } // unless we got the lock, clean up our port if (busyStatus != 0 && myport != MACH_PORT_NULL) mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1); diff --git a/sa.tproj/main.c b/sa.tproj/main.c index 5812c96..d8263f1 100644 --- a/sa.tproj/main.c +++ b/sa.tproj/main.c @@ -303,7 +303,7 @@ main(int argc, char **argv) } static void -usage() +usage(void) { (void)fprintf(stderr, "usage: sa [-abcdDfijkKlmnqrstu] [-P file] [-U file] [-v cutoff] [file ...]\n"); diff --git a/sa.tproj/pdb.c b/sa.tproj/pdb.c index 66c99f1..928aad9 100644 --- a/sa.tproj/pdb.c +++ b/sa.tproj/pdb.c @@ -94,14 +94,14 @@ v1_to_v2(DBT *key __unused, DBT *data) /* Copy pdb_file to in-memory pacct_db. */ int -pacct_init() +pacct_init(void) { return (db_copy_in(&pacct_db, pdb_file, "process accounting", NULL, v1_to_v2)); } void -pacct_destroy() +pacct_destroy(void) { db_destroy(pacct_db, "process accounting"); } @@ -150,14 +150,14 @@ pacct_add(const struct cmdinfo *ci) /* Copy in-memory pacct_db to pdb_file. */ int -pacct_update() +pacct_update(void) { return (db_copy_out(pacct_db, pdb_file, "process accounting", NULL)); } void -pacct_print() +pacct_print(void) { BTREEINFO bti; DBT key, data, ndata; @@ -466,4 +466,4 @@ print_ci(const struct cmdinfo *cip, const struct cmdinfo *totalcip) printf(" %s\n", cip->ci_comm); } -#endif \ No newline at end of file +#endif diff --git a/sa.tproj/usrdb.c b/sa.tproj/usrdb.c index 277987a..e47220a 100644 --- a/sa.tproj/usrdb.c +++ b/sa.tproj/usrdb.c @@ -97,7 +97,7 @@ v1_to_v2(DBT *key, DBT *data) /* Copy usrdb_file to in-memory usracct_db. */ int -usracct_init() +usracct_init(void) { BTREEINFO bti; @@ -109,7 +109,7 @@ usracct_init() } void -usracct_destroy() +usracct_destroy(void) { db_destroy(usracct_db, "user accounting"); } @@ -166,7 +166,7 @@ usracct_add(const struct cmdinfo *ci) /* Copy in-memory usracct_db to usrdb_file. */ int -usracct_update() +usracct_update(void) { BTREEINFO bti; @@ -178,7 +178,7 @@ usracct_update() } void -usracct_print() +usracct_print(void) { DBT key, data; struct userinfo uistore, *ui = &uistore; diff --git a/sadc.tproj/sa1.8 b/sadc.tproj/sa1.8 deleted file mode 100644 index 9fe6d9c..0000000 --- a/sadc.tproj/sa1.8 +++ /dev/null @@ -1,85 +0,0 @@ -.\"Portions Copyright (c) 1999-2003 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 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. -.\" -.\" @(#)sa1.8 -.Dd Jul 25 2003 \" DATE -.Dt sa1 8 \" Program name and manual section number -.Os "Mac OS X" -.Sh NAME \" Section Header - required - don't modify -.Nm sa1 -.Nd Generate a system activity daily data file. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm /usr/lib/sa/sa1 -.Op Ar t n \" [t n] -.Sh DESCRIPTION \" Section Header - required - don't modify -The -.Nm sa1 -command is a shell script used to invoke the system -activity data collector, -.Nm sadc . -The binary sample data is collected at intervals -.Ar t -seconds apart, in a loop -.Ar n -times. -The binary sample data is written to the standard -daily data file, -.Ar /var/log/sa/sadd -where the -.Ar dd -represents the current day of the month. -.Pp \" Inserts a space -.Nm sa1 -is intended to be started by cron. -.Sh EXAMPLE CRON ENTRY -.Bd -literal -# Starting at 8am collect system activity records -# every 20 minutes for 12 hours -# 20 minutes = 1200 seconds -# 12 hours with 3 samples each hour = 36 loops - -0 8 * * 1-5 /usr/lib/sa/sa1 1200 36 - - -# After the 12 hour period, -# collect a system activity report - -30 20 * * 1-5 /usr/lib/sa/sa2 -A - -.Ed -.Pp -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/var/log/sa/sadd" -compact -.It Pa /var/log/sa/sadd -Default daily activity file that holds the binary sampling data. -.Ar dd -are digits that represent the day of the month. -.El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.Xr crontab 1 , -.Xr fs_usage 1 , -.Xr netstat 1 , -.Xr sar 1 , -.Xr sc_usage 1 , -.Xr top 1 , -.Xr vm_stat 1 , -.Xr crontab 5 , -.Xr iostat 8 , -.Xr sa2 8 , -.Xr sadc 8 diff --git a/sadc.tproj/sa1.sh b/sadc.tproj/sa1.sh deleted file mode 100644 index 383f943..0000000 --- a/sadc.tproj/sa1.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# /usr/lib/sa/sa1.sh -# Portions Copyright (c) 1999-2003 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 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. -# -umask 0022 -DATE=`/bin/date +%d` -ENDIR=/usr/lib/sa -DFILE=/var/log/sa/sa${DATE} -cd ${ENDIR} -if [ $# = 0 ] -then - exec ${ENDIR}/sadc 1 1 ${DFILE} -else - exec ${ENDIR}/sadc $* ${DFILE} -fi diff --git a/sadc.tproj/sa2.8 b/sadc.tproj/sa2.8 deleted file mode 100644 index fd8d32e..0000000 --- a/sadc.tproj/sa2.8 +++ /dev/null @@ -1,100 +0,0 @@ -.\"Portions Copyright (c) 1999-2003 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 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. -.\" -.\" @(#)sa2.8 -.Dd Jul 25 2003 \" DATE -.Dt sa2 8 \" Program name and manual section number -.Os "Mac OS X" -.Sh NAME \" Section Header - required - don't modify -.Nm sa2 -.Nd Generate a system activity daily report file. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm /usr/lib/sa/sa2 -.Op Fl dgpu \" [-dgpu] -.Op Fl n Ar mode \" [-n mode ] -.Op Fl e Ar time \" [-e time] -.Op Fl f Ar filename \" [-f filename] -.Op Fl i Ar seconds \" [-i seconds] -.Op Fl s Ar time \" [-s time] -.Sh DESCRIPTION \" Section Header - required - don't modify -The -.Nm sa2 -command is a shell script used to invoke the system -activity reporter -.Nm sar -for purposes of generating the standard default -daily report file. -The report file generated is, -.Ar /var/log/sa/sardd -where the -.Ar dd -represents the current day of the month. -The -.Nm sa2 -options are the same as those documented in -.Nm sar(1) . -.Pp \" Inserts a space -When -.Nm sa2 -runs, it will also remove data and report files, -found in /var/log/sa, that are more than one week old. -.Pp -The -.Nm sa2 -command is intended to be started by cron. -.Pp -.Sh EXAMPLE CRON ENTRY -.Pp -.Bd -literal -# Starting at 8am collect system activity records -# every 20 minutes for 12 hours -# 20 minutes = 1200 seconds -# 12 hours with 3 samples each hour = 36 loops - -0 8 * * 1-5 /usr/lib/sa/sa1 1200 36 - -# After the 12 hour period, -# collect a system activity report - -30 20 * * 1-5 /usr/lib/sa/sa2 -A - -.Ed -.Pp -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/var/log/sa/sardd" -compact -.It Pa /var/log/sa/sardd -Default daily report file. -.It Pa /var/log/sa/sadd -Default daily data file. -.Pp -.Ar dd -are digits that represent the day of the month. -.El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.Xr crontab 1 , -.Xr fs_usage 1 , -.Xr netstat 1 , -.Xr sar 1 , -.Xr sc_usage 1 , -.Xr top 1 , -.Xr vm_stat 1 , -.Xr crontab 5 , -.Xr iostat 8 , -.Xr sa1 8 , -.Xr sadc 8 diff --git a/sadc.tproj/sa2.sh b/sadc.tproj/sa2.sh deleted file mode 100644 index 4325349..0000000 --- a/sadc.tproj/sa2.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# /usr/lib/sa/sa2.sh -# Portions Copyright (c) 1999-2003 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 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. -# -umask 0022 -DATE=`/bin/date +%d` -RPT=/var/log/sa/sar${DATE} -ENDIR=/usr/bin -DFILE=/var/log/sa/sa${DATE} -[ -f "$DFILE" ] || exit 0 -cd ${ENDIR} -${ENDIR}/sar $* -f ${DFILE} > ${RPT} -/usr/bin/find /var/log/sa \( -name 'sar??' -o -name 'sa??' \) -mtime +7 -exec /bin/rm -f {} \; diff --git a/sadc.tproj/sadc.8 b/sadc.tproj/sadc.8 deleted file mode 100644 index ca36ea7..0000000 --- a/sadc.tproj/sadc.8 +++ /dev/null @@ -1,110 +0,0 @@ -.\"Portions Copyright (c) 1999-2003 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 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. -.\" -.\" @(#)sadc.8 -.Dd Jul 25 2003 \" DATE -.Dt sadc 8 \" Program name and manual section number -.Os "Mac OS X" -.Sh NAME \" Section Header - required - don't modify -.Nm sadc -.Nd system activity data collector -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm /usr/lib/sa/sadc -.Op Fl m Ar mode \" [-m mode] -.Op Ar t n \" [t n] -.Op Ar ofile \" [ofile] -.Sh DESCRIPTION \" Section Header - required - don't modify -The -.Nm sadc -tool is used to collect cumulative system activity data. -The sample system data is collected at intervals -.Ar t -seconds apart, in a loop -.Ar n -times. -The binary sample data is written to -.Ar ofile -if specified. -Otherwise, the binary data is written to stdout. -If the -.Ar ofile -file does not exist, it is created, otherwise it is truncated. -.Pp \" Inserts a space -.Nm sadc -is intended to be used as the engine behind the -.Nm sar(1) -command, and is not typically invoked on the command line. -Two shell scripts, -.Nm sa1 -and -.Nm sa2 , -are provided to drive the typical sampling, saving, and -reporting process. -.Pp -.Sh OPTIONS -The following options modify the way data is collected by -.Nm sadc . -.Bl -tag -width -indent \" Begins a tagged list -.It Fl m Ar mode -Modify the collection of system statistics as specified by -.Ar mode . -Currently only one mode is supported. -.Bl -tag -width -indent \" Begins a tagged list -.It PPP -By default, the collection of ppp network interface statistics -is turned off. -This is because the number of ppp connections can be very high, -causing the raw data file to grow unexpectedly large, -especially when samples are collected at short intervals. -Use the -.Ar PPP -mode to turn the collection back on. -.El -.El -.Pp -.Sh EXAMPLES -/usr/lib/sa/sadc 15 20 /tmp/sample.out -.Pp -This call collects 20 samples at 15 second intervals. -The binary data is written to the /tmp/sample.out file -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/var/log/sa/sadd" -compact -.It Pa /var/log/sa/sadd -Default daily activity file that holds the binary sampling data. -.Ar dd -are digits that represent the day of the month. -.It Pa /usr/lib/sa/sa1 -Shell script used to drive the -.Nm sar -data collection. -.It Pa /usr/lib/sa/sa2 -Shell script used to drive the -.Nm sar -data reporting. -.El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.Xr fs_usage 1 , -.Xr netstat 1 , -.Xr sar 1 , -.Xr sc_usage 1 , -.Xr top 1 , -.Xr vm_stat 1 , -.Xr iostat 8 , -.Xr sa1 8 , -.Xr sa2 8 diff --git a/sadc.tproj/sadc.c b/sadc.tproj/sadc.c deleted file mode 100644 index 70ead05..0000000 --- a/sadc.tproj/sadc.c +++ /dev/null @@ -1,909 +0,0 @@ -/* - * Portions Copyright (c) 1999-2003 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 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. -*/ - -#define IOKIT 1 /* to get io_name_t in device_types.h */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -extern int errno; - -FILE *data_fp = (FILE *)0; /* raw data output file pointer */ - - -#define REVISION_HISTORY_DATE 20030718 - -struct record_hdr restart_record = { SAR_RESTART, REVISION_HISTORY_DATE, 0, 0 }; -struct record_hdr timestamp_record = { SAR_TIMESTAMP, 1, 0, 0 }; -struct record_hdr vmstat_record = {SAR_VMSTAT, 1, 1, 0 }; -struct record_hdr cpu_record = {SAR_CPU, 1, 1, 0 }; -struct record_hdr drivestats_record = {SAR_DRIVESTATS, 1, 0, 0 }; -struct record_hdr drivepath_record = {SAR_DRIVEPATH, 1, 1, 0 }; -struct record_hdr netstats_record = {SAR_NETSTATS, 1, 0, 0}; - -/* Compile for verbose output */ - -int t_interval = 0; /* in seconds */ -int n_samples = 1; /* number of sample loops */ -char *ofile = NULL; /* output file */ -int ofd; /* output file descriptor */ -static mach_port_t myHost; -static mach_port_t masterPort; - -/* internal table of drive path mappings */ -struct drivepath *dp_table = NULL; - -/* number of entries in the dp_table */ -int dp_count = 0; - -/* internal table of network interface statistics */ -struct netstats *ns_table = NULL; -int ns_count = 0; - -static uid_t realuid; - -int network_mode = 0; - -/* Forward fuction declarations */ -static void exit_usage(); -static void open_datafile(char *); -static void write_record_hdr(struct record_hdr *); -static void write_record_data(char *, int); -static void get_all_stats(); -static void get_vmstat_sample(); -static void get_drivestat_sample(); -static int get_ndrives(); -static int record_device(io_registry_entry_t, struct drivestats *, int ndrives); -static int check_device_path (char *name, char *path, int ndrives); -static void get_netstat_sample(int pppflag); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - - char *p; - char ch; - - /* - * Stop being root ASAP. - */ - if (geteuid() != 0) - { - fprintf(stderr, "sadc: must be setuid root or root"); - exit(1); - } - - realuid = getuid(); - seteuid(realuid); - - setvbuf(stdout, (char *)NULL, _IONBF, 0); - - while ((ch=getopt(argc, argv, "m:")) != EOF) { - switch(ch) { - case 'm': - /* Only the PPP mode matters on this collector side */ - /* The reporter side deals with the DEV or EDEV modes */ - if (!strncmp(optarg, "PPP", 3)) - network_mode |= NET_PPP_MODE; - break; - default: - exit_usage(); - break; - } - } - - argc -= optind; - if (argc > 0) - { - if (isdigit(*argv[optind])) - { - /* we expect to have both an interval and a sample count */ - errno=0; - t_interval = strtol(argv[optind], &p, 0); - if (errno || (*p !='\0') || t_interval <= 0) - { - exit_usage(); - } - - optind++; - if ((argc < 2) || (!isdigit(*argv[optind]))) { - exit_usage(); - } - - errno=0; - n_samples = strtol(argv[optind], &p, 0); - if (errno || (*p != '\0') || n_samples <= 0) - { - exit_usage(); - } - - optind++; - if (argc == 3) - { - /* we have an output file */ - ofile = argv[optind]; - } - } - else - { - /* all we have is an output file */ - ofile = argv[optind]; - } - } - - - /* open the output file */ - (void)open_datafile(ofile); - - /* - * Get the Mach private port. - */ - myHost = mach_host_self(); - - /* - * Get the I/O Kit communication handle. - */ - IOMasterPort(bootstrap_port, &masterPort); - - - restart_record.rec_timestamp = time((time_t *)0); - write_record_hdr(&restart_record); - get_all_stats(); /* this is the initial stat collection */ - sleep(t_interval); - - if (n_samples > 0) - { - /* this init sample is not counted */ - timestamp_record.rec_data = time((time_t *)0); /* returns time in - * seconds */ -#if 0 - struct tm *tm; - tm = gmtime(&(timestamp_record.rec_data)); - fprintf(stderr, "timestamp=%ld\n", timestamp_record.rec_data); - fprintf(stderr, "GMTIME offset from UTC in seconds = %ld\n", tm->tm_gmtoff); - fprintf(stderr, "GMTIME secnds=%d, min=%d, hour=%d\n", tm->tm_sec, tm->tm_min, tm->tm_hour); - fprintf(stderr, "asctime = %s\n", asctime(tm)); - - tm=localtime(&(timestamp_record.rec_data)); - fprintf(stderr, "LOCTIME offset from UTC in seconds = %ld\n",tm->tm_gmtoff); - fprintf(stderr, "LOCTIME secnds=%d, min=%d, hour=%d\n", tm->tm_sec, tm->tm_min, tm->tm_hour); - fprintf(stderr, "asctime = %s\n", asctime(tm)); -#endif - - write_record_hdr(×tamp_record); - get_all_stats(); - } - - while (n_samples) - { - sleep(t_interval); - timestamp_record.rec_timestamp = time((time_t *)0); /* returns time in - * seconds */ - write_record_hdr(×tamp_record); - get_all_stats(); - n_samples--; - } - exit(EXIT_SUCCESS); -} - -static void -exit_usage() -{ - fprintf(stderr, "/usr/lib/sa/sadc [-m {PPP}] [t n] [ofile]\n"); - exit(EXIT_FAILURE); -} - -static void -open_datafile(char *path) -{ - if (path == NULL) - { - data_fp = stdout; - return; - } - else - data_fp = fopen(path, "w+"); - - if (!data_fp) - { - /* failed to open path */ - fprintf(stderr, "sadc: failed to open data file [%s]\n", path?path:"stdout"); - exit_usage(); - } -} - -static void -write_record_hdr(hdr) - struct record_hdr *hdr; -{ - errno = 0; - - if (fwrite(hdr, sizeof(struct record_hdr), 1, data_fp) != 1) - { - fprintf(stderr, "sadc: write_record_hdr failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - - fflush(data_fp); - return; -} - -static void -write_record_data(data, size) - char *data; - int size; -{ - errno = 0; - - if (fwrite(data, size, 1, data_fp) != 1) - { - fprintf(stderr, "sadc: write_record_data failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - - fflush(data_fp); - return; -} - - -static void -get_vmstat_sample() -{ - struct vm_statistics stat; - kern_return_t error; - mach_msg_type_number_t count; - - count = HOST_VM_INFO_COUNT; - error = host_statistics(myHost, HOST_VM_INFO, (host_info_t)&stat, &count); - if (error != KERN_SUCCESS) { - fprintf(stderr, "sadc: Error in vm host_statistics(): %s\n", - mach_error_string(error)); - exit(2); - } - - vmstat_record.rec_count = 1; - vmstat_record.rec_size = sizeof(vm_statistics_data_t); - write_record_hdr(&vmstat_record); - write_record_data((char *)&stat, sizeof(vm_statistics_data_t)); -} - -static void -get_cpu_sample() -{ - host_cpu_load_info_data_t cpuload; - kern_return_t error; - mach_msg_type_number_t count; - - count = HOST_CPU_LOAD_INFO_COUNT; - error = host_statistics(myHost, HOST_CPU_LOAD_INFO,(host_info_t)&cpuload, &count); - if (error != KERN_SUCCESS) { - fprintf(stderr, "sadc: Error in cpu host_statistics(): %s", - mach_error_string(error)); - exit(2); - } - - cpu_record.rec_count = 1; - cpu_record.rec_size = sizeof(host_cpu_load_info_data_t); - write_record_hdr(&cpu_record); - write_record_data((char *)&cpuload, sizeof(host_cpu_load_info_data_t)); -} - -static void -get_drivestat_sample() -{ - io_registry_entry_t drive; - io_iterator_t drivelist; - CFMutableDictionaryRef match; - int ndrives; - int i = 0; - long bufsize = 0; - char *buf; - struct drivestats *dbuf; - kern_return_t status; - int error; - - if ((ndrives = get_ndrives()) <= 0) - return; - - /* allocate space to collect stats for all the drives */ - bufsize = ndrives * sizeof(struct drivestats); - buf = (char *) malloc (bufsize); - dbuf = (struct drivestats *)buf; - if (buf) - bzero((char *)buf, bufsize); - else - return; - - /* - * Get an iterator for IOMedia objects. - */ - match = IOServiceMatching("IOMedia"); - - /* Get whole disk info */ - CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); - - status = IOServiceGetMatchingServices(masterPort, match, &drivelist); - if (status != KERN_SUCCESS) - goto RETURN; - - /* - * Scan all of the IOMedia objects, and for each - * object that has a parent IOBlockStorageDriver, - * record the statistics - * - * XXX What about RAID devices? - */ - error = 1; - i = 0; - while ((drive = IOIteratorNext(drivelist))) - { - if (i < ndrives) - { - if (record_device(drive, &dbuf[i], ndrives)) - { - error = 0; - i++; - } - } - else - { - IOObjectRelease(drive); - break; - } - IOObjectRelease(drive); - } - IOObjectRelease(drivelist); - - if (! error) - { - drivestats_record.rec_count = i; - drivestats_record.rec_size = sizeof (struct drivestats); - write_record_hdr(&drivestats_record); - write_record_data((char *)buf, (i * sizeof(struct drivestats))); - } - - RETURN: - if (buf) - free(buf); - return; -} - -/* - * Determine whether an IORegistryEntry refers to a valid - * I/O device, and if so, record it. - * Return zero: no device recorded - * Return non-zero: device stats recorded - */ -static int -record_device(io_registry_entry_t drive, struct drivestats* drivestat, int ndrives) -{ - io_registry_entry_t parent; - CFDictionaryRef properties, statistics; - CFStringRef name; - CFNumberRef number; - UInt64 value; - kern_return_t status; - int retval = 0; - int drive_id; - io_string_t path; - char BSDName[MAXDRIVENAME + 1]; - - status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &parent); - if (status != KERN_SUCCESS) - { - /* device has no parent */ - return(retval); - } - - if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) - { - /* - * Get a unique device path identifier. - * Devices available at boot have an Open Firmware Device Tree path. - * The OF path is short and concise and should be first choice. - * Devices that show up after boot, are guaranteed to have - * a Service Plane, hardware unique path. - */ - - bzero(path, sizeof(io_string_t)); - if (IORegistryEntryGetPath(drive, kIODeviceTreePlane, path) != KERN_SUCCESS) - { - if(IORegistryEntryGetPath(drive, kIOServicePlane, path) != KERN_SUCCESS) - /* device has no unique path identifier */ - goto RETURN; - } - retval++; - - /* get drive properties */ - status = IORegistryEntryCreateCFProperties(drive, - (CFMutableDictionaryRef *)&properties, - kCFAllocatorDefault, - kNilOptions); - if (status != KERN_SUCCESS) - { - /* device has no properties */ - goto RETURN; - } - - bzero(BSDName, MAXDRIVENAME+1); - /* get name from properties */ - name = (CFStringRef)CFDictionaryGetValue(properties, - CFSTR(kIOBSDNameKey)); - if (name) { - CFStringGetCString(name, BSDName, - MAXDRIVENAME, kCFStringEncodingUTF8); - retval++; - } - - /* get blocksize from properties */ - number = (CFNumberRef)CFDictionaryGetValue(properties, - CFSTR(kIOMediaPreferredBlockSizeKey)); - if (number != 0) { - CFNumberGetValue(number, - kCFNumberSInt64Type, &value); - drivestat->blocksize = value; - retval++; - } - CFRelease(properties); - } - else - goto RETURN; - - /* we should have a name and blocksize at a minimum */ - if (retval != 3) - { - retval = FALSE; - goto RETURN; - } - - drive_id = check_device_path (BSDName, path, ndrives); - if (drive_id == -1) - { - retval = FALSE; - goto RETURN; - } - else - drivestat->drivepath_id = drive_id; - - - /* get parent drive properties */ - status = IORegistryEntryCreateCFProperties(parent, - (CFMutableDictionaryRef *)&properties, - kCFAllocatorDefault, - kNilOptions); - if (status != KERN_SUCCESS) - { - /* device has no properties */ - goto RETURN; - } - - /* Obtain the statistics from the parent drive properties. */ - - statistics - = (CFDictionaryRef)CFDictionaryGetValue(properties, - CFSTR(kIOBlockStorageDriverStatisticsKey)); - - if (statistics != 0) - { - /* Get number of reads. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsReadsKey)); - if (number != 0) { - CFNumberGetValue(number, - kCFNumberSInt64Type, &value); - drivestat->Reads = value; - } - - /* Get bytes read. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->BytesRead = value; - } - - /* Get number of writes. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsWritesKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->Writes = value; - } - - /* Get bytes written. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->BytesWritten = value; - } - - /* Get LatentReadTime. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->LatentReadTime = value; - } - - /* Get LatentWriteTime. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->LatentWriteTime = value; - } - - /* Get ReadErrors. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsReadErrorsKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->ReadErrors = value; - } - - /* Get WriteErrors. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsWriteErrorsKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->WriteErrors = value; - } - - /* Get ReadRetries. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsReadRetriesKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->ReadRetries = value; - } - - /* Get WriteRetries. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsWriteRetriesKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->WriteRetries = value; - } - - /* Get TotalReadTime. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->TotalReadTime = value; - } - - /* Get WriteRetries. */ - number = - (CFNumberRef)CFDictionaryGetValue(statistics, - CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)); - if (number != 0) { - CFNumberGetValue(number, kCFNumberSInt64Type, &value); - drivestat->TotalWriteTime = value; - } - - CFRelease(properties); - } /* end if statistics != 0 */ - - RETURN: - IOObjectRelease(parent); - return(retval); -} - - -/* - * find IOMedia objects - * This routine always gives me a lower count on the number - * of disks. I don't know which one to use. - */ -static int -get_ndrives(void) -{ - io_iterator_t drivelist; - io_registry_entry_t drive; - io_registry_entry_t parent; - CFMutableDictionaryRef match; - int error, ndrives; - kern_return_t status; - - /* - * Get an iterator for IOMedia objects. - */ - match = IOServiceMatching("IOMedia"); - CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); - status = IOServiceGetMatchingServices(masterPort, match, &drivelist); - if (status != KERN_SUCCESS) - return(0); - - /* - * Scan all of the IOMedia objects, and count each - * object that has a parent IOBlockStorageDriver - * - * XXX What about RAID devices? - */ - error = 1; - ndrives = 0; - while ((drive = IOIteratorNext(drivelist))) - { - /* get drive's parent */ - status = IORegistryEntryGetParentEntry(drive, - kIOServicePlane, &parent); - if (status != KERN_SUCCESS) - { - IOObjectRelease(drive); - continue; - } - - if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) - { - error = 0; - ndrives++; - } - IOObjectRelease(parent); - IOObjectRelease(drive); - } - - IOObjectRelease(drivelist); - - return(ndrives); -} - - -/* - * When getting the stats, do it in the order - * of their type. The types that have the most - * data come first in the list if possible. - * This makes the sar reporter tool more efficient, - * because in some cases, it will allocate a buffer - * and keep reusing it as long as the sample data fits. - * When a sample data doesn't fit, it reallocates the buffer - * to a bigger size etc. - */ -void -get_all_stats() -{ - - get_drivestat_sample(); - get_netstat_sample(network_mode); - get_vmstat_sample(); - get_cpu_sample(); -} - - -/* - * An internal table maps the BSDName to a unique ioregistry path. - * The table's index is then used as a unique compressed path, and - * helps track disks that come and go during the sampling intervals. - * This routine finds an entry that maps both the BSDName and the - * IOKit registry path. If no mapping is discovered, a new entry - * is created. An entry is never removed, this maintaining the - * unique index throughout the data collection. - * Success returns the map index. Failure returns -1. - */ -static int -check_device_path (char *name, char *path, int ndrives) -{ - int i; - int index; - int n; - - if (dp_table == NULL) - { - /* First setup of internal drivepath table */ - dp_table = (struct drivepath *)malloc (ndrives * sizeof(struct drivepath)); - if (dp_table == NULL) - return(-1); - else - { - bzero(dp_table, (ndrives * sizeof(struct drivepath))); - dp_count = ndrives; - drivepath_record.rec_size = sizeof(struct drivepath); - } - } - - for (i=0; i < dp_count; i++) - { - if (dp_table[i].state == DPSTATE_UNINITIALIZED) - { - /* This is a new drive entry that should be recorded */ - index = i; - goto NEW_ENTRY; - } - else if (!strcmp (dp_table[i].ioreg_path, path)) - { - /* Found a matching hardware path */ - if (!strcmp(dp_table[i].BSDName, name)) - { - /* The BSDName matches the entry in the table - * so there is no need to record this data. - */ - return(i); - } - else - { - /* The BSDName is different ... implies a change, - * like the drive was removed and now is back - */ - bzero((char *)dp_table[i].BSDName, MAXDRIVENAME+1); - dp_table[i].drivepath_id = i; - dp_table[i].state = DPSTATE_CHANGED; - strcpy(dp_table[i].BSDName, name); - write_record_hdr(&drivepath_record); - write_record_data((char *)&dp_table[i], sizeof(struct drivepath)); - return(i); - } - } - } /* end for loop */ - - /* - * If we reach this point, then we've run out of - * table entries. Double the size of the table. - */ - n = dp_count * 2; - dp_table = (struct drivepath *)realloc(dp_table, n * sizeof(struct drivepath)); - bzero(&dp_table[dp_count], dp_count * sizeof(struct drivepath)); - index = dp_count; - dp_count = n; - - /* This is a new drive entry that should be recorded */ - NEW_ENTRY: - dp_table[index].drivepath_id = index; - dp_table[index].state = DPSTATE_NEW; - strcpy(dp_table[index].BSDName, name); - strcpy(dp_table[index].ioreg_path, path); - write_record_hdr(&drivepath_record); - write_record_data((char *)&dp_table[index], sizeof(struct drivepath)); - return(index); -} - - - -/* - * Thus far, only the networking stats take an optional flag - * to modify the collection of data. The number of ppp - * interfaces can be very high, causing the raw data file to - * grow very large. We want this option to include ppp - * statistics to be off by default. When we see the -m PPP - * mode passed in, ppp collection will be turned on. - */ -static void -get_netstat_sample(int mode) -{ - - int n; - int ns_index = 0; - char tname[MAX_TNAME_SIZE + 1]; - char name[MAX_TNAME_UNIT_SIZE + 1]; - struct ifaddrs *ifa_list, *ifa; - - - /* - * Set the starting table size to 100 entries - * That should be big enough for most cases, - * even with a lot of ppp connections. - */ - ns_count = 100; - ns_table = (struct netstats *) malloc(ns_count * sizeof (struct netstats)); - if (ns_table == NULL) - { - fprintf(stderr, "sadc: malloc netstat table failed\n"); - return; - } - - bzero(ns_table, ns_count * sizeof(struct netstats)); - if (getifaddrs(&ifa_list) == -1) - return; - - for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) - { - struct if_data *if_data = (struct if_data *)ifa->ifa_data; - - if (AF_LINK != ifa->ifa_addr->sa_family) - continue; - if (ifa->ifa_data == 0) - continue; - tname[MAX_TNAME_SIZE] = '\0'; - if (!(network_mode & NET_PPP_MODE)) - { - /* - * If the flag is set, include PPP connections. - * By default this collection is turned off - */ - if(!strncmp(ifa->ifa_name, "ppp", 3)) - continue; - } - snprintf(name, MAX_TNAME_UNIT_SIZE, "%s", ifa->ifa_name); - name[MAX_TNAME_UNIT_SIZE] = '\0'; - - if (ns_index == ns_count) - { - /* the stat table needs to grow */ - n = ns_count * 2; - ns_table = (struct netstats *)realloc(ns_table, n * sizeof(struct netstats)); - bzero(&ns_table[ns_count], ns_count * sizeof(struct netstats)); - ns_count = n; - } - - /* - * As a means of helping to identify when interface unit numbers - * are reused, a generation counter may eventually be implemented. - * This will be especially helpful with ppp-x connections. - * In anticipation, we will reserve a space for it, but always - * set it to zero for now. - */ - ns_table[ns_index].gen_counter = 0; - - strncpy(ns_table[ns_index].tname_unit, name, MAX_TNAME_UNIT_SIZE); - ns_table[ns_index].tname_unit[MAX_TNAME_UNIT_SIZE] = '\0'; - ns_table[ns_index].net_ipackets = if_data->ifi_ipackets; - ns_table[ns_index].net_ierrors = if_data->ifi_ierrors; - ns_table[ns_index].net_opackets = if_data->ifi_opackets; - ns_table[ns_index].net_oerrors = if_data->ifi_oerrors; - ns_table[ns_index].net_collisions = if_data->ifi_collisions; - ns_table[ns_index].net_ibytes = if_data->ifi_ibytes; - ns_table[ns_index].net_obytes = if_data->ifi_obytes; - ns_table[ns_index].net_imcasts = if_data->ifi_imcasts; - ns_table[ns_index].net_omcasts = if_data->ifi_omcasts; - ns_table[ns_index].net_drops = if_data->ifi_iqdrops; - ns_index++; - } /* end for */ - - netstats_record.rec_count = ns_index; - netstats_record.rec_size = sizeof(struct netstats); - write_record_hdr(&netstats_record); - write_record_data((char *)ns_table, (ns_index * sizeof(struct netstats))); - return; -} diff --git a/sadc.tproj/sadc.h b/sadc.tproj/sadc.h deleted file mode 100644 index d37ae0d..0000000 --- a/sadc.tproj/sadc.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Portions Copyright (c) 1999-2003 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 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. -*/ - -#include -#include -#include -#include -#include - -/* record types in sadc raw data output */ - -#define SAR_NOTSET 0 -#define SAR_RESTART 1 -#define SAR_TIMESTAMP 2 -#define SAR_NETSTATS 3 -#define SAR_DRIVEPATH 4 -#define SAR_DRIVESTATS 5 -#define SAR_VMSTAT 6 -#define SAR_CPU 7 - -struct record_hdr -{ - int32_t rec_type; - int32_t rec_version; - int32_t rec_count; - int32_t rec_size; -}; - -#define rec_data rec_size -#define rec_timestamp rec_size - -#define MAXDRIVENAME 31 /* largest drive name we allow */ - -#define DPSTATE_UNINITIALIZED 0 -#define DPSTATE_NEW 1 -#define DPSTATE_CHANGED 2 -#define DPSTATE_ACTIVE 3 - -struct drivepath -{ - int32_t drivepath_id; /* compressed table id */ - int32_t state; - char BSDName[MAXDRIVENAME + 1]; - io_string_t ioreg_path; /* unique id, hardware path */ -}; - - -struct drivestats -{ - io_registry_entry_t driver; - - int32_t drivepath_id; - uint64_t blocksize; - - uint64_t Reads; - uint64_t BytesRead; - - uint64_t Writes; - uint64_t BytesWritten; - - uint64_t LatentReadTime; - uint64_t LatentWriteTime; - - uint64_t ReadErrors; - uint64_t WriteErrors; - - uint64_t ReadRetries; - uint64_t WriteRetries; - - uint64_t TotalReadTime; - uint64_t TotalWriteTime; -}; - - -/* - * netstat mode drives the - * collection of ppp interface data - */ - -#define NET_DEV_MODE 0x1 /* Turn on network interface counters */ -#define NET_EDEV_MODE 0x2 /* Turn on network interface error counters */ -#define NET_PPP_MODE 0x4 /* Include ppp interface counters - further - * modifies NET_DEV_MODE and NET_EDEV_MODE */ - -#define MAX_TNAME_SIZE 15 -#define MAX_TNAME_UNIT_SIZE 23 - -struct netstats -{ - char tname_unit[MAX_TNAME_UNIT_SIZE + 1]; - uint32_t gen_counter; /* unit generation counter */ - - uint64_t net_ipackets; - uint64_t net_ierrors; - uint64_t net_opackets; - uint64_t net_oerrors; - uint64_t net_collisions; - uint64_t net_ibytes; - uint64_t net_obytes; - uint64_t net_imcasts; - uint64_t net_omcasts; - uint64_t net_drops; -}; diff --git a/sar.tproj/sar.1 b/sar.tproj/sar.1 deleted file mode 100644 index 02e5f33..0000000 --- a/sar.tproj/sar.1 +++ /dev/null @@ -1,223 +0,0 @@ -.\"Portions Copyright (c) 1999-2003 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 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. -.\" -.\" @(#)sadc.8 - -.Dd Jul 25, 2003 \" DATE -.Dt sar 1 \" Program name and manual section number -.Os "Mac OS X" -.Sh NAME \" Section Header - required - don't modify -.Nm sar -.Nd system activity reporter -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm sar -.Op Fl dgpu \" [-dgpu] -.Op Fl n Ar mode \" [-n mode] -.Op Fl o Ar filename \" [-o filename] -t \" t -.Op Ar n \" [ n ] -.Nm sar -.Op Fl dgpu \" [-dgpu] -.Op Fl n Ar mode \" [-n mode] -.Op Fl e Ar time \" [-e time] -.Op Fl f Ar filename \" [-f filename] -.Op Fl i Ar seconds \" [-i seconds] -.Op Fl s Ar time \" [-s time] -.Sh DESCRIPTION \" Section Header - required - don't modify -The -.Nm sar -command is used to sample and report various cumulative statistic counters -maintained by the operating system. -It can be invoked in two different ways. -.Pp -In the first usage instance, -.Ar n -samples are reported at -.Ar t -second intervals. -If -.Ar n -is not specified, only one sample will be captured. -When the -o option is specified, -.Nm sar -will write the binary sampling data to the output file specified by -.Ar filename . -.Pp -In the second usage instance, -there is no on-going sample interval to specify. -This is because the sampling input comes -from a previously recorded, binary activity file. -The binary activity file can be specified using the -.Fl f Ar filename -option. -When the -.Fl f -option isn't used, -.Nm sar -attempts to open a default binary activity file, -/var/log/sa/sadd, where -.Ar dd -represents the current day of the month. -.Pp -The starting and ending time of the report can be restricted using the -.Fl e -and -.Fl s -options. Here, the -.Ar time -field is specified in the form hh[:mm[:ss]]. -.Pp -Finally, the -.Fl i -option can be used to select the sampling interval. -Only records at least -.Ar seconds -apart will be reported. -When the -.Fl i -option is not used, -all of the previously recorded interval samples are reported. -.Pp -Due to the nature of on-going sample collection, -the data is reported in a verbose mode -when more than one sampling option is specified. -Column headers are printed at the beginning of the report; -averages are printed when the -.Nm sar -command terminates. -.Sh OPTIONS -The following options restrict the sample set that -.Nm sar -reports. -.Pp \" Inserts a space -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl d -Report disk activity. -.Pp -.Bl -tag -width -indent \" Begins a tagged list -.It device -The BSD name of the device. -.It r+w/s -The number of reads and writes per second. -.It blks/s -Number of blocks (in device's default blocksize) transferred to a device per second. -.El -.It Fl g -Report page-out activity. -.Pp -.Bl -tag -width -indent \" Begins a tagged list -.It pgout/s -The number of pages paged out per second. -.El -.It Fl p -Report page-in and page fault activity -.Pp -.Bl -tag -width -indent \" Begins a tagged list -.It pgin/s -The number of pages paged in per second. -.It pflts/s -The number of faults that caused a page to be copied in per second. -.It vflts/s -The number of times vm_fault routine has been called. -.El -.It Fl n Ar mode -Report network activity with modes -.Ar DEV , -.Ar EDEV , -or -.Ar PPP . -Multiple network modes can be specified. -.Pp -.Bl -tag -width -indent \" Begins a tagged list -.It DEV -The -.Ar DEV -mode reports network device statistics. The following -information is displayed for each interface. -.Pp -.Bl -tag -width "Obytes/s" \" Begins a tagged list -.It IFACE -The network interface name. -.It Ipkts/s -The number of packets received per second. -.It Ibytes/s -The number of bytes received per second. -.It Opkts/s -The number of packets sent per second. -.It Obytes/s -The number of bytes sent per second. -.El -.It EDEV -The -.Ar EDEV -mode reports network device error statistics. The -following information is displayed for each interface. -.Pp -.Bl -tag -width "Drops/s" \" Begins a tagged list -.It IFACE -The interface name. -.It Ierrs/s -The input errors per second. -.It Oerrs/s -The output errors per second. -.It Coll/s -The collisions that occurred per second. -.It Drops/s -The number of dropped packets per second. -.El -.It PPP -The -.Ar PPP -mode must be specified in order to display ppp connections -in the network statistics. This will also turn on the PPP modify -mode in -.Ar sadc -(8) when sampling data is not being read from a file. -By default, both the collection and reporting of ppp -statistics is turned off. See -.Ar sadc -(8). -.El -.Pp -.It Fl u -Report CPU activity (default) -.Pp -%usr, %sys, and %idle -.Pp -These report the percentage of time running in user mode, -system mode and idle. -.El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/var/log/sa/sadd" -compact -.It Pa /var/log/sa/sadd -Default daily activity file that holds the binary sampling data. -.Ar dd -are digits that represent the day of the month. -.El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.Xr fs_usage 1 , -.Xr netstat 1 , -.Xr sc_usage 1 , -.Xr top 1 , -.Xr vm_stat 1 , -.Xr iostat 8 , -.Xr sa1 8 , -.Xr sa2 8 , -.Xr sadc 8 -.\" .Sh BUGS \" Document known, unremedied bugs diff --git a/sar.tproj/sar.c b/sar.tproj/sar.c deleted file mode 100644 index 678914c..0000000 --- a/sar.tproj/sar.c +++ /dev/null @@ -1,2340 +0,0 @@ -/* - * Portions Copyright (c) 1999-2003 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 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. -*/ - -/* - cc -Wall -I. -I ../sadc.tproj -O -o sar sar.c -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -#define IFNET_32_BIT_COUNTERS 1 - -/* Options used only for launching sadc */ -int t_interval = 5; /* in seconds */ -char * t_intervalp = "5"; -int n_samples = 1; /* number of sample loops */ -char * n_samplesp = "1"; - -/* Used only for storing the binary output after launching sadc */ -char *outfile = NULL; /* output file */ -int ofd = 0; /* output file descriptor */ - -/* - * When launching sadc, this file descriptor reads sadc's stdout - * via pipe. - * When not launching sadc, this file descriptor will be either - * the input file passed in with the -f flag - * or the standard input file /var/log/sa/saXX - */ -int ifd = 0; /* input file descriptor */ -char *infile = NULL; /* input file */ - - - -/* Used when we have to luanch sadc */ -pid_t pid; -int fd[2]; /* read from fd[0], write to fd[1] */ - -char *optionstring1 = "Adgn:puo:"; -char *optionstring1_usage = "/usr/bin/sar [-Adgpu] [-n { DEV | EDEV | PPP } ] [-o filename] t [n]"; -char *optionstring2 = "Adgn:pue:f:i:s:"; -char *optionstring2_usage = "/usr/bin/sar [-Adgpu] [-n { DEV | EDEV | PPP }] [-e time] [-f filename] [-i sec] [-s time]"; - - -/* option flags */ -int aflag = 0; -int Aflag = 0; -int bflag = 0; -int cflag = 0; -int dflag = 0; /* drive statistics */ -int gflag = 0; /* page-out activity */ -int kflag = 0; -int mflag = 0; - -int nflag = 0; /* network statistics */ -int network_mode = 0; -char *sadc_mflagp = "-m"; -char *sadc_ppp_modep = "PPP"; - -int pflag = 0; /* page-in activity */ -int qflag = 0; -int rflag = 0; -int uflag = 0; /* cpu utilization - this is the only default */ -int vflag = 0; -int wflag = 0; -int yflag = 0; -int set_default_flag = 1; -int flag_count = 0; - -/* - * To get the current time of day in seconds - * based on a 24 hour clock, pass in the time_t from time() - * the remainder is the current time in seconds -*/ -#define HOURS_PER_DAY 24 -#define MINS_PER_HOUR 60 -#define SECS_PER_MIN 60 -#define SECS_PER_DAY (SECS_PER_MIN * MINS_PER_HOUR * HOURS_PER_DAY) - -/* end time delimiter -- converted from hh:mm:ss to seconds */ -time_t end_time = 0; - -int iflag = 0; -int iseconds = 0; /* interval seconds, default = 0 implies all samples are - * printed */ - -/* start time delimiter -- converted from hh:mm:ss to seconds */ -time_t start_time = 0; - -int oflag = 0; -int fflag = 0; - -/* stat records average and previous */ -struct vm_statistics prev_vmstat, avg_vmstat, cur_vmstat; -host_cpu_load_info_data_t prev_cpuload, avg_cpuload, cur_cpuload; -struct drivestats_report *dr_head = NULL; - -/* internal table of drive path mappings */ -struct drivepath *dp_table = NULL; -int dp_count = 0; - -/* internal table of network interface statistics */ -struct netstats_report *nr_table = NULL; -int nr_count; -struct netstats *netstat_readbuf = NULL; -size_t netstat_readbuf_size = 0; - -int avg_counter = 0; -int avg_interval = 0; - -extern int errno; - -/* Forward function declarations */ -static void exit_usage(); -static void open_output_file(char *path); -static void open_input_file(char *path); -static void read_record_hdr(struct record_hdr *hdr, int writeflag); -static void read_record_data(char *buf, size_t size, int writeflag); -static void write_record_hdr(struct record_hdr *hdr); -static void write_record_data(char *buf, size_t size); -static time_t convert_hms(char *string); -static char *get_hms_string(time_t, char *); -static int find_restart_header(struct record_hdr *); -static void print_all_column_headings (time_t timestamp); -static void print_column_heading (int type, char *timebufptr, int mode); -static void read_sample_set(int, time_t, struct record_hdr *); -static void do_main_workloop(); -static int bypass_sample_set(struct record_hdr *, time_t); -static void skip_data(int); -static int get_cpu_sample(int flag, struct record_hdr *hdr); -static void print_cpu_sample(char *timebufptr); -static int get_vmstat_sample(int flag, struct record_hdr *hdr); -static void print_vmstat_sample(char *timebufptr); - -static int get_drivestats_sample(int flag, struct record_hdr *hdr); -static void init_drivestats(struct drivestats_report *dr); -static void print_drivestats_sample(char *timebufptr); -static int get_drivepath_sample(int flag, struct record_hdr *hdr); - -static void set_cur_netstats(struct netstats_report *nr, struct netstats *ns); -static void init_prev_netstats(struct netstats_report *nr); -static int get_netstats_sample(int flag, struct record_hdr *hdr); -static void print_netstats_sample(char *timebufptr); - -static void exit_average(); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - - char ch; - - time_t curr_time; /* current time in seconds */ - char timebuf[26]; - char filenamebuf[20]; - char *optstring = NULL; - int optstringval; - int i; - - /* - * Detirmine which option string to use - */ - - optreset=0; - optstringval=0; - - while((ch=getopt(argc, argv, "aAbcdgkmn:pqruvwyo:e:f:i:s:")) != EOF) { - switch(ch) { - case 'o': - if (optstringval == 2) - exit_usage(); - optstring=optionstring1; - optstringval=1; - break; - case 'e': - case 'f': - case 'i': - case 's': - if (optstringval == 1) - exit_usage(); - optstring=optionstring2; - optstringval=2; - break; - default: - /* ignore for now */ - break; - } - } - - if (!optstring) - { - /* still trying to determine which option string to use */ - if (argc - optind > 0) - { - optstring=optionstring1; /* we should have a t_second value */ - optstringval=1; - } - else - { - optstring=optionstring2; - optstringval=2; - } - } - - optreset = optind = 1; - while ((ch=getopt(argc, argv, optstring)) != EOF) { - switch (ch) { - case 'a': - aflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'A': - Aflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'b': - bflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'c': - cflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'd': - dflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'g': - gflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'k': - kflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'm': - mflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'n': - nflag= 1; - if (!strncmp(optarg, "PPP", 3)) - network_mode |= NET_PPP_MODE; - else if (!strncmp(optarg, "DEV", 3)) - network_mode |= NET_DEV_MODE; - else if (!strncmp(optarg, "EDEV", 4)) - network_mode |= NET_EDEV_MODE; - else - exit_usage(); - set_default_flag = 0; - flag_count++; - break; - case 'p': - pflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'q': - qflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'r': - rflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'u': - uflag= 1; - set_default_flag = 0; - flag_count++; - break; - case 'v': - vflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'w': - wflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'y': - yflag = 1; - set_default_flag = 0; - flag_count++; - break; - case 'o': - /* open the output file */ - oflag = 1; - outfile=optarg; - (void)open_output_file(outfile); - break; - case 'e': /* eflag */ - end_time = convert_hms(optarg); - break; - case 'f': - fflag = 1; - infile=optarg; - break; - case 'i': - iflag = 1; - iseconds=atoi(optarg); - break; - case 's': - start_time = convert_hms(optarg); - break; - default: - exit_usage(); - break; - } - } - - /* setup default uflag option */ - if (Aflag) - { - dflag = gflag = pflag = uflag = 1; - if (!nflag) - { - /* - * Add network stats to the load - * but avoid PPP data by default. - */ - nflag = 1; - network_mode = NET_DEV_MODE | NET_EDEV_MODE;; - } - flag_count = 2; /* triggers column headings */ - } - else if (set_default_flag) - { - uflag=1; - flag_count++; - } - - if (nflag) - { - if (network_mode & NET_PPP_MODE) - { - if (!(network_mode & NET_DEV_MODE) && - !(network_mode & NET_EDEV_MODE)) - { - /* set defaults */ - network_mode |= NET_DEV_MODE; - network_mode |= NET_EDEV_MODE; - flag_count++; - } - } - } - - argc -= optind; - argv += optind; - - /* set up signal handlers */ - signal(SIGINT, exit_average); - signal(SIGQUIT, exit_average); - signal(SIGHUP, exit_average); - signal(SIGTERM, exit_average); - - if (optstringval == 1) - { - /* expecting a time interval */ - - char *p; - - if (argc >= 1) - { - errno = 0; - t_interval = strtol(argv[0], &p, 0); - t_intervalp = argv[0]; - if (errno || (*p != '\0') || t_interval <= 0 ) - exit_usage(); - if (argc >= 2) - { - errno=0; - n_samples = strtol(argv[1], &p, 0); - n_samplesp = argv[1]; - if (errno || (*p != '\0') || n_samples <= 0) - exit_usage(); - } - } - } - - /* where does the input come from */ - if (fflag) - { - (void)open_input_file(infile); - } - else if (optstringval == 2) - { - /* - * Create a filename of the form /var/log/sa/sadd - * where "dd" is the date of the month - */ - curr_time = time((time_t *)0); /* returns time in seconds */ - - /* - timebuf will be a 26-character string of the form: - Thu Nov 24 18:22:48 1986\n\0 - */ - - ctime_r(&curr_time, timebuf); - strncpy(filenamebuf, "/var/log/sa/sa", 14); - strncpy(&filenamebuf[14], &timebuf[8], 2); - if (filenamebuf[14] == ' ') - filenamebuf[14] = '0'; - filenamebuf[16]='\0'; - infile = filenamebuf; - (void)open_input_file(infile); - } - else if (optstringval == 1) - { - /* launch sadc */ - if (pipe(fd) == -1) - { - fprintf(stderr, "sar: pipe(2) failed, errno = (%d)\n",errno); - exit(1); - } - - if ((pid=fork()) == 0) - { -#if 0 - int efd; -#endif - int fdlimit = getdtablesize(); - - /* This is the child */ - /* Close all file descriptors except the one we need */ - - for (i=0; i < fdlimit; i++) { - if ((i != fd[0]) && (i != fd[1])) - (void)close(i); - } -#if 0 - efd = open("/tmp/errlog", O_CREAT|O_APPEND|O_RDWR, 0666); - if (dup2(efd,2) == -1) { - exit(1); - } -#endif - /* Dup the two file descriptors to stdin and stdout */ - if (dup2(fd[0],0) == -1) { - exit(1); - } - if (dup2(fd[1],1) == -1) { - exit(1); - } - /* Exec the child process */ - if (network_mode & NET_PPP_MODE) - execl("/usr/lib/sa/sadc", "sadc", sadc_mflagp, sadc_ppp_modep, t_intervalp, n_samplesp, NULL); - else - execl("/usr/lib/sa/sadc", "sadc", t_intervalp, n_samplesp, NULL); - - perror("execlp sadc"); - exit(2); /* This call of exit(2) should never be reached... */ - } - else - { /* This is the parent */ - if (pid == -1) { - fprintf(stderr, "sar: fork(2) failed, errno = (%d)\n",errno); - exit(1); - } - close (fd[1]); /* parent does not write to the pipe */ - ifd = fd[0]; /* parent will read from the pipe */ - } - } - else - { - /* we're confused about source of input data - bail out */ - fprintf(stderr, "sar: no input file recognized\n"); - exit_usage(); - } - - /* start reading input data and format the output */ - (void)do_main_workloop(); - (void)exit_average(); - exit(0); -} - -static void -exit_usage() -{ - fprintf(stderr, "\n%s\n\n", optionstring1_usage); - fprintf(stderr, "%s\n", optionstring2_usage); - exit(EXIT_FAILURE); -} - -static void -open_output_file(char *path) -{ - if ((ofd = open(path, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY, 0664)) == -1 ) - { - /* failed to open path */ - fprintf(stderr, "sar: failed to open output file [%s]\n", path); - exit_usage(); - } -} - - -static void -open_input_file(char *path) -{ - if ((ifd = open(path, O_RDONLY, 0)) == -1) - { - /* failed to open path */ - fprintf(stderr, "sar: failed to open input file [%d][%s]\n", ifd, path); - exit_usage(); - } -} - -static void -read_record_hdr(hdr, writeflag) - struct record_hdr *hdr; - int writeflag; -{ - errno = 0; - int num = 0; - int n = 0; - size_t size = 0; - - size = sizeof(struct record_hdr); - - while (size) - { - num = read(ifd, &hdr[n], size); - if (num > 0) - { - n += num; - size -= num; - } - else if (num == 0) - exit_average(); - else - { - fprintf(stderr, "sar: read_record_data failed, errno=%d num=%d, size=%d\n", (int)errno, (int)num, (int)size); - exit(EXIT_FAILURE); - } - } - - if (oflag && writeflag) - write_record_hdr(hdr); - - return; -} - -static void -read_record_data(buf, size, writeflag) - char * buf; - size_t size; - int writeflag; -{ - errno = 0; - size_t num = 0; - size_t n = 0; - - while (size) - { - num = read(ifd, &buf[n], size); - if (num > 0) - { - n += num; - size -= num; - } - else if (num == 0) /* EOF */ - exit_average(); - else - { - fprintf(stderr, "sar: read_record_data failed, errno=%d num=%d, size=%d\n", (int)errno, (int)num, (int)size); - exit(EXIT_FAILURE); - } - } - - if (oflag && writeflag) - write_record_data(buf, n); - - return; -} - -static void -write_record_hdr(hdr) - struct record_hdr *hdr; -{ - errno = 0; - int num; - - if ((num = write(ofd, hdr, sizeof(struct record_hdr))) == -1) - { - fprintf(stderr, "sar: write_record_hdr failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - return; -} - -static void -write_record_data(char *buf, size_t nbytes) -{ - errno = 0; - int num; - if ((num = write(ofd, buf, nbytes)) == -1) - { - fprintf(stderr, "sar: write_record_data failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - return; -} - -/* - * Convert a string of one of the forms - * hh hh:mm hh:mm:ss - * into the number of seconds. - * exit on error -*/ - -static time_t -convert_hms(string) - char *string; -{ - int hh = 0; /* hours */ - int mm = 0; /* minutes */ - int ss = 0; /* seconds */ - time_t seconds; - time_t timestamp; - struct tm *tm; - int i; - - if (string == NULL || *string == '\0') - goto convert_err; - - for (i=0; string[i] != '\0'; i++) - { - if ((!isdigit(string[i])) && (string[i] != ':')) - { - goto convert_err; - } - } - - if (sscanf(string, "%d:%d:%d", &hh, &mm, &ss) != 3) - { - if (sscanf(string, "%d:%d", &hh, &mm) != 2) - { - if (sscanf(string, "%d", &hh) != 1) - { - goto convert_err; - } - } - } - - if (hh < 0 || hh >= HOURS_PER_DAY || - mm < 0 || mm >= MINS_PER_HOUR || - ss < 0 || ss > SECS_PER_MIN) - { - goto convert_err; - } - - seconds = ((((hh * MINS_PER_HOUR) + mm) * SECS_PER_MIN) + ss); - timestamp = time((time_t *)0); - tm=localtime(×tamp); - seconds -= tm->tm_gmtoff; - - return(seconds); - - convert_err: - fprintf(stderr, "sar: time format usage is hh[:mm[:ss]]\n"); - exit_usage(); - return(0); -} - - -/* - * Use ctime_r to convert a time value into - * a 26-character string of the form: - * - * Thu Nov 24 18:22:48 1986\n\0 - */ - -static char * -get_hms_string(tdata, tbuf) - time_t tdata; - char *tbuf; -{ - time_t t; - char *p; - - t = tdata; - ctime_r(&t, tbuf); - p=&tbuf[11]; - tbuf[19] = 0; - - return(p); -} - - -/* sample set flags */ -#define INIT_SET 0 -#define PRINT_SET 1 -#define PRINT_AVG 2 - -static void -do_main_workloop() -{ - struct record_hdr hdr; - time_t cur_timestamp = 0; /* seconds - Coordinated Universal Time */ - time_t next_timestamp = 0; /* seconds - Coordinated Universal Time */ - - if (!find_restart_header(&hdr)) - exit(1); - - cur_timestamp = hdr.rec_timestamp; - - /* convert sflag's start_time from 24 hour clock time to UTC seconds */ - if (start_time < (cur_timestamp % SECS_PER_DAY)) - start_time = cur_timestamp; - else - start_time += cur_timestamp - (cur_timestamp % SECS_PER_DAY); - - /* convert end_time, from 24 hour clock time to UTC seconds */ - if (end_time != 0) - end_time += cur_timestamp - (cur_timestamp % SECS_PER_DAY); - -#if 0 - fprintf(stderr, "start = %ld, end = %ld, cur=%ld, [24hour - %ld]\n", - start_time, end_time, cur_timestamp,(cur_timestamp % SECS_PER_DAY)); -#endif - - while (cur_timestamp < start_time) - { - bypass_sample_set(&hdr, cur_timestamp); - cur_timestamp = hdr.rec_timestamp; - } - - next_timestamp = cur_timestamp + iseconds; - print_all_column_headings(cur_timestamp); - read_sample_set(INIT_SET, cur_timestamp, &hdr); - cur_timestamp = hdr.rec_timestamp; - - while ((end_time == 0) || (next_timestamp < end_time)) - { - if (cur_timestamp < next_timestamp) - { - bypass_sample_set (&hdr, cur_timestamp); - cur_timestamp = hdr.rec_timestamp; - } - else - { - /* need to know the seconds interval when printing averages */ - if (avg_interval == 0) - { - if (iseconds) - avg_interval = iseconds; - else - avg_interval = cur_timestamp - next_timestamp; - } - next_timestamp = cur_timestamp + iseconds; - read_sample_set(PRINT_SET, cur_timestamp, &hdr); - cur_timestamp = hdr.rec_timestamp; - } - } - exit_average(); -} - - -/* - * Find and fill in a restart header. We don't write - * the binary data when looking for SAR_RESTART. - * Return: 1 on success - * 0 on failure - */ -static int -find_restart_header (ret_hdr) - struct record_hdr *ret_hdr; -{ - struct record_hdr hdr; - int bufsize = 0; - char *buf = NULL; - - errno = 0; - - restart_loop: - read_record_hdr(&hdr, FALSE); /* exits on error */ - - if (hdr.rec_type == SAR_RESTART) - { - *ret_hdr = hdr; - if (oflag) - write_record_hdr(&hdr); /* writes the RESTART record */ - if (buf) - free(buf); - return(1); - } - - /* - * not the record we want... - * read past data and try again - */ - if (hdr.rec_count) - { - if (fflag) - { /* seek past data in the file */ - if ((lseek(ifd, (hdr.rec_count * hdr.rec_size), SEEK_CUR)) == -1) - { - /*exit on error */ - fprintf(stderr, "sar: lseek failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - - } - /* compute data size - malloc a new buf if it's not big enough */ - else - { - /* have to read from the pipe */ - if (bufsize < (hdr.rec_count * hdr.rec_size)) - { - if (buf) - free(buf); - bufsize = hdr.rec_count * hdr.rec_size; - if((buf = (char *)malloc(bufsize)) == NULL) - { - fprintf(stderr, "sar: malloc failed\n"); - return(0); - } - } - /* exits on error */ - read_record_data(buf, (hdr.rec_count * hdr.rec_size), FALSE); - } - } - goto restart_loop; -} - -static void -print_all_column_headings(timestamp) - time_t timestamp; -{ - char timebuf[26]; - char *timebufp; - - timebufp = get_hms_string (timestamp, timebuf); - - if (uflag) /* print cpu headers */ - print_column_heading(SAR_CPU, timebufp, 0); - - if (gflag) /* print page-out activity */ - print_column_heading(SAR_VMSTAT, timebufp, 0); - - if (pflag ) /* print page-in activity */ - print_column_heading(SAR_VMSTAT, timebufp, 1); - - if (dflag) /* print drive stats */ - print_column_heading(SAR_DRIVESTATS, timebufp, 0); - - if (nflag) /* print network stats */ - { - if (network_mode & NET_DEV_MODE) - print_column_heading(SAR_NETSTATS, timebufp, NET_DEV_MODE); - - if (network_mode & NET_EDEV_MODE) - print_column_heading(SAR_NETSTATS, timebufp, NET_EDEV_MODE); - } -} - - -/* - * Find and fill in a timestamp header. - * Write the binary data when looking for SAR_TIMESTAMP - * Don't do anything with the data, just read past it. - * Return: 1 on success - * 0 on failure - */ -static int -bypass_sample_set (ret_hdr, timestamp) - struct record_hdr *ret_hdr; - time_t timestamp; -{ - struct record_hdr hdr; - int bufsize = 0; - char *buf = NULL; - - bypass_loop: - read_record_hdr(&hdr, TRUE); /* exits on error */ - - if (hdr.rec_type == SAR_TIMESTAMP) - { - *ret_hdr = hdr; - if (buf) - free(buf); - return(1); - } - - /* - * not the record we want... - * read past data and try again - */ - if (hdr.rec_count) - { - if (fflag && !oflag) - { - /* - * we're reading from a file and we don't have to write the - * binary data so seek past data in the file - */ - errno = 0; - if ((lseek(ifd, (hdr.rec_count * hdr.rec_size), SEEK_CUR)) == -1) - { - /*exit on error */ - fprintf(stderr, "sar: lseek failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - } - else - { - /* - * We end up here when reading from pipe. - * malloc a new buffer if current is not big enough - */ - if (bufsize < (hdr.rec_count * hdr.rec_size)) - { - if (buf) - free(buf); - bufsize = hdr.rec_count * hdr.rec_size; - if((buf = (char *)malloc(bufsize)) == NULL) - { - fprintf(stderr, "sar: malloc failed\n"); - exit(EXIT_FAILURE); - } - } - - /* exits on error */ - read_record_data(buf, (hdr.rec_count * hdr.rec_size), TRUE); - } - } /* end if hdr.rec_count */ - goto bypass_loop; -} - - -/* - * INIT_SET: This initializes the first sample for each type. - * PRINT_SET: This read, compute and print out sample data. - */ -static void -read_sample_set(flag, timestamp, ret_hdr) - int flag; - time_t timestamp; - struct record_hdr *ret_hdr; -{ - struct record_hdr hdr; - char timebuf[26]; - char *timebufp; - char *indent_string; - char *indent_string_wide; - char *indent_string_narrow; - int sar_cpu = 0; - int sar_vmstat=0; - int sar_drivestats=0; - int sar_drivepath=0; - int sar_netstats = 0; - - indent_string_wide = " "; - indent_string_narrow = " "; - indent_string = indent_string_narrow; - - read_record_hdr(&hdr, TRUE); - - while (hdr.rec_type != SAR_TIMESTAMP) - { - switch (hdr.rec_type) - { - case SAR_CPU: - sar_cpu = get_cpu_sample(flag, &hdr); - break; - case SAR_VMSTAT: - sar_vmstat=get_vmstat_sample(flag, &hdr); - break; - case SAR_DRIVEPATH: - sar_drivepath = get_drivepath_sample(flag, &hdr); - if (sar_drivepath < 0) - fprintf(stderr, "sar: drivepath sync code error %d\n", sar_drivepath); - break; - case SAR_DRIVESTATS: - sar_drivestats = get_drivestats_sample(flag, &hdr); - break; - case SAR_NETSTATS: - sar_netstats = get_netstats_sample(flag, &hdr); - break; - default: - break; - } - - read_record_hdr(&hdr, TRUE); - } - - /* return the timestamp header */ - *ret_hdr = hdr; - - if (flag == PRINT_SET) - { - avg_counter++; - timebufp = get_hms_string(timestamp, timebuf); - - if (uflag && sar_cpu) - print_cpu_sample(timebufp); - - if((gflag || pflag) && sar_vmstat) - print_vmstat_sample(timebufp); - - if (dflag && sar_drivestats) - print_drivestats_sample(timebufp); - - if (nflag && sar_netstats) - print_netstats_sample(timebufp); - } -} - -static void -skip_data(bufsize) - int bufsize; -{ - char *buf = NULL; - - if (fflag) - { - /* seek past data in the file */ - if ((lseek(ifd, bufsize, SEEK_CUR) == -1)) - { - /*exit on error */ - fprintf(stderr, "sar: lseek failed, errno=%d\n", errno); - exit(EXIT_FAILURE); - } - } - else - { - /* have to read from the pipe */ - if((buf = (char *)malloc(bufsize)) == NULL) - { - fprintf(stderr, "sar: malloc failed\n"); - exit(EXIT_FAILURE); - } - /* even though we skip this data, we still write it if necessary */ - read_record_data(buf, bufsize, TRUE); - } - if (buf) - free(buf); - - return; -} - -static int -get_cpu_sample(flag, hdr) - int flag; - struct record_hdr *hdr; -{ - int datasize; - - datasize = hdr->rec_count * hdr->rec_size; - - if (datasize != sizeof(host_cpu_load_info_data_t)) - { - /* read past the data but don't do anything with it */ - skip_data(datasize); - return(0); - } - - read_record_data ((char *)&cur_cpuload, (int)sizeof(host_cpu_load_info_data_t), TRUE ); - - if (flag == INIT_SET) - { - prev_cpuload = cur_cpuload; - bzero(&avg_cpuload, sizeof(avg_cpuload)); - } - return(1); -} - -static void -print_cpu_sample(timebufptr) - char * timebufptr; -{ - - double time; - - time = 0.0; - cur_cpuload.cpu_ticks[CPU_STATE_USER] - -= prev_cpuload.cpu_ticks[CPU_STATE_USER]; - - prev_cpuload.cpu_ticks[CPU_STATE_USER] - += cur_cpuload.cpu_ticks[CPU_STATE_USER]; - - time += cur_cpuload.cpu_ticks[CPU_STATE_USER]; - - cur_cpuload.cpu_ticks[CPU_STATE_NICE] - -= prev_cpuload.cpu_ticks[CPU_STATE_NICE]; - - prev_cpuload.cpu_ticks[CPU_STATE_NICE] - += cur_cpuload.cpu_ticks[CPU_STATE_NICE]; - - time += cur_cpuload.cpu_ticks[CPU_STATE_NICE]; - - cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM] - -= prev_cpuload.cpu_ticks[CPU_STATE_SYSTEM]; - - prev_cpuload.cpu_ticks[CPU_STATE_SYSTEM] - += cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]; - - time += cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]; - - cur_cpuload.cpu_ticks[CPU_STATE_IDLE] - -= prev_cpuload.cpu_ticks[CPU_STATE_IDLE]; - - prev_cpuload.cpu_ticks[CPU_STATE_IDLE] - += cur_cpuload.cpu_ticks[CPU_STATE_IDLE]; - - time += cur_cpuload.cpu_ticks[CPU_STATE_IDLE]; - - avg_cpuload.cpu_ticks[CPU_STATE_USER] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER] - / (time ? time : 1)); - - avg_cpuload.cpu_ticks[CPU_STATE_NICE] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE] - / (time ? time : 1)); - - avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM] - / (time ? time : 1)); - - avg_cpuload.cpu_ticks[CPU_STATE_IDLE] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_IDLE] - / (time ? time : 1)); - - if(flag_count > 1) - print_column_heading(SAR_CPU, timebufptr, 0); - - fprintf(stdout, "%s%5.0f ", timebufptr, - rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER] - / (time ? time : 1))); - - fprintf(stdout, "%4.0f ", - rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE] - / (time ? time : 1))); - - fprintf(stdout, "%4.0f ", - rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM] - / (time ? time : 1))); - - fprintf(stdout, "%4.0f\n", - rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_IDLE] - / (time ? time : 1))); -} - -static int -get_vmstat_sample(flag, hdr) - int flag; - struct record_hdr *hdr; -{ - int datasize; - - datasize = hdr->rec_count * hdr->rec_size; - - if (datasize != sizeof(struct vm_statistics)) - { - /* read past the data but don't do anything with it */ - skip_data(datasize); - return(0); - } - - read_record_data ((char *)&cur_vmstat, (int)sizeof(struct vm_statistics), TRUE ); - - if (flag == INIT_SET) - { - prev_vmstat = cur_vmstat; - bzero(&avg_vmstat, sizeof(avg_vmstat)); - } - return(1); -} - - -static void -print_vmstat_sample(char *timebufptr) -{ - - cur_vmstat.faults -= prev_vmstat.faults; - prev_vmstat.faults += cur_vmstat.faults; - avg_vmstat.faults += cur_vmstat.faults; - - cur_vmstat.cow_faults -= prev_vmstat.cow_faults; - prev_vmstat.cow_faults += cur_vmstat.cow_faults; - avg_vmstat.cow_faults += cur_vmstat.cow_faults; - - cur_vmstat.zero_fill_count -= prev_vmstat.zero_fill_count; - prev_vmstat.zero_fill_count += cur_vmstat.zero_fill_count; - avg_vmstat.zero_fill_count += cur_vmstat.zero_fill_count; - - cur_vmstat.reactivations -= prev_vmstat.reactivations; - prev_vmstat.reactivations += cur_vmstat.reactivations; - avg_vmstat.reactivations += cur_vmstat.reactivations; - - cur_vmstat.pageins -= prev_vmstat.pageins; - prev_vmstat.pageins += cur_vmstat.pageins; - avg_vmstat.pageins += cur_vmstat.pageins; - - cur_vmstat.pageouts -= prev_vmstat.pageouts; - prev_vmstat.pageouts += cur_vmstat.pageouts; - avg_vmstat.pageouts += cur_vmstat.pageouts; - - - if (gflag) - { - if (flag_count > 1) - print_column_heading(SAR_VMSTAT, timebufptr, 0); - fprintf(stdout, "%s %8.1f \n", timebufptr, (float)((float)cur_vmstat.pageouts/avg_interval)); - } - - if (pflag) - { - if (flag_count > 1) - print_column_heading(SAR_VMSTAT, timebufptr, 1); - fprintf(stdout, "%s %8.1f %8.1f %8.1f\n", timebufptr, - (float)((float)cur_vmstat.pageins / avg_interval), - (float)((float)cur_vmstat.cow_faults/avg_interval), - (float)((float)cur_vmstat.faults/avg_interval)); - } - fflush(stdout); -} - -static int -get_drivestats_sample(flag, hdr) - int flag; - struct record_hdr *hdr; -{ - struct drivestats *databuf; - struct drivestats_report *dr; - size_t datasize; - int datacount; - int index; - int i; - - datasize = hdr->rec_count * hdr->rec_size; - datacount = hdr->rec_count; - - if (hdr->rec_size != sizeof(struct drivestats)) - { - /* something isn't right... read past the data but don't analyze it */ - skip_data(datasize); - return(0); - } - - /* malloc read buffer */ - if ((databuf = (struct drivestats *)malloc(datasize)) == NULL) - { - fprintf(stderr, "sar: malloc failed\n"); - exit (EXIT_FAILURE); - } - - bzero(databuf, datasize); - - read_record_data ((char *)databuf, datasize, TRUE ); - - /* clear all global current fields */ - for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - dr->present = 0; - dr->cur_Reads = 0; - dr->cur_BytesRead = 0; - dr->cur_Writes = 0; - dr->cur_BytesWritten = 0; - dr->cur_LatentReadTime = 0; - dr->cur_LatentWriteTime = 0; - dr->cur_ReadErrors = 0; - dr->cur_WriteErrors = 0; - dr->cur_ReadRetries = 0; - dr->cur_WriteRetries = 0; - dr->cur_TotalReadTime = 0; - dr->cur_TotalWriteTime=0; - } - - /* By this point, we have read in a complete set of diskstats from the sadc - * data collector. - * The order of the drives in not guaranteed. - * The global report structure is a linked list, but may need initialization - * We need to traverse this list and transfer the current - * read data. If a disk entry isn't found, then we need to allocate one - * initilize it. - */ - for (i=0; i< datacount; i++) - { - struct drivestats_report *dr_last = NULL; - - index = databuf[i].drivepath_id; /* use this as index into dp_table */ - - /* find disk entry or allocate new one*/ - for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - dr_last = dr; - if(index == dr->drivepath_id) - break; - } - - if (dr == NULL) - { - /* allocate new entry */ - if((dr = (struct drivestats_report *)malloc(sizeof(struct drivestats_report))) == NULL) - { - fprintf(stderr, "sar: malloc error\n"); - exit(EXIT_FAILURE); - } - bzero((char *)dr, sizeof(struct drivestats_report)); - dr->blocksize = databuf[i].blocksize; - dr->drivepath_id = index; - dr->next = NULL; - dr->avg_count = 0; - - /* get the BSDName which should be in the table by now */ - if ((index < dp_count) && (dp_table[index].state != DPSTATE_UNINITIALIZED)) - strncpy(dr->name, dp_table[index].BSDName, MAXDRIVENAME+1); - else - strcpy(dr->name, "disk??"); - - if (dr_head == NULL) - { - dr_head = dr; - dr_head->next = NULL; - } - else - { - dr_last->next = (char *)dr; - } - } /* end if dr == NULL */ - - dr->present = TRUE; - dr->cur_Reads = databuf[i].Reads; - dr->cur_BytesRead = databuf[i].BytesRead; - dr->cur_Writes = databuf[i].Writes; - dr->cur_BytesWritten = databuf[i].BytesWritten; - dr->cur_LatentReadTime = databuf[i].LatentReadTime; - dr->cur_LatentWriteTime = databuf[i].LatentWriteTime; - dr->cur_ReadErrors = databuf[i].ReadErrors; - dr->cur_WriteErrors = databuf[i].WriteErrors; - dr->cur_ReadRetries = databuf[i].ReadRetries; - dr->cur_WriteRetries = databuf[i].WriteRetries; - dr->cur_TotalReadTime = databuf[i].TotalReadTime; - dr->cur_TotalWriteTime=databuf[i].TotalWriteTime; - } /* end for loop */ - - /* Reinitialize the prev and avg fields when - * This is a new disk - * This is a changed disk - name change implies disk swapping - * This disk is not present in this sample - */ - for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - if (dr->drivepath_id >= dp_count) - { - /* something is amiss */ - continue; - } - else - { - index = dr->drivepath_id; /* use this as index into dp_table */ - } - - if ((flag == INIT_SET) || - (dp_table[index].state == DPSTATE_NEW) || - (dp_table[index].state == DPSTATE_CHANGED) || - (!dr->present)) - { - /* - * prev will be set to cur - * activate the state in dp_table - */ - if (dr->present) - dp_table[index].state = DPSTATE_ACTIVE; - - init_drivestats(dr); - } - } - return(1); -} - -static void -init_drivestats(struct drivestats_report *dr) -{ - dr->avg_count = 0; - dr->prev_Reads = dr->cur_Reads; - dr->avg_Reads = 0; - dr->prev_BytesRead = dr->cur_BytesRead; - dr->avg_BytesRead = 0; - dr->prev_Writes = dr->cur_Writes; - dr->avg_Writes = 0; - dr->prev_BytesWritten = dr->cur_BytesWritten; - dr->avg_BytesWritten = 0; - dr->prev_LatentReadTime = dr->cur_LatentReadTime; - dr->avg_LatentReadTime = 0; - dr->prev_LatentWriteTime = dr->cur_LatentWriteTime ; - dr->avg_LatentWriteTime = 0; - dr->prev_ReadErrors = dr->cur_ReadErrors ; - dr->avg_ReadErrors = 0; - dr->prev_WriteErrors = dr->cur_WriteErrors ; - dr->avg_WriteErrors = 0; - dr->prev_ReadRetries = dr->cur_ReadRetries ; - dr->avg_ReadRetries = 0; - dr->prev_WriteRetries = dr->cur_WriteRetries ; - dr->avg_WriteRetries = 0; - dr->prev_TotalReadTime = dr->cur_TotalReadTime ; - dr->avg_TotalReadTime = 0; - dr->prev_TotalWriteTime = dr->cur_TotalWriteTime ; - dr->avg_TotalWriteTime = 0; -} - - -static void -print_drivestats_sample(char *timebufptr) -{ - struct drivestats_report *dr; - long double transfers_per_second; - long double kb_per_transfer, mb_per_second; - u_int64_t interval_bytes, interval_transfers, interval_blocks; - u_int64_t interval_time; - long double blocks_per_second, ms_per_transaction; - - if (flag_count > 1) - print_column_heading(SAR_DRIVESTATS, timebufptr, 0); - - for (dr=dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - if(!dr->present) - continue; - - /* - * This sanity check is for drives that get removed and then - * returned during the sampling sleep interval. If anything - * looks out of sync, reinit and skip this entry. There is - * no way to guard against this entirely. - */ - if ((dr->cur_Reads < dr->prev_Reads) || - (dr->cur_BytesRead < dr->prev_BytesRead) || - (dr->cur_Writes < dr->prev_Writes) || - (dr->cur_BytesWritten < dr->prev_BytesWritten)) - { - init_drivestats(dr); - continue; - } - - dr->avg_count++; - - dr->cur_Reads -= dr->prev_Reads; - dr->prev_Reads += dr->cur_Reads; - dr->avg_Reads += dr->cur_Reads; - - dr->cur_BytesRead -= dr->prev_BytesRead; - dr->prev_BytesRead += dr->cur_BytesRead; - dr->avg_BytesRead += dr->cur_BytesRead; - - dr->cur_Writes -= dr->prev_Writes ; - dr->prev_Writes += dr->cur_Writes ; - dr->avg_Writes += dr->cur_Writes ; - - dr->cur_BytesWritten -= dr->prev_BytesWritten ; - dr->prev_BytesWritten += dr->cur_BytesWritten ; - dr->avg_BytesWritten += dr->cur_BytesWritten ; - - dr->cur_LatentReadTime -= dr->prev_LatentReadTime ; - dr->prev_LatentReadTime += dr->cur_LatentReadTime ; - dr->avg_LatentReadTime += dr->cur_LatentReadTime ; - - dr->cur_LatentWriteTime -= dr->prev_LatentWriteTime ; - dr->prev_LatentWriteTime += dr->cur_LatentWriteTime ; - dr->avg_LatentWriteTime += dr->cur_LatentWriteTime ; - - dr->cur_ReadErrors -= dr->prev_ReadErrors ; - dr->prev_ReadErrors += dr->cur_ReadErrors ; - dr->avg_ReadErrors += dr->cur_ReadErrors ; - - dr->cur_WriteErrors -= dr->prev_WriteErrors ; - dr->prev_WriteErrors += dr->cur_WriteErrors ; - dr->avg_WriteErrors += dr->cur_WriteErrors ; - - dr->cur_ReadRetries -= dr->prev_ReadRetries ; - dr->prev_ReadRetries += dr->cur_ReadRetries ; - dr->avg_ReadRetries += dr->cur_ReadRetries ; - - dr->cur_WriteRetries -= dr->prev_WriteRetries ; - dr->prev_WriteRetries += dr->cur_WriteRetries; - dr->avg_WriteRetries += dr->cur_WriteRetries; - - dr->cur_TotalReadTime -= dr->prev_TotalReadTime ; - dr->prev_TotalReadTime += dr->cur_TotalReadTime ; - dr->avg_TotalReadTime += dr->cur_TotalReadTime ; - - dr->cur_TotalWriteTime -= dr->prev_TotalWriteTime ; - dr->prev_TotalWriteTime += dr->cur_TotalWriteTime ; - dr->avg_TotalWriteTime += dr->cur_TotalWriteTime ; - - /* I/O volume */ - interval_bytes = dr->cur_BytesRead + dr->cur_BytesWritten; - - /* I/O counts */ - interval_transfers = dr->cur_Reads + dr->cur_Writes; - - /* I/O time */ - interval_time = dr->cur_LatentReadTime + dr->cur_LatentWriteTime; - - interval_blocks = interval_bytes / dr->blocksize; - blocks_per_second = interval_blocks / avg_interval; - transfers_per_second = interval_transfers / avg_interval; - mb_per_second = (interval_bytes / avg_interval) / (1024 *1024); - - kb_per_transfer = (interval_transfers > 0) ? - ((long double)interval_bytes / interval_transfers) - / 1024 : 0; - - /* times are in nanoseconds, convert to milliseconds */ - ms_per_transaction = (interval_transfers > 0) ? - ((long double)interval_time / interval_transfers) - / 1000 : 0; - - /* print device name */ - fprintf(stdout, "%s %-10s", timebufptr, dr->name); - - /* print transfers per second */ - fprintf(stdout, "%4.0Lf ", transfers_per_second); - - /* print blocks per second - in device blocksize */ - fprintf(stdout, "%4.0Lf\n", blocks_per_second); - } -} - -/* - * Print averages before exiting. - */ -static void -exit_average() -{ - int i; - - if (avg_counter <= 0 ) - exit(0); - - if (oflag) - { - if (ofd) - close (ofd); - ofd = 0; - } - - if (uflag) /* print cpu averages */ - { - if(flag_count > 1) - print_column_heading(SAR_CPU, 0, 0); - - fprintf(stdout, "Average: %5d ", - (int)avg_cpuload.cpu_ticks[CPU_STATE_USER] - / (avg_counter ? avg_counter : 1)); - - fprintf(stdout, "%4d ", - (int)avg_cpuload.cpu_ticks[CPU_STATE_NICE] - / (avg_counter ? avg_counter : 1)); - - fprintf(stdout, "%4d ", - (int)avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM] - / (avg_counter ? avg_counter : 1)); - - fprintf(stdout, "%4d \n", - (int)avg_cpuload.cpu_ticks[CPU_STATE_IDLE] - / (avg_counter ? avg_counter : 1)); - - fflush(stdout); - } - - - if (gflag) /* print page-out averages */ - { - if (flag_count > 1) - print_column_heading(SAR_VMSTAT, 0, 0); - - fprintf(stdout, "Average: %8.1f\n", - (float)((avg_vmstat.pageouts / (avg_counter ? avg_counter : 1)) / avg_interval)); - fflush(stdout); - } - - if (pflag) /* print page-in averages */ - { - if (flag_count > 1) - print_column_heading(SAR_VMSTAT, 0, 1); - - fprintf(stdout, "Average: %8.1f %8.1f %8.1f\n", - (float)(((float)avg_vmstat.pageins / (avg_counter ? avg_counter : 1)) / avg_interval), - (float)(((float)avg_vmstat.cow_faults / (avg_counter ? avg_counter : 1)) / avg_interval), - (float)(((float)avg_vmstat.faults / (avg_counter ? avg_counter : 1)) / avg_interval)); - fflush(stdout); - } - - if (dflag) /* print drivestats averages */ - { - struct drivestats_report *dr; - long double transfers_per_second; - long double kb_per_transfer, mb_per_second; - u_int64_t total_bytes, total_transfers, total_blocks; - u_int64_t total_time; - long double blocks_per_second, ms_per_transaction; - int msdig; - - if (flag_count > 1) - print_column_heading(SAR_DRIVESTATS, 0, 0); - - for (dr=dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - /* don't bother to print out averages for disks that were removed */ - if (!dr->present) - continue; - - fprintf(stdout, " %s %s\n", - dp_table[dr->drivepath_id].BSDName, dp_table[dr->drivepath_id].ioreg_path); - - /* I/O volume */ - total_bytes = dr->avg_BytesRead + dr->avg_BytesWritten; - - /* I/O counts */ - total_transfers = dr->avg_Reads + dr->avg_Writes; - - /* I/O time */ - total_time = dr->avg_LatentReadTime + dr->avg_LatentWriteTime; - - total_blocks = total_bytes / dr->blocksize; - blocks_per_second = total_blocks / avg_interval; - transfers_per_second = total_transfers / avg_interval; - mb_per_second = (total_bytes / avg_interval) / (1024 *1024); - - kb_per_transfer = (total_transfers > 0) ? - ((long double)total_bytes / total_transfers) - / 1024 : 0; - - /* times are in nanoseconds, convert to milliseconds */ - ms_per_transaction = (total_transfers > 0) ? - ((long double)total_time / total_transfers) - / 1000 : 0; - msdig = (ms_per_transaction < 100.0) ? 1 : 0; - fprintf(stdout, "Average: %-10s %4.0Lf %4.0Lf\n", - dr->name, - (transfers_per_second / dr->avg_count), - (blocks_per_second / dr->avg_count)); - - fflush(stdout); - } - } /* end if dflag */ - - if (nflag) - { - int avg_count; - - if (network_mode & NET_DEV_MODE) - { - if (flag_count > 1) - print_column_heading(SAR_NETSTATS, 0, NET_DEV_MODE); - for (i = 0; i < nr_count; i++) - { - if (!nr_table[i].valid) - continue; - - if(nr_table[i].avg_count == 0) - avg_count = 1; - else - avg_count = nr_table[i].avg_count; - - fprintf(stdout, "Average: %-8.8s", nr_table[i].tname_unit); - - fprintf (stdout, "%8llu ", - ((nr_table[i].avg_ipackets / avg_count) / avg_interval)); - - fprintf (stdout, "%10llu ", - ((nr_table[i].avg_ibytes / avg_count) / avg_interval)); - - fprintf (stdout, "%8llu ", - ((nr_table[i].avg_opackets / avg_count) / avg_interval)); - - fprintf (stdout, "%10llu\n", - ((nr_table[i].avg_obytes / avg_count) / avg_interval)); - - fflush(stdout); - } - } - - if (network_mode & NET_EDEV_MODE) - { - - if(flag_count > 1) - print_column_heading(SAR_NETSTATS, 0, NET_EDEV_MODE); - - for (i = 0; i < nr_count; i++) - { - if (!nr_table[i].valid) - continue; - - if(nr_table[i].avg_count == 0) - avg_count = 1; - else - avg_count = nr_table[i].avg_count; - - fprintf(stdout, "Average: %-8.8s ", nr_table[i].tname_unit); - - fprintf (stdout, "%7llu ", - ((nr_table[i].avg_ierrors / avg_count) / avg_interval)); - - fprintf (stdout, "%7llu ", - ((nr_table[i].avg_oerrors / avg_count) / avg_interval)); - - fprintf (stdout, "%5llu ", - ((nr_table[i].avg_collisions / avg_count) / avg_interval)); - - fprintf (stdout, " %5llu\n", - ((nr_table[i].avg_drops / avg_count) / avg_interval)); - - fflush(stdout); - } - } - - } /* end if nflag */ - exit(0); -} - - -/* - * Return < 0 failure, debugging purposes only - * Return = 0 data skipped - * Return > 0 success - */ - -static int -get_drivepath_sample(flag, hdr) - int flag; - struct record_hdr *hdr; -{ - size_t datasize; - struct drivepath dp; - struct drivestats_report *dr; - int i, n; - - datasize = hdr->rec_count * hdr->rec_size; - - if (datasize != sizeof(struct drivepath)) - { - /* read past the data but don't do anything with it */ - skip_data(datasize); - return(0); - } - - read_record_data ((char *)&dp, (int)sizeof(struct drivepath), TRUE ); - - /* - * If state is new -- put a new entry in the dp_table. - * If state is changed -- traverse the drivestats_report table - * and copy new name. - */ - if (dp.state == DPSTATE_NEW) - { - - if (dp_table == NULL) - { - if (dp.drivepath_id != 0) - return(-1); - /* First setup of internal drivepath table */ - dp_table = (struct drivepath *)malloc(sizeof(struct drivepath)); - if (dp_table == NULL) - return(-2); - dp_count = 1; - } - - if (dflag) - fprintf(stdout, "New Disk: [%s] %s\n", dp.BSDName, dp.ioreg_path); - - /* traverse table and find next uninitialized entry */ - for (i = 0; i< dp_count; i++) - { - if (dp_table[i].state == DPSTATE_UNINITIALIZED) - { - if (dp.drivepath_id != i) - { - /* the table is out of sync - this should not happen */ - return (-3); - } - dp_table[i] = dp; - return(1); - } - } - /* - * If we get here, we've run out of table entries. - * Double the size of the table, then assign the next entry. - */ - if (dp.drivepath_id != i) - { - /* the table is out of sync - this should not happen */ - return (-4); - } - n = dp_count * 2; - dp_table = (struct drivepath *)realloc(dp_table, n * sizeof(struct drivepath)); - bzero(&dp_table[dp_count], dp_count * sizeof(struct drivepath)); - dp_table[dp_count] = dp; - dp_count = n; - return(1); - - } - else if (dp.state == DPSTATE_CHANGED) - { - - /* Update the name in the table */ - if ((dp.drivepath_id < dp_count) && (dp_table[dp.drivepath_id].state != DPSTATE_UNINITIALIZED)) - { - if (strcmp(dp_table[dp.drivepath_id].ioreg_path, dp.ioreg_path) != 0) - { - /* something is amiss */ - return (-5); - } - else - { - if (dflag) - { - fprintf(stdout, "Change: [%s] %s\n", dp.BSDName, - dp_table[dp.drivepath_id].ioreg_path); - } - strcpy(dp_table[dp.drivepath_id].BSDName, dp.BSDName); - - for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next) - { - if (dr->drivepath_id == dp.drivepath_id) - strcpy(dr->name, dp.BSDName); - } - return(1); - } - } - else - return(-6); - } - return(-7); -} - -/* - * Bytes and packet counts are used to track - * counter wraps. So, don't enforce the - * NET_DEV_MODE or NET_EDEV_MODE in here. - * Maintain all the stats. - */ -static void -set_cur_netstats(struct netstats_report *nr, struct netstats *ns) -{ - - nr->cur_ipackets = ns->net_ipackets; - nr->cur_ibytes = ns->net_ibytes; - nr->cur_opackets = ns->net_opackets; - nr->cur_obytes = ns->net_obytes; - - nr->cur_ierrors = ns->net_ierrors; - nr->cur_oerrors = ns->net_oerrors; - nr->cur_collisions = ns->net_collisions; - nr->cur_drops = ns->net_drops; - - nr->cur_imcasts = ns->net_imcasts; - nr->cur_omcasts = ns->net_omcasts; - -} - -static void -init_prev_netstats(struct netstats_report *nr) -{ - nr->avg_count = 0; - nr->valid = 1; - nr->present = 1; - - nr->prev_ipackets = nr->cur_ipackets; - nr->avg_ipackets = 0; - nr->prev_ibytes = nr->cur_ibytes; - nr->avg_ibytes = 0; - nr->prev_opackets = nr->cur_opackets; - nr->avg_opackets = 0; - nr->prev_obytes = nr->cur_obytes; - nr->avg_obytes = 0; - - nr->prev_ierrors = nr->cur_ierrors; - nr->avg_ierrors = 0; - nr->prev_oerrors = nr->cur_oerrors ; - nr->avg_oerrors = 0; - nr->prev_collisions = nr->cur_collisions ; - nr->avg_collisions = 0; - nr->prev_drops = nr->cur_drops ; - nr->avg_drops = 0; - - /* track these, but never displayed */ - nr->prev_imcasts = nr->cur_imcasts; - nr->avg_imcasts = 0; - nr->prev_omcasts = nr->cur_omcasts; - nr->avg_omcasts = 0; -} - -/* - * Success : 1 - * Failure : 0 - */ -static int -get_netstats_sample(flag, hdr) - int flag; - struct record_hdr *hdr; -{ - struct netstats *databuf = NULL; - size_t datasize; - int datacount; - int i, j; - - datasize = hdr->rec_count * hdr->rec_size; - datacount = hdr->rec_count; - - if (hdr->rec_size != sizeof(struct netstats)) - { - /* something isn't right... read past the data but don't analyze it */ - skip_data(datasize); - return(0); - } - - /* malloc new or bigger read buffer */ - if((netstat_readbuf == NULL) || (netstat_readbuf_size < datasize)) - { - if (netstat_readbuf) - free (netstat_readbuf); - - if ((netstat_readbuf = (struct netstats *)malloc(datasize)) == NULL) - { - fprintf(stderr, "sar: malloc failed\n"); - exit (EXIT_FAILURE); - } - netstat_readbuf_size = datasize; - } - - bzero(netstat_readbuf, netstat_readbuf_size); - databuf = netstat_readbuf; - - read_record_data ((char *)databuf, datasize, TRUE ); - - if (nr_table == NULL) - { - /* initial internal table setup */ - nr_table = (struct netstats_report *)malloc(datacount * sizeof(struct netstats_report)); - nr_count = datacount; - bzero(nr_table, (datacount * sizeof(struct netstats_report))); - - /* on first init, this is faster than finding our way to NEW_ENTRY */ - for (i = 0; i < datacount; i++) - { - if (!(network_mode & NET_PPP_MODE)) - { - if (!strncmp(databuf[i].tname_unit, "ppp", 3)) - continue; /* - * Skip ppp interfaces. - * ie don't even put them in this internal table. - */ - } - strncpy(nr_table[i].tname_unit, databuf[i].tname_unit, MAX_TNAME_UNIT_SIZE); - nr_table[i].tname_unit[MAX_TNAME_UNIT_SIZE] = '\0'; - set_cur_netstats(&nr_table[i], &databuf[i]); - init_prev_netstats(&nr_table[i]); - } - return(1); - } - - /* - * clear all the present flags. - * As we traverse the current sample set - * and update the internal table, the flag - * is reset. - */ - for (i = 0; i < nr_count; i++) - { - nr_table[i].present = 0; - } - - /* - * Find and update table entries. - * Init new entries. - */ - for (i=0; i 1)) - fprintf(stdout, "\n"); - - if (network_mode & NET_DEV_MODE) - { - if (flag_count > 1) - print_column_heading(SAR_NETSTATS, timebufptr, NET_DEV_MODE); - - for (i=0; i < nr_count; i++) - { - if (!nr_table[i].valid) - continue; - - if (!(network_mode & NET_PPP_MODE)) - { - if (!strncmp(nr_table[i].tname_unit, "ppp", 3)) - { - continue; /* skip any ppp interfaces */ - } - } - - /* print the interface name */ - fprintf(stdout, "%s %-8.8s", timebufptr, nr_table[i].tname_unit); - - fprintf (stdout, "%8llu ", - (nr_table[i].cur_ipackets / avg_interval)); - - fprintf (stdout, "%10llu ", - (nr_table[i].cur_ibytes / avg_interval)); - - fprintf (stdout, "%8llu ", - (nr_table[i].cur_opackets / avg_interval)); - - fprintf (stdout, "%10llu\n", - (nr_table[i].cur_obytes / avg_interval)); - } - } - - - if (network_mode & NET_EDEV_MODE) - { - if(flag_count > 1) - { - print_column_heading(SAR_NETSTATS, timebufptr, NET_EDEV_MODE); - } - - for (i=0; i < nr_count; i++) - { - if (!nr_table[i].valid) - continue; - - if (!(network_mode & NET_PPP_MODE)) - { - if (!strncmp(nr_table[i].tname_unit, "ppp", 3)) - { - continue; /* skip any ppp interfaces */ - } - } - - /* print the interface name */ - fprintf(stdout, "%s %-8.8s ", timebufptr, nr_table[i].tname_unit); - - fprintf (stdout, "%7llu ", - (nr_table[i].cur_ierrors / avg_interval)); - - fprintf (stdout, "%7llu ", - (nr_table[i].cur_oerrors / avg_interval)); - - fprintf (stdout, "%5llu ", - (nr_table[i].cur_collisions / avg_interval)); - - fprintf (stdout, " %5llu\n", - (nr_table[i].cur_drops / avg_interval)); - } - fflush(stdout); - } -} - -static void -print_column_heading(int type, char *timebufptr, int mode) -{ - char *p; - - p = timebufptr; - - if (p == NULL) - p = "Average:"; - - if (!(flag_count > 1)) - fprintf(stdout, "\n"); - - switch (type) - { - case SAR_CPU: - fprintf (stdout, "\n%s %%usr %%nice %%sys %%idle\n", p); - break; - - case SAR_VMSTAT: - if (mode == 0) /* gflag */ - fprintf(stdout, "\n%s pgout/s\n", p); - else if (mode == 1) /* pflag */ - fprintf(stdout, "\n%s pgin/s pflt/s vflt/s\n", p); - break; - case SAR_DRIVESTATS: - fprintf(stdout, "\n%s device r+w/s blks/s\n", p); - break; - case SAR_NETSTATS: - if (mode == NET_DEV_MODE) - { - fprintf(stdout, "\n%s %-8.8s %8.8s %10.10s %8.8s %10.10s\n", p, - " IFACE", "Ipkts/s", "Ibytes/s", "Opkts/s", "Obytes/s"); - } - else if (mode == NET_EDEV_MODE) - { - fprintf(stdout, "\n%s %-8.8s %7.7s %7.7s %5s %s\n", p, - " IFACE", "Ierrs/s", "Oerrs/s", "Coll/s", "Drop/s"); - } - break; - default: - break; - } -} - diff --git a/sar.tproj/sar.h b/sar.tproj/sar.h deleted file mode 100644 index 2ff405e..0000000 --- a/sar.tproj/sar.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Portions Copyright (c) 1999-2003 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 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. -*/ - -#include -#include -#include -#include -#include - -#define MAXDRIVENAME 31 /* largest drive name we allow */ - - -struct drivestats_report -{ - char *next; - int32_t present; - int32_t avg_count; - int32_t drivepath_id; - char name[MAXDRIVENAME+1]; - uint64_t blocksize; - - uint64_t cur_Reads; - uint64_t prev_Reads; - uint64_t avg_Reads; - - uint64_t cur_BytesRead; - uint64_t prev_BytesRead; - uint64_t avg_BytesRead; - - uint64_t cur_Writes; - uint64_t prev_Writes; - uint64_t avg_Writes; - - uint64_t cur_BytesWritten; - uint64_t prev_BytesWritten; - uint64_t avg_BytesWritten; - - uint64_t cur_LatentReadTime; - uint64_t prev_LatentReadTime; - uint64_t avg_LatentReadTime; - - uint64_t cur_LatentWriteTime; - uint64_t prev_LatentWriteTime; - uint64_t avg_LatentWriteTime; - - uint64_t cur_ReadErrors; - uint64_t prev_ReadErrors; - uint64_t avg_ReadErrors; - - uint64_t cur_WriteErrors; - uint64_t prev_WriteErrors; - uint64_t avg_WriteErrors; - - uint64_t cur_ReadRetries; - uint64_t prev_ReadRetries; - uint64_t avg_ReadRetries; - - uint64_t cur_WriteRetries; - uint64_t prev_WriteRetries; - uint64_t avg_WriteRetries; - - uint64_t cur_TotalReadTime; - uint64_t prev_TotalReadTime; - uint64_t avg_TotalReadTime; - - uint64_t cur_TotalWriteTime; - uint64_t prev_TotalWriteTime; - uint64_t avg_TotalWriteTime; -}; - -struct netstats_report -{ - int32_t valid; - int32_t present; - int32_t avg_count; - uint32_t gen_counter; - char tname_unit[MAX_TNAME_UNIT_SIZE +1 ]; - - uint64_t cur_ipackets; - uint64_t prev_ipackets; - uint64_t avg_ipackets; - - uint64_t cur_ierrors; - uint64_t prev_ierrors; - uint64_t avg_ierrors; - - uint64_t cur_opackets; - uint64_t prev_opackets; - uint64_t avg_opackets; - - uint64_t cur_oerrors; - uint64_t prev_oerrors; - uint64_t avg_oerrors; - - uint64_t cur_collisions; - uint64_t prev_collisions; - uint64_t avg_collisions; - - uint64_t cur_ibytes; - uint64_t prev_ibytes; - uint64_t avg_ibytes; - - uint64_t cur_obytes; - uint64_t prev_obytes; - uint64_t avg_obytes; - - uint64_t cur_imcasts; - uint64_t prev_imcasts; - uint64_t avg_imcasts; - - uint64_t cur_omcasts; - uint64_t prev_omcasts; - uint64_t avg_omcasts; - - uint64_t cur_drops; - uint64_t prev_drops; - uint64_t avg_drops; -}; diff --git a/sc_usage.tproj/sc_usage.c b/sc_usage.tproj/sc_usage.c index 5e7f768..d39e8ef 100644 --- a/sc_usage.tproj/sc_usage.c +++ b/sc_usage.tproj/sc_usage.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999-2007 Apple Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ @@ -119,7 +119,7 @@ struct entry { }; struct th_info { - int thread; + uintptr_t thread; int depth; int vfslookup; int curpri; @@ -129,7 +129,7 @@ struct th_info { }; struct sc_entry { - char name[32]; + char name[64]; int delta_count; int total_count; int waiting; @@ -194,10 +194,9 @@ int scalls; #define DIVISOR 16.6666 /* Trace divisor converts to microseconds */ double divisor = DIVISOR; - int mib[6]; size_t needed; -char *my_buffer; +void *my_buffer; kbufinfo_t bufinfo = {0, 0, 0, 0}; @@ -205,29 +204,36 @@ int trace_enabled = 0; int set_remove_flag = 1; struct kinfo_proc *kp_buffer = 0; -int kp_nentries = 0; +size_t kp_nentries = 0; extern char **environ; -void set_enable(); -void set_pidcheck(); -void set_remove(); -void set_numbufs(); -void set_init(); +static void set_enable(int); +static void set_pidcheck(int, int); +static void set_remove(void); +static void set_numbufs(int); +static void set_init(void); void quit(char *); int argtopid(char *); int argtoi(int, char*, char*, int); void get_bufinfo(kbufinfo_t *); - +static void reset_counters(void); +static void getdivisor(void); +static void screen_update(void); +static void sc_tab_init(char *); +static void sort_scalls(void); +static void sample_sc(void); +static int find_msgcode(int); /* * signal handlers */ -void leave() /* exit under normal conditions -- INT handler */ +/* exit under normal conditions -- INT handler */ +static void +leave(__unused int unused) { - if (no_screen_refresh == 0) { move(LINES - 1, 0); refresh(); @@ -239,36 +245,16 @@ void leave() /* exit under normal conditions -- INT handler */ exit(0); } -void err_leave(s) /* exit under error conditions */ -char *s; -{ - - if (no_screen_refresh == 0) { - move(LINES - 1, 0); - refresh(); - endwin(); - } - - printf("sc_usage: "); - if (s) - printf("%s ", s); - - set_enable(0); - set_pidcheck(pid, 0); - set_remove(); - - exit(1); -} - -void sigwinch() +static void +sigwinch(__unused int unused) { if (no_screen_refresh == 0) newLINES = 1; } -int -exit_usage(char *myname) { - +static int +exit_usage(char *myname) +{ fprintf(stderr, "Usage: %s [-c codefile] [-e] [-l] [-sn] pid | cmd | -E execute path\n", myname); fprintf(stderr, " -c name of codefile containing mappings for syscalls\n"); fprintf(stderr, " Default is /usr/share/misc/trace.codes\n"); @@ -282,10 +268,10 @@ exit_usage(char *myname) { exit(1); } - #define usec_to_1000ths(t) ((t) / 1000) -void print_time(char *p, unsigned int useconds, unsigned int seconds) +static void +print_time(char *p, unsigned int useconds, unsigned int seconds) { long minutes, hours; @@ -306,20 +292,13 @@ void print_time(char *p, unsigned int useconds, unsigned int seconds) } int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { char *myname = "sc_usage"; char *codefile = "/usr/share/misc/trace.codes"; char ch; char *ptr; int delay = Default_DELAY; - void screen_update(); - void sort_scalls(); - void sc_tab_init(); - void getdivisor(); - void reset_counters(); if ( geteuid() != 0 ) { printf("'sc_usage' must be run as root...\n"); @@ -330,7 +309,7 @@ main(argc, argv) fprintf(stderr, "Could not re-execute: %d\n", errno); exit(1); } - + /* get our name */ if (argc > 0) { if ((myname = rindex(argv[0], '/')) == 0) { @@ -381,7 +360,7 @@ main(argc, argv) uid_t uid, euid; gid_t gid, egid; - + ptr = strrchr(argv[optind], '/'); if (ptr) ptr++; @@ -391,7 +370,7 @@ main(argc, argv) strncpy(proc_name, ptr, sizeof(proc_name)-1); proc_name[sizeof(proc_name)-1] = '\0'; - uid= getuid(); + uid= getuid(); gid= getgid(); euid= geteuid(); egid= getegid(); @@ -470,7 +449,7 @@ main(argc, argv) if ((sort_now = 10 / delay) < 2) sort_now = 2; - get_bufinfo(&bufinfo); + get_bufinfo(&bufinfo); my_buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf)); if(my_buffer == (char *) 0) @@ -484,13 +463,12 @@ main(argc, argv) while (1) { int i; char c; - void sample_sc(); - + for (i = 0; i < (10 * delay) && newLINES == 0; i++) { if (no_screen_refresh == 0) { - if ((c = getch()) != ERR && (char)c == 'q') - leave(); + if ((c = getch()) != ERR && (char)c == 'q') + leave(0); if (c != ERR) reset_counters(); } else @@ -515,10 +493,11 @@ main(argc, argv) } } -void -print_row(struct sc_entry *se, int no_wtime) { +static void +print_row(struct sc_entry *se, int no_wtime) +{ char tbuf[256]; - int clen; + size_t clen; if (se->delta_count) sprintf(tbuf, "%-23.23s %8d(%d)", se->name, se->total_count, se->delta_count); @@ -528,14 +507,14 @@ print_row(struct sc_entry *se, int no_wtime) { memset(&tbuf[clen], ' ', 45 - clen); - print_time(&tbuf[45], (unsigned long)(se->stime_usecs), se->stime_secs); + print_time(&tbuf[45], (unsigned int)(se->stime_usecs), se->stime_secs); clen = strlen(tbuf); if (no_wtime == 0 && (se->wtime_usecs || se->wtime_secs)) { sprintf(&tbuf[clen], " "); clen += strlen(&tbuf[clen]); - print_time(&tbuf[clen], (unsigned long)(se->wtime_usecs), se->wtime_secs); + print_time(&tbuf[clen], (unsigned int)(se->wtime_usecs), se->wtime_secs); clen += strlen(&tbuf[clen]); if (se->waiting || se->delta_wtime_usecs || se->delta_wtime_secs) { @@ -543,7 +522,7 @@ print_row(struct sc_entry *se, int no_wtime) { sprintf(&tbuf[clen], "("); clen += strlen(&tbuf[clen]); - print_time(&tbuf[clen], (unsigned long)(se->delta_wtime_usecs), + print_time(&tbuf[clen], (unsigned int)(se->delta_wtime_usecs), se->delta_wtime_secs); clen += strlen(&tbuf[clen]); @@ -566,23 +545,23 @@ print_row(struct sc_entry *se, int no_wtime) { printw(tbuf); } - -void screen_update() +static void +screen_update(void) { char *p1, *p2, *p3; char tbuf[256]; - int clen; - int plen; + size_t clen; + size_t plen; int n, i, rows; long curr_time; long elapsed_secs; - int hours; - int minutes; + long hours; + long minutes; struct sc_entry *se; int output_lf; int max_rows; struct th_info *ti; - + if (no_screen_refresh == 0) { /* clear for new display */ erase(); @@ -592,7 +571,7 @@ void screen_update() sprintf(tbuf, "%-14.14s", proc_name); clen = strlen(tbuf); - + if (preempted == 1) p1 = "preemption "; else @@ -613,7 +592,7 @@ void screen_update() /* * Display the current time. * "ctime" always returns a string that looks like this: - * + * * Sun Sep 16 01:03:52 1973 * 012345678901234567890123 * 1 2 @@ -652,7 +631,7 @@ void screen_update() clen = strlen(tbuf); sprintf(&tbuf[clen], " %3ld:%02ld:%02ld\n", - (long)hours, (long)(minutes % 60), (long)(elapsed_secs % 60)); + hours, minutes % 60, elapsed_secs % 60); if (no_screen_refresh) printf("%s", tbuf); else @@ -678,7 +657,7 @@ void screen_update() sprintf(tbuf, "System Idle "); clen = strlen(tbuf); - print_time(&tbuf[clen], (unsigned long)(itime_usecs), itime_secs); + print_time(&tbuf[clen], itime_usecs, itime_secs); clen += strlen(&tbuf[clen]); if (delta_itime_usecs || delta_itime_secs) { @@ -686,7 +665,7 @@ void screen_update() sprintf(&tbuf[clen], "("); clen += strlen(&tbuf[clen]); - print_time(&tbuf[clen], (unsigned long)(delta_itime_usecs), delta_itime_secs); + print_time(&tbuf[clen], delta_itime_usecs, delta_itime_secs); clen += strlen(&tbuf[clen]); sprintf(&tbuf[clen], ")"); @@ -704,15 +683,15 @@ void screen_update() sprintf(tbuf, "System Busy "); clen = strlen(tbuf); - print_time(&tbuf[clen], (unsigned long)(otime_usecs), otime_secs); + print_time(&tbuf[clen], otime_usecs, otime_secs); clen += strlen(&tbuf[clen]); if (delta_otime_usecs || delta_otime_secs) { - sprintf(&tbuf[clen], "("); + sprintf(&tbuf[clen], "("); clen += strlen(&tbuf[clen]); - print_time(&tbuf[clen], (unsigned long)(delta_otime_usecs), delta_otime_secs); + print_time(&tbuf[clen], delta_otime_usecs, delta_otime_secs); clen += strlen(&tbuf[clen]); sprintf(&tbuf[clen], ")"); @@ -729,9 +708,9 @@ void screen_update() sprintf(tbuf, "%-14.14s Usermode ", proc_name); clen = strlen(tbuf); - print_time(&tbuf[clen], (unsigned long)(utime_usecs), utime_secs); + print_time(&tbuf[clen], utime_usecs, utime_secs); clen += strlen(&tbuf[clen]); - + sprintf(&tbuf[clen], "\n"); if (no_screen_refresh) printf("%s", tbuf); @@ -793,7 +772,7 @@ void screen_update() if (num_of_threads) { sprintf(tbuf, "\nCURRENT_TYPE LAST_PATHNAME_WAITED_FOR CUR_WAIT_TIME THRD# PRI\n"); - + if (no_screen_refresh) printf("%s", tbuf); else @@ -806,10 +785,10 @@ void screen_update() printw(tbuf); } ti = &th_state[0]; - + for (i = 0; i < num_of_threads; i++, ti++) { struct entry *te; - char *p; + char *p; uint64_t now; int secs, time_secs, time_usecs; @@ -828,14 +807,14 @@ void screen_update() sprintf(tbuf, "%-23.23s", sc_tab[te->code].name); else sprintf(tbuf, "%-23.23s", "vm_fault"); - } else + } else sprintf(tbuf, "%-23.23s", state_name[te->sc_state]); } else { te = &ti->th_entry[0]; sprintf(tbuf, "%-23.23s", state_name[te->sc_state]); } clen = strlen(tbuf); - + /* print the tail end of the pathname */ p = (char *)ti->pathname; @@ -848,7 +827,7 @@ void screen_update() clen += strlen(&tbuf[clen]); - time_usecs = (unsigned long)(((double)now - te->otime) / divisor); + time_usecs = (((double)now - te->otime) / divisor); secs = time_usecs / 1000000; time_usecs -= secs * 1000000; time_secs = secs; @@ -893,8 +872,9 @@ void screen_update() delta_otime_usecs = 0; } -void -reset_counters() { +static void +reset_counters(void) +{ int i; for (i = 0; i < (MAX_SC + msgcode_cnt) ; i++) { @@ -924,7 +904,7 @@ reset_counters() { total_faults = 0; scalls = 0; called = 0; - + utime_secs = 0; utime_usecs = 0; itime_secs = 0; @@ -937,10 +917,11 @@ reset_counters() { delta_otime_usecs = 0; } -void -sc_tab_init(char *codefile) { +static void +sc_tab_init(char *codefile) +{ int code; - int n, cnt; + int n; int msgcode_indx=0; char name[56]; FILE *fp; @@ -949,7 +930,7 @@ sc_tab_init(char *codefile) { printf("Failed to open code description file %s\n", codefile); exit(1); } - + /* Count Mach message MSG_ codes */ for (msgcode_cnt=0;;) { n = fscanf(fp, "%x%55s\n", &code, &name[0]); @@ -983,7 +964,7 @@ sc_tab_init(char *codefile) { rewind(fp); - + for (;;) { n = fscanf(fp, "%x%55s\n", &code, &name[0]); @@ -1048,8 +1029,8 @@ sc_tab_init(char *codefile) { strcpy(&faults[4].name[0], "cache_hit"); } -void -find_proc_names() +static void +find_proc_names(void) { size_t bufSize = 0; struct kinfo_proc *kp; @@ -1064,7 +1045,7 @@ find_proc_names() if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0) quit("can't allocate memory for proc buffer\n"); - + if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0) quit("trace facility failure, KERN_PROC_ALL\n"); @@ -1072,7 +1053,9 @@ find_proc_names() kp_buffer = kp; } -struct th_info *find_thread(int thread) { +static struct th_info * +find_thread(uintptr_t thread) +{ struct th_info *ti; for (ti = th_state; ti < &th_state[MAX_THREADS]; ti++) { @@ -1082,10 +1065,9 @@ struct th_info *find_thread(int thread) { return ((struct th_info *)0); } - -int -cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) { - +static int +cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) +{ if (s1->wtime_secs < s2->wtime_secs) return 0; if (s1->wtime_secs > s2->wtime_secs) @@ -1095,9 +1077,9 @@ cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) { return 1; } - -void -sort_scalls() { +static void +sort_scalls(void) +{ int i, n, k, cnt, secs; struct th_info *ti; struct sc_entry *se; @@ -1179,8 +1161,8 @@ sort_scalls() { called++; } -void -set_enable(int val) +static void +set_enable(int val) { mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; @@ -1197,8 +1179,8 @@ set_enable(int val) trace_enabled = 0; } -void -set_numbufs(int nbufs) +static void +set_numbufs(int nbufs) { mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; @@ -1211,7 +1193,7 @@ set_numbufs(int nbufs) mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; + mib[2] = KERN_KDSETUP; mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ @@ -1220,8 +1202,8 @@ set_numbufs(int nbufs) } -void -set_pidcheck(int pid, int on_off) +static void +set_pidcheck(int pid, int on_off) { kd_regtype kr; @@ -1236,7 +1218,7 @@ set_pidcheck(int pid, int on_off) mib[4] = 0; mib[5] = 0; if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) { - if (on_off == 1) { + if (on_off == 1) { printf("pid %d does not exist\n", pid); set_remove(); exit(2); @@ -1250,7 +1232,7 @@ get_bufinfo(kbufinfo_t *val) needed = sizeof (*val); mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDGETBUF; + mib[2] = KERN_KDGETBUF; mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ @@ -1259,8 +1241,8 @@ get_bufinfo(kbufinfo_t *val) } -void -set_remove() +static void +set_remove(void) { extern int errno; @@ -1284,9 +1266,10 @@ set_remove() } } -void -set_init() -{ kd_regtype kr; +static void +set_init(void) +{ + kd_regtype kr; kr.type = KDBG_RANGETYPE; kr.value1 = 0; @@ -1294,7 +1277,7 @@ set_init() needed = sizeof(kd_regtype); mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETREG; + mib[2] = KERN_KDSETREG; mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ @@ -1303,24 +1286,21 @@ set_init() mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; + mib[2] = KERN_KDSETUP; mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) quit("trace facility failure, KERN_KDSETUP\n"); - } -void -sample_sc() +static void +sample_sc(void) { kd_buf *kd; - int i, count; + int i; + size_t count; int secs; - int find_msgcode(); - - int reenable; #ifdef OLD_KDEBUG set_enable(0); @@ -1330,12 +1310,12 @@ sample_sc() needed = bufinfo.nkdbufs * sizeof(kd_buf); mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - mib[3] = 0; - mib[4] = 0; + mib[2] = KERN_KDREADTR; + mib[3] = 0; + mib[4] = 0; mib[5] = 0; - - if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) + + if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) quit("trace facility failure, KERN_KDREADTR\n"); count = needed; @@ -1360,7 +1340,8 @@ sample_sc() kd = (kd_buf *)my_buffer; for (i = 0; i < count; i++) { - int debugid, baseid, thread; + int debugid, baseid; + uintptr_t thread; int type, code; uint64_t now; struct th_info *ti, *switched_out, *switched_in; @@ -1376,7 +1357,7 @@ sample_sc() switched_in = (struct th_info *)0; now = kd[i].timestamp & KDBG_TIMESTAMP_MASK; - + baseid = debugid & 0xffff0000; if (type == vfs_lookup) { @@ -1518,14 +1499,14 @@ sample_sc() if (switched_out || switched_in) { if (switched_out) { ti = switched_out; - ti->curpri = kd[i].arg3; + ti->curpri = (int)kd[i].arg3; if (ti->depth) { te = &ti->th_entry[ti->depth-1]; if (te->sc_state == KERNEL_MODE) te->ctime += (double)now - te->stime; - te->sc_state = WAITING; + te->sc_state = WAITING; ti->vfslookup = 1; @@ -1544,14 +1525,14 @@ sample_sc() } if (switched_in) { ti = switched_in; - ti->curpri = kd[i].arg4; + ti->curpri = (int)kd[i].arg4; if (ti->depth) { te = &ti->th_entry[ti->depth-1]; if (te->sc_state == WAITING) te->wtime += (double)now - te->stime; - te->sc_state = KERNEL_MODE; + te->sc_state = KERNEL_MODE; } else { te = &ti->th_entry[0]; @@ -1561,7 +1542,7 @@ sample_sc() te->otime = (double)now; } continue; - } + } if ((ti = find_thread(thread)) == (struct th_info *)0) { for (ti = &th_state[0]; ti < &th_state[MAX_THREADS]; ti++) { if (ti->thread == 0) { @@ -1641,7 +1622,7 @@ sample_sc() ti->depth--; if (ti->depth == 0) { - /* + /* * headed back to user mode * start the time accumulation */ @@ -1658,7 +1639,7 @@ sample_sc() ti->depth--; if (ti->depth == 0) { - /* + /* * headed back to user mode * start the time accumulation */ @@ -1697,14 +1678,14 @@ quit(char *s) if (trace_enabled) set_enable(0); - /* + /* This flag is turned off when calling quit() due to a set_remove() failure. */ if (set_remove_flag) set_remove(); - if (no_screen_refresh == 0) { + if (no_screen_refresh == 0) { /* clear for new display */ erase(); move(0, 0); @@ -1719,81 +1700,73 @@ quit(char *s) exit(1); } -void getdivisor() +static void +getdivisor(void) { - mach_timebase_info_data_t info; - - (void) mach_timebase_info (&info); + mach_timebase_info_data_t info; - divisor = ( (double)info.denom / (double)info.numer) * 1000; + (void) mach_timebase_info (&info); + divisor = ( (double)info.denom / (double)info.numer) * 1000; } - int -argtopid(str) - char *str; +argtopid(char *str) { - char *cp; - int ret; + char *cp; + int ret; int i; if (!kp_buffer) - find_proc_names(); - - ret = (int)strtol(str, &cp, 10); - if (cp == str || *cp) { - /* Assume this is a command string and find first matching pid */ - for (i=0; i < kp_nentries; i++) { - if(kp_buffer[i].kp_proc.p_stat == 0) - continue; - else { - if(!strcmp(str, kp_buffer[i].kp_proc.p_comm)) - { - strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1); - proc_name[sizeof(proc_name)-1] = '\0'; - return(kp_buffer[i].kp_proc.p_pid); - } - } + find_proc_names(); + + ret = (int)strtol(str, &cp, 10); + if (cp == str || *cp) { + /* Assume this is a command string and find first matching pid */ + for (i=0; i < kp_nentries; i++) { + if (kp_buffer[i].kp_proc.p_stat == 0) + continue; + else { + if (!strcmp(str, kp_buffer[i].kp_proc.p_comm)) { + strncpy(proc_name, + kp_buffer[i].kp_proc.p_comm, + sizeof(proc_name)-1); + proc_name[sizeof(proc_name)-1] = '\0'; + return (kp_buffer[i].kp_proc.p_pid); + } + } } - } - else - { - for (i=0; i < kp_nentries; i++) - { - if(kp_buffer[i].kp_proc.p_stat == 0) - continue; - else if (kp_buffer[i].kp_proc.p_pid == ret) { - strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1); - proc_name[sizeof(proc_name)-1] = '\0'; - return(kp_buffer[i].kp_proc.p_pid); + } else { + for (i=0; i < kp_nentries; i++) { + if (kp_buffer[i].kp_proc.p_stat == 0) + continue; + else if (kp_buffer[i].kp_proc.p_pid == ret) { + strncpy(proc_name, + kp_buffer[i].kp_proc.p_comm, + sizeof(proc_name)-1); + proc_name[sizeof(proc_name)-1] = '\0'; + return (kp_buffer[i].kp_proc.p_pid); + } } - } - } - return(-1); + } + return (-1); } - /* Returns index into sc_tab for a mach msg entry */ -int +static int find_msgcode(int debugid) { + int indx; - int indx; - - for (indx=0; indx< msgcode_cnt; indx++) - { - if (msgcode_tab[indx] == ((debugid & 0x00ffffff) >>2)) - return (MAX_SC+indx); - } - return (0); + for (indx=0; indx< msgcode_cnt; indx++) { + if (msgcode_tab[indx] == ((debugid & 0x00ffffff) >>2)) + return (MAX_SC+indx); + } + return (0); } int -argtoi(flag, req, str, base) - int flag; - char *req, *str; - int base; +argtoi(int flag, char *req, char *str, int base) { char *cp; int ret; @@ -1803,4 +1776,3 @@ argtoi(flag, req, str, base) errx(EINVAL, "-%c flag requires a %s", flag, req); return (ret); } - diff --git a/shutdown.tproj/pathnames.h b/shutdown.tproj/pathnames.h index 2bb5f01..7e024e0 100644 --- a/shutdown.tproj/pathnames.h +++ b/shutdown.tproj/pathnames.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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 diff --git a/shutdown.tproj/shutdown.c b/shutdown.tproj/shutdown.c index 6e4aebe..d6e60d6 100644 --- a/shutdown.tproj/shutdown.c +++ b/shutdown.tproj/shutdown.c @@ -114,7 +114,8 @@ struct interval { static time_t offset, shuttime; #ifdef __APPLE__ -static int dohalt, doreboot, doups, killflg, mbuflen, oflag; +static int dohalt, doreboot, doups, killflg, oflag; +static size_t mbuflen; #else static int dohalt, dopower, doreboot, killflg, mbuflen, oflag; #endif @@ -135,7 +136,7 @@ void getoffset(char *); void loop(void); void nolog(void); void timeout(int); -void timewarn(int); +void timewarn(time_t); void usage(const char *); #ifdef __APPLE__ int audit_shutdown(int); @@ -149,7 +150,8 @@ main(int argc, char **argv) { char *p, *endp; struct passwd *pw; - int arglen, ch, len, readstdin; + size_t arglen; + int ch, len, readstdin; #ifndef DEBUG if (geteuid()) @@ -219,7 +221,7 @@ main(int argc, char **argv) if (!(dohalt || doreboot || dosleep || killflg)) usage("-h, -r, -s, or -k is required"); - + if (doups && !dohalt) usage("-u requires -h"); #endif /* !__APPLE__ */ @@ -244,7 +246,7 @@ main(int argc, char **argv) p = mbuf; endp = mbuf + sizeof(mbuf) - 2; for (;;) { - if (!fgets(p, endp - p + 1, stdin)) + if (!fgets(p, (int)(endp - p + 1), stdin)) break; for (; *p && p < endp; ++p); if (p == endp) { @@ -298,7 +300,7 @@ main(int argc, char **argv) } void -loop() +loop(void) { struct interval *tp; u_int sltime; @@ -320,8 +322,8 @@ loop() * Warn now, if going to sleep more than a fifth of * the next wait time. */ - if ((sltime = offset - tp->timeleft)) { - if (sltime > (u_int)(tp->timetowait / 5)) + if ((sltime = (u_int)(offset - tp->timeleft))) { + if (sltime > (tp->timetowait / 5)) timewarn(offset); (void)sleep(sltime); } @@ -351,7 +353,7 @@ static const char *restricted_environ[] = { }; void -timewarn(int timeleft) +timewarn(time_t timeleft) { static int first; static char hostname[MAXHOSTNAMELEN + 1]; @@ -380,7 +382,7 @@ timewarn(int timeleft) (void)fprintf(pf, "System going down at %5.5s\n\n", ctime(&shuttime) + 11); else if (timeleft > 59) - (void)fprintf(pf, "System going down in %d minute%s\n\n", + (void)fprintf(pf, "System going down in %ld minute%s\n\n", timeleft / 60, (timeleft > 60) ? "s" : ""); else if (timeleft) (void)fprintf(pf, "System going down in 30 seconds\n\n"); @@ -427,7 +429,7 @@ die_you_gravy_sucking_pig_dog() syslog(LOG_NOTICE, "%s%s by %s: %s", #ifndef __APPLE__ - doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" : + doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" : #else doreboot ? "reboot" : dohalt ? "halt" : dosleep ? "sleep" : #endif @@ -475,7 +477,7 @@ die_you_gravy_sucking_pig_dog() } else { int howto = 0; -#if defined(__APPLE__) +#if defined(__APPLE__) { struct utmpx utx; bzero(&utx, sizeof(utx)); @@ -495,7 +497,7 @@ die_you_gravy_sucking_pig_dog() if (nosync) howto |= RB_NOSYNC; // launchd(8) handles reboot. This call returns NULL on success. - if (reboot2(howto)) { + if (reboot3(howto)) { syslog(LOG_ERR, "shutdown: launchd reboot failed."); } } @@ -507,7 +509,7 @@ die_you_gravy_sucking_pig_dog() SIGTERM); /* single-user */ } else { if (doreboot) { - execle(_PATH_REBOOT, "reboot", "-l", nosync, + execle(_PATH_REBOOT, "reboot", "-l", nosync, (char *)NULL, empty_environ); syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT); @@ -620,7 +622,7 @@ getoffset(char *timearg) #define NOMSG "\n\nNO LOGINS: System going down at " void -nolog() +nolog(void) { int logfd; char *ct; @@ -650,7 +652,7 @@ finish(int signo __unused) } void -badtime() +badtime(void) { errx(1, "bad time format"); } @@ -676,8 +678,9 @@ usage(const char *cp) * header * subject * return - */ -int audit_shutdown(int exitstatus) + */ +int +audit_shutdown(int exitstatus) { int aufd; token_t *tok; @@ -693,7 +696,7 @@ int audit_shutdown(int exitstatus) if((aufd = au_open()) == -1) { fprintf(stderr, "shutdown: Audit Error: au_open() failed\n"); - exit(1); + exit(1); } /* The subject that performed the operation */ @@ -725,7 +728,7 @@ int audit_shutdown(int exitstatus) * contact kextd to lock for reboot */ int -reserve_reboot() +reserve_reboot(void) { int rval = ELAST + 1; kern_return_t macherr = KERN_FAILURE; @@ -776,4 +779,3 @@ finish: return rval; } #endif /* __APPLE__ */ - diff --git a/sysctl.tproj/sysctl.c b/sysctl.tproj/sysctl.c index 7e69787..30b066b 100644 --- a/sysctl.tproj/sysctl.c +++ b/sysctl.tproj/sysctl.c @@ -38,7 +38,7 @@ __unused static const char copyright[] = #if 0 static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; #endif -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ @@ -513,7 +513,7 @@ static int S_xswusage(int l2, void *p) { struct xsw_usage *xsu = (struct xsw_usage *)p; - + if (l2 != sizeof(*xsu)) { warnx("S_xswusage %d != %ld", l2, sizeof(*xsu)); return (1); @@ -693,7 +693,7 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) } } #endif - + return (0); } @@ -825,7 +825,7 @@ show_var(int *oid, int nlen) return (1); } #endif - + switch (ctltype) { case CTLTYPE_STRING: if (!nflag) diff --git a/system_cmds.xcodeproj/project.pbxproj b/system_cmds.xcodeproj/project.pbxproj index 98c424d..de9e5df 100644 --- a/system_cmds.xcodeproj/project.pbxproj +++ b/system_cmds.xcodeproj/project.pbxproj @@ -7,6 +7,62 @@ objects = { /* Begin PBXAggregateTarget section */ + 1812F18C1C8F923900F3DC9E /* All_Bridge */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 1812F1EF1C8F923900F3DC9E /* Build configuration list for PBXAggregateTarget "All_Bridge" */; + buildPhases = ( + 1812F1ED1C8F923900F3DC9E /* CopyFiles */, + ); + dependencies = ( + 1812F18D1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F18F1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1911C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1931C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1991C8F923900F3DC9E /* PBXTargetDependency */, + 1812F19B1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F19D1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F19F1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1A11C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1A31C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1A51C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1A71C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1A91C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1AB1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1AD1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1AF1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1B11C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1B31C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1B51C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1B71C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1B91C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1BB1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1BD1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1BF1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1C11C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1C31C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1C51C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1C71C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1C91C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1CB1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1CD1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1CF1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1D11C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1D31C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1D51C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1D71C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1D91C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1DB1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1DD1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1DF1C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1E11C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1E31C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1E51C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1E71C8F923900F3DC9E /* PBXTargetDependency */, + 1812F1EB1C8F923900F3DC9E /* PBXTargetDependency */, + ); + name = All_Bridge; + productName = All_iOS; + }; BA4FD2FE1372FE4E0025925C /* All_MacOSX */ = { isa = PBXAggregateTarget; buildConfigurationList = BA4FD2FF1372FE4E0025925C /* Build configuration list for PBXAggregateTarget "All_MacOSX" */; @@ -14,10 +70,10 @@ C9D64CD21B91066B00CFA43B /* CopyFiles */, ); dependencies = ( + C21481471C1A1447003BCA63 /* PBXTargetDependency */, + 78DE9DED1B5048D400FE6DF5 /* PBXTargetDependency */, 97999D351AE84D3A00E8B10F /* PBXTargetDependency */, 08DC48921A12C6FA008AAF38 /* PBXTargetDependency */, - 18597F1A18CBC3B000531A50 /* PBXTargetDependency */, - 1865518B18CA7151003B92A7 /* PBXTargetDependency */, 550C19F11804D2B7001DA380 /* PBXTargetDependency */, ADA9007E1767A31300161ADF /* PBXTargetDependency */, C625B29116D6F38700168EF7 /* PBXTargetDependency */, @@ -38,9 +94,7 @@ BA9BF4B7139682710018C7BB /* PBXTargetDependency */, BA91CE6A137F43A500AE5160 /* PBXTargetDependency */, BAE58A54137D69FB0049DD3B /* PBXTargetDependency */, - BAE58A42137A59300049DD3B /* PBXTargetDependency */, BAE58A2E1379A1260049DD3B /* PBXTargetDependency */, - BAE58A301379A1260049DD3B /* PBXTargetDependency */, BAE589FE137905740049DD3B /* PBXTargetDependency */, BAE58A00137905740049DD3B /* PBXTargetDependency */, BAE58A02137905740049DD3B /* PBXTargetDependency */, @@ -50,7 +104,6 @@ BACC1D681377B8DC007728F4 /* PBXTargetDependency */, BACC1D6A1377B8DC007728F4 /* PBXTargetDependency */, BACC1D6C1377B8DC007728F4 /* PBXTargetDependency */, - BACC1D3C1377B5D9007728F4 /* PBXTargetDependency */, BACC1D001377B3A4007728F4 /* PBXTargetDependency */, BA4B7A981376600200003422 /* PBXTargetDependency */, BA4B7A7C13765DC600003422 /* PBXTargetDependency */, @@ -60,7 +113,6 @@ BA4B7A0C1373BA8D00003422 /* PBXTargetDependency */, BA4B79F81373B06B00003422 /* PBXTargetDependency */, BA4B79DB1373A9CE00003422 /* PBXTargetDependency */, - BA4B79DD1373A9CE00003422 /* PBXTargetDependency */, BA9B76A81373A2CF001BB39F /* PBXTargetDependency */, BA9B76AA1373A2CF001BB39F /* PBXTargetDependency */, BA9B76AC1373A2CF001BB39F /* PBXTargetDependency */, @@ -74,6 +126,7 @@ BA4FD3121373001C0025925C /* PBXTargetDependency */, BA4FD329137301370025925C /* PBXTargetDependency */, BA4FD337137306260025925C /* PBXTargetDependency */, + 8EC3916E1C973440001E28E6 /* PBXTargetDependency */, ); name = All_MacOSX; productName = All_MacOSX; @@ -171,10 +224,10 @@ C9D64CD01B91064700CFA43B /* CopyFiles */, ); dependencies = ( + C21481491C1A14AD003BCA63 /* PBXTargetDependency */, + 78DE9DFA1B504D1200FE6DF5 /* PBXTargetDependency */, 97999D371AE84D4100E8B10F /* PBXTargetDependency */, 08DC48901A12C6F0008AAF38 /* PBXTargetDependency */, - 18597F1C18CBC3B900531A50 /* PBXTargetDependency */, - 186551D018CA8154003B92A7 /* PBXTargetDependency */, 550C19EF1804D2AD001DA380 /* PBXTargetDependency */, ADA900801767A31900161ADF /* PBXTargetDependency */, C625B29316D6F39000168EF7 /* PBXTargetDependency */, @@ -192,9 +245,7 @@ BA9BF4BB139682880018C7BB /* PBXTargetDependency */, BA9BF4BD139682880018C7BB /* PBXTargetDependency */, BAE58A56137D6A050049DD3B /* PBXTargetDependency */, - BAE58A44137A59390049DD3B /* PBXTargetDependency */, BAE58A321379A1300049DD3B /* PBXTargetDependency */, - BAE58A341379A1300049DD3B /* PBXTargetDependency */, BAE58A041379057F0049DD3B /* PBXTargetDependency */, BAE58A061379057F0049DD3B /* PBXTargetDependency */, BAE58A081379057F0049DD3B /* PBXTargetDependency */, @@ -209,7 +260,6 @@ BACC1D201377B58A007728F4 /* PBXTargetDependency */, BACC1D221377B58A007728F4 /* PBXTargetDependency */, BACC1D241377B58A007728F4 /* PBXTargetDependency */, - BACC1D261377B58A007728F4 /* PBXTargetDependency */, BACC1D281377B58A007728F4 /* PBXTargetDependency */, BACC1D2A1377B58A007728F4 /* PBXTargetDependency */, BACC1D2C1377B58A007728F4 /* PBXTargetDependency */, @@ -218,7 +268,6 @@ BACC1D321377B58A007728F4 /* PBXTargetDependency */, BACC1D341377B58A007728F4 /* PBXTargetDependency */, BACC1D361377B58A007728F4 /* PBXTargetDependency */, - BACC1D381377B58A007728F4 /* PBXTargetDependency */, BACC1D3A1377B58A007728F4 /* PBXTargetDependency */, ); name = All_iOS; @@ -254,102 +303,7 @@ 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 */; }; - 1845E41718EB95810010F451 /* TraceFile.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1845E41518EB95810010F451 /* TraceFile.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18597EC918CBC2A300531A50 /* kdprof.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18597EC818CBC2A300531A50 /* kdprof.1 */; }; - 18597EE918CBC35700531A50 /* CollectAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ECE18CBC35700531A50 /* CollectAction.cpp */; }; - 18597EEA18CBC35700531A50 /* DisableAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ED018CBC35700531A50 /* DisableAction.cpp */; }; - 18597EEB18CBC35700531A50 /* EnableAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ED218CBC35700531A50 /* EnableAction.cpp */; }; - 18597EEC18CBC35700531A50 /* EventPrinting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ED418CBC35700531A50 /* EventPrinting.cpp */; }; - 18597EED18CBC35700531A50 /* Globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ED718CBC35700531A50 /* Globals.cpp */; }; - 18597EEE18CBC35700531A50 /* InitializeAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597ED918CBC35700531A50 /* InitializeAction.cpp */; }; - 18597EEF18CBC35700531A50 /* kdprof.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EDA18CBC35700531A50 /* kdprof.cpp */; }; - 18597EF018CBC35700531A50 /* NoWrapAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EDC18CBC35700531A50 /* NoWrapAction.cpp */; }; - 18597EF118CBC35700531A50 /* PrintStateAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EDE18CBC35700531A50 /* PrintStateAction.cpp */; }; - 18597EF218CBC35700531A50 /* RemoveAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EE018CBC35700531A50 /* RemoveAction.cpp */; }; - 18597EF318CBC35700531A50 /* SaveTraceAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EE218CBC35700531A50 /* SaveTraceAction.cpp */; }; - 18597EF418CBC35700531A50 /* SleepAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EE418CBC35700531A50 /* SleepAction.cpp */; }; - 18597EF518CBC35700531A50 /* SummaryPrinting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EE618CBC35700531A50 /* SummaryPrinting.cpp */; }; - 18597EF618CBC35700531A50 /* TraceFileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18597EE818CBC35700531A50 /* TraceFileAction.cpp */; }; - 18597F1F18CBC3D000531A50 /* libCPPUtil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865513618CA6F41003B92A7 /* libCPPUtil.a */; }; - 185B9772191022B200FCB84C /* VoucherContentSysctl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 185B9771191022B200FCB84C /* VoucherContentSysctl.cpp */; }; - 185B97751910475500FCB84C /* WriteTraceFileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 185B97731910475500FCB84C /* WriteTraceFileAction.cpp */; }; - 1865515918CA70B5003B92A7 /* CPPUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 1865513A18CA70B5003B92A7 /* CPPUtil.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865515A18CA70B5003B92A7 /* UtilAbsInterval.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865513B18CA70B5003B92A7 /* UtilAbsInterval.cpp */; }; - 1865515B18CA70B5003B92A7 /* UtilAbsInterval.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865513C18CA70B5003B92A7 /* UtilAbsInterval.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865515C18CA70B5003B92A7 /* UtilAbsTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865513D18CA70B5003B92A7 /* UtilAbsTime.cpp */; }; - 1865515D18CA70B5003B92A7 /* UtilAbsTime.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865513E18CA70B5003B92A7 /* UtilAbsTime.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865515E18CA70B5003B92A7 /* UtilAssert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865513F18CA70B5003B92A7 /* UtilAssert.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865515F18CA70B5003B92A7 /* UtilBase.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514018CA70B5003B92A7 /* UtilBase.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516018CA70B5003B92A7 /* UtilException.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514118CA70B5003B92A7 /* UtilException.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516118CA70B5003B92A7 /* UtilFileDescriptor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514218CA70B5003B92A7 /* UtilFileDescriptor.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516218CA70B5003B92A7 /* UtilLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865514318CA70B5003B92A7 /* UtilLog.cpp */; }; - 1865516318CA70B5003B92A7 /* UtilLog.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514418CA70B5003B92A7 /* UtilLog.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516418CA70B5003B92A7 /* UtilMakeUnique.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514518CA70B5003B92A7 /* UtilMakeUnique.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516518CA70B5003B92A7 /* UtilMappedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865514618CA70B5003B92A7 /* UtilMappedFile.cpp */; }; - 1865516618CA70B5003B92A7 /* UtilMappedFile.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514718CA70B5003B92A7 /* UtilMappedFile.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516718CA70B5003B92A7 /* UtilMemoryBuffer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514818CA70B5003B92A7 /* UtilMemoryBuffer.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516818CA70B5003B92A7 /* UtilNanoInterval.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514918CA70B5003B92A7 /* UtilNanoInterval.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516918CA70B5003B92A7 /* UtilNanoTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865514A18CA70B5003B92A7 /* UtilNanoTime.cpp */; }; - 1865516A18CA70B5003B92A7 /* UtilNanoTime.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514B18CA70B5003B92A7 /* UtilNanoTime.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516B18CA70B5003B92A7 /* UtilPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865514C18CA70B5003B92A7 /* UtilPath.cpp */; }; - 1865516C18CA70B5003B92A7 /* UtilPath.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514D18CA70B5003B92A7 /* UtilPath.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516D18CA70B5003B92A7 /* UtilPrettyPrinting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865514E18CA70B5003B92A7 /* UtilPrettyPrinting.cpp */; }; - 1865516E18CA70B5003B92A7 /* UtilPrettyPrinting.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865514F18CA70B5003B92A7 /* UtilPrettyPrinting.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865516F18CA70B5003B92A7 /* UtilString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865515018CA70B5003B92A7 /* UtilString.cpp */; }; - 1865517018CA70B5003B92A7 /* UtilString.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515118CA70B5003B92A7 /* UtilString.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865517118CA70B5003B92A7 /* UtilTerminalColor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865515218CA70B5003B92A7 /* UtilTerminalColor.cpp */; }; - 1865517218CA70B5003B92A7 /* UtilTerminalColor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515318CA70B5003B92A7 /* UtilTerminalColor.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865517318CA70B5003B92A7 /* UtilTime.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515418CA70B5003B92A7 /* UtilTime.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865517418CA70B5003B92A7 /* UtilTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865515518CA70B5003B92A7 /* UtilTimer.cpp */; }; - 1865517518CA70B5003B92A7 /* UtilTimer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515618CA70B5003B92A7 /* UtilTimer.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865517618CA70B5003B92A7 /* UtilTRange.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515718CA70B5003B92A7 /* UtilTRange.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865517718CA70B5003B92A7 /* UtilTRangeValue.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1865515818CA70B5003B92A7 /* UtilTRangeValue.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 1865518118CA7104003B92A7 /* msa.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1865518018CA7104003B92A7 /* msa.1 */; }; - 1865518718CA7130003B92A7 /* libCPPUtil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865513618CA6F41003B92A7 /* libCPPUtil.a */; }; - 1865519B18CA72F7003B92A7 /* Globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865519118CA72F7003B92A7 /* Globals.cpp */; }; - 1865519C18CA72F7003B92A7 /* LiveTraceAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865519418CA72F7003B92A7 /* LiveTraceAction.cpp */; }; - 1865519D18CA72F7003B92A7 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865519618CA72F7003B92A7 /* main.cpp */; }; - 1865519E18CA72F7003B92A7 /* Printing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865519718CA72F7003B92A7 /* Printing.cpp */; }; - 1865519F18CA72F7003B92A7 /* ReadTraceFileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1865519918CA72F7003B92A7 /* ReadTraceFileAction.cpp */; }; - 188959FD1958D287004576E8 /* TaskRequestedPolicy.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 188959FC1958D287004576E8 /* TaskRequestedPolicy.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872A918EA128B00F86DD9 /* CPUActivity.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728718EA128B00F86DD9 /* CPUActivity.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872AA18EA128B00F86DD9 /* CPUSummary.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728818EA128B00F86DD9 /* CPUSummary.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872AB18EA128B00F86DD9 /* IOActivity.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728918EA128B00F86DD9 /* IOActivity.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872AC18EA128B00F86DD9 /* KDBG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18C8728A18EA128B00F86DD9 /* KDBG.cpp */; }; - 18C872AD18EA128B00F86DD9 /* KDBG.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728B18EA128B00F86DD9 /* KDBG.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872AE18EA128B00F86DD9 /* KDCPUMapEntry.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728C18EA128B00F86DD9 /* KDCPUMapEntry.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872AF18EA128B00F86DD9 /* KDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728D18EA128B00F86DD9 /* KDebug.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B018EA128B00F86DD9 /* KDEvent.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728E18EA128B00F86DD9 /* KDEvent.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B118EA128B00F86DD9 /* KDState.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8728F18EA128B00F86DD9 /* KDState.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B218EA128B00F86DD9 /* KDThreadMapEntry.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729018EA128B00F86DD9 /* KDThreadMapEntry.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B318EA128B00F86DD9 /* Kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18C8729118EA128B00F86DD9 /* Kernel.cpp */; }; - 18C872B418EA128B00F86DD9 /* Kernel.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729218EA128B00F86DD9 /* Kernel.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B518EA128B00F86DD9 /* Machine.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729318EA128B00F86DD9 /* Machine.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B618EA128B00F86DD9 /* Machine.impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729418EA128B00F86DD9 /* Machine.impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B718EA128B00F86DD9 /* Machine.mutable-impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729518EA128B00F86DD9 /* Machine.mutable-impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B818EA128B00F86DD9 /* MachineCPU.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729618EA128B00F86DD9 /* MachineCPU.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872B918EA128B00F86DD9 /* MachineCPU.impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729718EA128B00F86DD9 /* MachineCPU.impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BA18EA128B00F86DD9 /* MachineCPU.mutable-impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729818EA128B00F86DD9 /* MachineCPU.mutable-impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BB18EA128B00F86DD9 /* MachineMachMsg.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729918EA128B00F86DD9 /* MachineMachMsg.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BC18EA128B00F86DD9 /* MachineProcess.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729A18EA128B00F86DD9 /* MachineProcess.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BD18EA128B00F86DD9 /* MachineProcess.impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729B18EA128B00F86DD9 /* MachineProcess.impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BE18EA128B00F86DD9 /* MachineProcess.mutable-impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729C18EA128B00F86DD9 /* MachineProcess.mutable-impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872BF18EA128B00F86DD9 /* MachineThread.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729D18EA128B00F86DD9 /* MachineThread.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C018EA128B00F86DD9 /* MachineThread.impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729E18EA128B00F86DD9 /* MachineThread.impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C118EA128B00F86DD9 /* MachineThread.mutable-impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C8729F18EA128B00F86DD9 /* MachineThread.mutable-impl.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C218EA128B00F86DD9 /* MachineVoucher.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A018EA128B00F86DD9 /* MachineVoucher.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C318EA128B00F86DD9 /* MetaTypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A118EA128B00F86DD9 /* MetaTypes.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C418EA128B00F86DD9 /* NurseryMachMsg.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A218EA128B00F86DD9 /* NurseryMachMsg.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C518EA128B00F86DD9 /* ProcessSummary.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A318EA128B00F86DD9 /* ProcessSummary.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C618EA128B00F86DD9 /* ThreadSummary.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A418EA128B00F86DD9 /* ThreadSummary.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C718EA128B00F86DD9 /* TraceCodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18C872A518EA128B00F86DD9 /* TraceCodes.cpp */; }; - 18C872C818EA128B00F86DD9 /* TraceCodes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A618EA128B00F86DD9 /* TraceCodes.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872C918EA128B00F86DD9 /* TraceDataHeader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A718EA128B00F86DD9 /* TraceDataHeader.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872CA18EA128B00F86DD9 /* VoucherInterval.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18C872A818EA128B00F86DD9 /* VoucherInterval.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - 18C872CB18EA1A4600F86DD9 /* libKDBG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C8727F18EA114F00F86DD9 /* libKDBG.a */; }; - 18C872CC18EA1A5000F86DD9 /* libKDBG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C8727F18EA114F00F86DD9 /* libKDBG.a */; }; - 18D8B66619537115008847DF /* TaskEffectivePolicy.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 18D8B66519535B92008847DF /* TaskEffectivePolicy.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; + 1812F1EE1C8F923900F3DC9E /* system_cmds.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C9D64CCF1B91063200CFA43B /* system_cmds.plist */; }; 550C19E61804D226001DA380 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A091373BA4600003422 /* libutil.dylib */; }; 550C19EC1804D281001DA380 /* iosim.c in Sources */ = {isa = PBXBuildFile; fileRef = 550C19E11804C55E001DA380 /* iosim.c */; }; 550C19ED1804D295001DA380 /* iosim.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 550C19E01804C55E001DA380 /* iosim.1 */; }; @@ -358,11 +312,15 @@ 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 */; }; + 78DE9DFE1B504D7F00FE6DF5 /* wait4path.c in Sources */ = {isa = PBXBuildFile; fileRef = 78DE9DFC1B504D7F00FE6DF5 /* wait4path.c */; }; + 78DE9E001B504DE500FE6DF5 /* wait4path.version in Sources */ = {isa = PBXBuildFile; fileRef = 78DE9DFD1B504D7F00FE6DF5 /* wait4path.version */; }; + 78DE9EE61B505F1800FE6DF5 /* wait4path.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 78DE9EE51B505EBF00FE6DF5 /* wait4path.1 */; }; + 8EC391681C973400001E28E6 /* proc_uuid_policy.c in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8EC391671C973400001E28E6 /* proc_uuid_policy.c */; }; + 8EC391691C973405001E28E6 /* proc_uuid_policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 8EC391671C973400001E28E6 /* proc_uuid_policy.c */; }; + 8EC3916B1C97341E001E28E6 /* proc_uuid_policy.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8EC3916A1C97341E001E28E6 /* proc_uuid_policy.1 */; }; + 8EC3916C1C973429001E28E6 /* proc_uuid_policy.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8EC3916A1C97341E001E28E6 /* proc_uuid_policy.1 */; }; 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 */; }; @@ -375,12 +333,7 @@ BA28FB891396DA8A004986CB /* private in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA28FB851396DA01004986CB /* private */; }; BA4B79CF1373A74B00003422 /* dmesg.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2201372FAFA0025925C /* dmesg.8 */; }; BA4B79D01373A74F00003422 /* dmesg.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2211372FAFA0025925C /* dmesg.c */; }; - BA4B79D81373A99200003422 /* backing_store_alerts.defs in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2281372FAFA0025925C /* backing_store_alerts.defs */; settings = {ATTRIBUTES = (Server, ); }; }; - BA4B79D91373A99600003422 /* backing_store_triggers.defs in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2291372FAFA0025925C /* backing_store_triggers.defs */; }; BA4B79EE1373AFFA00003422 /* dynamic_pager.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD22D1372FAFA0025925C /* dynamic_pager.c */; }; - BA4B79EF1373B00300003422 /* backing_store_alerts.defs in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2281372FAFA0025925C /* backing_store_alerts.defs */; }; - BA4B79F01373B00300003422 /* backing_store_triggers.defs in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2291372FAFA0025925C /* backing_store_triggers.defs */; settings = {ATTRIBUTES = (Server, ); }; }; - BA4B79F11373B00300003422 /* default_pager_alerts.defs in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD22B1372FAFA0025925C /* default_pager_alerts.defs */; settings = {ATTRIBUTES = (Server, ); }; }; BA4B79F21373B01100003422 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA9B766D13739D27001BB39F /* CoreFoundation.framework */; }; BA4B79F41373B01C00003422 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B79F31373B01B00003422 /* SystemConfiguration.framework */; }; BA4B79F51373B03300003422 /* dynamic_pager.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD22C1372FAFA0025925C /* dynamic_pager.8 */; }; @@ -493,8 +446,6 @@ BACC1CFA1377B28C007728F4 /* login_audit.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD25F1372FAFA0025925C /* login_audit.c */; }; BACC1CFB1377B2A8007728F4 /* login.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD25C1372FAFA0025925C /* login.1 */; }; BACC1CFE1377B2D8007728F4 /* login.term in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2621372FAFA0025925C /* login.term */; }; - BACC1D0B1377B413007728F4 /* makekey.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2681372FAFA0025925C /* makekey.c */; }; - BACC1D0C1377B41B007728F4 /* makekey.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2671372FAFA0025925C /* makekey.8 */; }; BACC1D171377B4A9007728F4 /* mean.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD26B1372FAFA0025925C /* mean.c */; }; BACC1D471377B71D007728F4 /* mkfile.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD26F1372FAFA0025925C /* mkfile.c */; }; BACC1D481377B723007728F4 /* mkfile.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD26E1372FAFA0025925C /* mkfile.8 */; }; @@ -525,29 +476,51 @@ BAE58A1513799F9B0049DD3B /* pdb.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD29B1372FAFA0025925C /* pdb.c */; }; BAE58A1613799F9F0049DD3B /* usrdb.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD29D1372FAFA0025925C /* usrdb.c */; }; BAE58A1713799FA80049DD3B /* sa.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD29C1372FAFA0025925C /* sa.8 */; }; - BAE58A271379A0590049DD3B /* sadc.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2A51372FAFA0025925C /* sadc.c */; }; - BAE58A281379A0670049DD3B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA9B766D13739D27001BB39F /* CoreFoundation.framework */; }; - BAE58A291379A06B0049DD3B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A7613765D7700003422 /* IOKit.framework */; }; - BAE58A2A1379A07E0049DD3B /* sa1.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2A01372FAFA0025925C /* sa1.8 */; }; - BAE58A2B1379A0820049DD3B /* sa2.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2A21372FAFA0025925C /* sa2.8 */; }; - BAE58A2C1379A0860049DD3B /* sadc.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2A41372FAFA0025925C /* sadc.8 */; }; - BAE58A3F137A59140049DD3B /* sar.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2AA1372FAFA0025925C /* sar.c */; }; - BAE58A40137A59200049DD3B /* sar.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2A91372FAFA0025925C /* sar.1 */; }; BAE58A49137D69A60049DD3B /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A091373BA4600003422 /* libutil.dylib */; }; BAE58A50137D69DA0049DD3B /* sc_usage.c in Sources */ = {isa = PBXBuildFile; fileRef = BA4FD2AF1372FAFA0025925C /* sc_usage.c */; }; BAE58A51137D69E30049DD3B /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A9313765F8B00003422 /* libncurses.dylib */; }; BAE58A52137D69ED0049DD3B /* sc_usage.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA4FD2AE1372FAFA0025925C /* sc_usage.1 */; }; + C20138731C1A17D0008EE53F /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A091373BA4600003422 /* libutil.dylib */; }; + C21481381C1A1213003BCA63 /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = C21481201C1A11E7003BCA63 /* vm.c */; }; + C21481391C1A1216003BCA63 /* vanilla.c in Sources */ = {isa = PBXBuildFile; fileRef = C214811E1C1A11E7003BCA63 /* vanilla.c */; }; + C214813A1C1A1219003BCA63 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = C214811C1C1A11E7003BCA63 /* utils.c */; }; + C214813B1C1A122B003BCA63 /* corefile.c in Sources */ = {isa = PBXBuildFile; fileRef = C214810D1C1A11E6003BCA63 /* corefile.c */; }; + C214813C1C1A122B003BCA63 /* dyld_shared_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = C214810F1C1A11E6003BCA63 /* dyld_shared_cache.c */; }; + C214813D1C1A122B003BCA63 /* dyld.c in Sources */ = {isa = PBXBuildFile; fileRef = C21481111C1A11E6003BCA63 /* dyld.c */; }; + C214813E1C1A122B003BCA63 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = C21481151C1A11E6003BCA63 /* main.c */; }; + C214813F1C1A122B003BCA63 /* sparse.c in Sources */ = {isa = PBXBuildFile; fileRef = C21481181C1A11E6003BCA63 /* sparse.c */; }; + C21481401C1A122B003BCA63 /* threads.c in Sources */ = {isa = PBXBuildFile; fileRef = C214811A1C1A11E7003BCA63 /* threads.c */; }; + C21481451C1A131D003BCA63 /* gcore.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C21481131C1A11E6003BCA63 /* gcore.1 */; }; + C248DBB01C1A1D0500F6E9AF /* libcompression.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C248DBAF1C1A1D0500F6E9AF /* libcompression.dylib */; }; C625B28B16D6F27E00168EF7 /* taskpolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = C625B28A16D6F27E00168EF7 /* taskpolicy.c */; }; C625B28D16D6F27E00168EF7 /* taskpolicy.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C625B28C16D6F27E00168EF7 /* taskpolicy.8 */; }; C65BF57A144BD7C5009028A3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA9B766D13739D27001BB39F /* CoreFoundation.framework */; }; C96F50B215BDCEC3008682F7 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A091373BA4600003422 /* libutil.dylib */; }; C96F50BD15BDFEFB008682F7 /* lsmp.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C96F50AC15BDCBF0008682F7 /* lsmp.1 */; }; C96F50BE15BDFF03008682F7 /* lsmp.c in Sources */ = {isa = PBXBuildFile; fileRef = C96F50AD15BDCE8E008682F7 /* lsmp.c */; }; + C97199F21C5206DE006D9758 /* libktrace.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C97199F11C5206DE006D9758 /* libktrace.dylib */; }; C9779F6E159A2A0C009436FD /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA4B7A091373BA4600003422 /* libutil.dylib */; }; C9D64CD11B91065D00CFA43B /* system_cmds.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C9D64CCF1B91063200CFA43B /* system_cmds.plist */; }; C9D64CD31B91067500CFA43B /* system_cmds.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C9D64CCF1B91063200CFA43B /* system_cmds.plist */; }; + C9E0691A1C58BD7E00C956EB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA9B766D13739D27001BB39F /* CoreFoundation.framework */; }; + C9E0691C1C58BDA000C956EB /* CoreSymbolication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9E0691B1C58BDA000C956EB /* CoreSymbolication.framework */; }; + C9E0691E1C58BDB800C956EB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9E0691D1C58BDB800C956EB /* IOKit.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXBuildRule section */ + 78DE9DFF1B504DB800FE6DF5 /* PBXBuildRule */ = { + isa = PBXBuildRule; + compilerSpec = com.apple.compilers.proxy.script; + fileType = pattern.proxy; + isEditable = 1; + outputFiles = ( + "$(DERIVED_SOURCES_DIR)/$(CURRENT_ARCH)/darwin_version.c", + "$(DERIVED_SOURCES_DIR)/$(CURRENT_ARCH)/darwin_version.h", + ); + script = "/bin/bash ${XPC_BUILD_XCSCRIPTS_DIR}/darwinversion.sh"; + }; +/* End PBXBuildRule section */ + /* Begin PBXContainerItemProxy section */ 08DC488F1A12C6F0008AAF38 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -577,68 +550,320 @@ remoteGlobalIDString = 1523FE5A1595048900661E82; remoteInfo = ltop; }; - 18597F1918CBC3B000531A50 /* PBXContainerItemProxy */ = { + 1812F18E1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C20D8C681C1A102F00C1226B; + remoteInfo = gcore; + }; + 1812F1901C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 78DE9DDF1B5045DE00FE6DF5; + remoteInfo = wait4path; + }; + 1812F1921C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97999D211AE84C0E00E8B10F; + remoteInfo = lskq; + }; + 1812F1941C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 08DC48841A12C21B008AAF38; + remoteInfo = kpgo; + }; + 1812F19A1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 550C19E21804D226001DA380; + remoteInfo = iosim; + }; + 1812F19C1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = ADA9006F17679A8C00161ADF; + remoteInfo = purge; + }; + 1812F19E1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C625B28716D6F27E00168EF7; + remoteInfo = taskpolicy; + }; + 1812F1A01C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55CCB16A16B84EDA00B56979; + remoteInfo = vm_purgeable_stat; + }; + 1812F1A21C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C96F50AE15BDCEC3008682F7; + remoteInfo = lsmp; + }; + 1812F1A41C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1523FE5A1595048900661E82; + remoteInfo = ltop; + }; + 1812F1A61C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA959E7E13968C8E00CA9C60; + remoteInfo = zoneinfo; + }; + 1812F1A81C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA0A860713968E8500D2272C; + remoteInfo = zprint; + }; + 1812F1AA1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4BE139682BA0018C7BB; + remoteInfo = vifs; + }; + 1812F1AC1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4CA139682F80018C7BB; + remoteInfo = vipw; + }; + 1812F1AE1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4D7139683580018C7BB; + remoteInfo = vm_stat; + }; + 1812F1B01C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4E3139683EB0018C7BB; + remoteInfo = zdump; + }; + 1812F1B21C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4EF139684B40018C7BB; + remoteInfo = zic; + }; + 1812F1B41C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF48A139680CF0018C7BB; + remoteInfo = sync; + }; + 1812F1B61C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4971396812D0018C7BB; + remoteInfo = sysctl; + }; + 1812F1B81C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA9BF4A5139681910018C7BB; + remoteInfo = trace; + }; + 1812F1BA1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE58A45137D69A60049DD3B; + remoteInfo = sc_usage; + }; + 1812F1BC1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE58A0913799F610049DD3B; + remoteInfo = sa; + }; + 1812F1BE1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE589DB137902F50049DD3B; + remoteInfo = pwd_mkdb; + }; + 1812F1C01C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE589E81379044E0049DD3B; + remoteInfo = reboot; + }; + 1812F1C21C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE589F5137904DF0049DD3B; + remoteInfo = halt; + }; + 1812F1C41C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE589BA1378FCAA0049DD3B; + remoteInfo = passwd; + }; + 1812F1C61C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE5899B137836A00049DD3B; + remoteInfo = nvram; + }; + 1812F1C81C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BAE589AA137837130049DD3B; + remoteInfo = pagesize; + }; + 1812F1CA1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BACC1D3D1377B6E2007728F4; + remoteInfo = mkfile; + }; + 1812F1CC1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BACC1D491377B7A7007728F4; + remoteInfo = newgrp; + }; + 1812F1CE1C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BACC1D591377B85C007728F4; + remoteInfo = nologin; + }; + 1812F1D01C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA4FD2EE1372FB3D0025925C; + remoteInfo = ac; + }; + 1812F1D21C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA4FD3041372FFD80025925C; + remoteInfo = accton; + }; + 1812F1D41C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA4FD31A137300ED0025925C; + remoteInfo = arch; + }; + 1812F1D61C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA4FD32F137305DD0025925C; + remoteInfo = machine; + }; + 1812F1D81C8F923900F3DC9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA4B79C51373A72800003422; + remoteInfo = dmesg; + }; + 1812F1DA1C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 18597EC318CBC2A300531A50; - remoteInfo = kdprof; + remoteGlobalIDString = BA4B79E01373AF7A00003422; + remoteInfo = dynamic_pager; }; - 18597F1B18CBC3B900531A50 /* PBXContainerItemProxy */ = { + 1812F1DC1C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 18597EC318CBC2A300531A50; - remoteInfo = kdprof; + remoteGlobalIDString = BA4B79FD1373B9E900003422; + remoteInfo = fs_usage; }; - 18597F1D18CBC3C900531A50 /* PBXContainerItemProxy */ = { + 1812F1DE1C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 1865513518CA6F41003B92A7; - remoteInfo = CPPUtil; + remoteGlobalIDString = BA4B7A0E1373BE9D00003422; + remoteInfo = getconf; }; - 1865518818CA7137003B92A7 /* PBXContainerItemProxy */ = { + 1812F1E01C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 1865513518CA6F41003B92A7; - remoteInfo = CPPUtil; + remoteGlobalIDString = BA4B7A3F137648E100003422; + remoteInfo = getty; }; - 1865518A18CA7151003B92A7 /* PBXContainerItemProxy */ = { + 1812F1E21C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 1865517B18CA7104003B92A7; - remoteInfo = msa; + remoteGlobalIDString = BA4B7A5D13765CC700003422; + remoteInfo = hostinfo; }; - 186551CF18CA8154003B92A7 /* PBXContainerItemProxy */ = { + 1812F1E41C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 1865517B18CA7104003B92A7; - remoteInfo = msa; + remoteGlobalIDString = BA4B7A6913765D3E00003422; + remoteInfo = iostat; }; - 18C8728318EA115D00F86DD9 /* PBXContainerItemProxy */ = { + 1812F1E61C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 1865513518CA6F41003B92A7; - remoteInfo = CPPUtil; + remoteGlobalIDString = BA4B7A7D13765F3C00003422; + remoteInfo = latency; }; - 18C872CD18EA1A6200F86DD9 /* PBXContainerItemProxy */ = { + 1812F1E81C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 18C8727E18EA114F00F86DD9; - remoteInfo = KDBG; + remoteGlobalIDString = BA473DA01377B2230005CC19; + remoteInfo = login; }; - 18C872CF18EA1A6F00F86DD9 /* PBXContainerItemProxy */ = { + 1812F1EC1C8F923900F3DC9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = 18C8727E18EA114F00F86DD9; - remoteInfo = KDBG; + remoteGlobalIDString = BACC1D0D1377B481007728F4; + remoteInfo = mean; }; 550C19EE1804D2AD001DA380 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -668,6 +893,27 @@ remoteGlobalIDString = 55CCB16A16B84EDA00B56979; remoteInfo = vm_purgeable_stat; }; + 78DE9DEC1B5048D400FE6DF5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 78DE9DDF1B5045DE00FE6DF5; + remoteInfo = wait4path; + }; + 78DE9DF91B504D1200FE6DF5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 78DE9DDF1B5045DE00FE6DF5; + remoteInfo = wait4path; + }; + 8EC3916D1C973440001E28E6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA2DE9181372FA9100D1913C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC3915B1C9733C2001E28E6; + remoteInfo = proc_uuid_policy; + }; 97999D341AE84D3A00E8B10F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -745,13 +991,6 @@ remoteGlobalIDString = BA4B79C51373A72800003422; remoteInfo = dmesg; }; - BA4B79DC1373A9CE00003422 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BA4B79D41373A97000003422; - remoteInfo = dp_notify_lib; - }; BA4B79F71373B06B00003422 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -1095,19 +1334,12 @@ remoteGlobalIDString = BA4B79C51373A72800003422; remoteInfo = dmesg; }; - BACC1D251377B58A007728F4 /* PBXContainerItemProxy */ = { + BACC1D271377B58A007728F4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = BA4B79D41373A97000003422; - remoteInfo = dp_notify_lib; - }; - BACC1D271377B58A007728F4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BA4B79E01373AF7A00003422; - remoteInfo = dynamic_pager; + remoteGlobalIDString = BA4B79E01373AF7A00003422; + remoteInfo = dynamic_pager; }; BACC1D291377B58A007728F4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -1158,13 +1390,6 @@ remoteGlobalIDString = BA473DA01377B2230005CC19; remoteInfo = login; }; - BACC1D371377B58A007728F4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BACC1D011377B3E6007728F4; - remoteInfo = makekey; - }; BACC1D391377B58A007728F4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -1172,13 +1397,6 @@ remoteGlobalIDString = BACC1D0D1377B481007728F4; remoteInfo = mean; }; - BACC1D3B1377B5D9007728F4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BACC1D011377B3E6007728F4; - remoteInfo = makekey; - }; BACC1D671377B8DC007728F4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -1319,13 +1537,6 @@ remoteGlobalIDString = BAE58A0913799F610049DD3B; remoteInfo = sa; }; - BAE58A2F1379A1260049DD3B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BAE58A1813799FFA0049DD3B; - remoteInfo = sadc; - }; BAE58A311379A1300049DD3B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; @@ -1333,40 +1544,33 @@ remoteGlobalIDString = BAE58A0913799F610049DD3B; remoteInfo = sa; }; - BAE58A331379A1300049DD3B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BA2DE9181372FA9100D1913C /* Project object */; - proxyType = 1; - remoteGlobalIDString = BAE58A1813799FFA0049DD3B; - remoteInfo = sadc; - }; - BAE58A41137A59300049DD3B /* PBXContainerItemProxy */ = { + BAE58A53137D69FB0049DD3B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = BAE58A351379A3F60049DD3B; - remoteInfo = sar; + remoteGlobalIDString = BAE58A45137D69A60049DD3B; + remoteInfo = sc_usage; }; - BAE58A43137A59390049DD3B /* PBXContainerItemProxy */ = { + BAE58A55137D6A050049DD3B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = BAE58A351379A3F60049DD3B; - remoteInfo = sar; + remoteGlobalIDString = BAE58A45137D69A60049DD3B; + remoteInfo = sc_usage; }; - BAE58A53137D69FB0049DD3B /* PBXContainerItemProxy */ = { + C21481461C1A1447003BCA63 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = BAE58A45137D69A60049DD3B; - remoteInfo = sc_usage; + remoteGlobalIDString = C20D8C681C1A102F00C1226B; + remoteInfo = gcore; }; - BAE58A55137D6A050049DD3B /* PBXContainerItemProxy */ = { + C21481481C1A14AD003BCA63 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BA2DE9181372FA9100D1913C /* Project object */; proxyType = 1; - remoteGlobalIDString = BAE58A45137D69A60049DD3B; - remoteInfo = sc_usage; + remoteGlobalIDString = C20D8C681C1A102F00C1226B; + remoteInfo = gcore; }; C625B29016D6F38700168EF7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -1418,43 +1622,53 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - 18597EC218CBC2A300531A50 /* CopyFiles */ = { + 1812F1ED1C8F923900F3DC9E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /AppleInternal/CoreOS/BATS/unit_tests; + dstSubfolderSpec = 0; + files = ( + 1812F1EE1C8F923900F3DC9E /* system_cmds.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 550C19E71804D226001DA380 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/local/share/man/man1; dstSubfolderSpec = 0; files = ( - 18597EC918CBC2A300531A50 /* kdprof.1 in CopyFiles */, + 550C19ED1804D295001DA380 /* iosim.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 1865517A18CA7104003B92A7 /* CopyFiles */ = { + 55CCB16F16B84EDA00B56979 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/local/share/man/man1; dstSubfolderSpec = 0; files = ( - 1865518118CA7104003B92A7 /* msa.1 in CopyFiles */, + 55CCB17616B84F3600B56979 /* vm_purgeable_stat.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 550C19E71804D226001DA380 /* CopyFiles */ = { + 78DE9DDE1B5045DE00FE6DF5 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = /usr/local/share/man/man1; + dstPath = /usr/share/man/man1; dstSubfolderSpec = 0; files = ( - 550C19ED1804D295001DA380 /* iosim.1 in CopyFiles */, + 78DE9EE61B505F1800FE6DF5 /* wait4path.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 55CCB16F16B84EDA00B56979 /* CopyFiles */ = { + 8EC391601C9733C2001E28E6 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/local/share/man/man1; dstSubfolderSpec = 0; files = ( - 55CCB17616B84F3600B56979 /* vm_purgeable_stat.1 in CopyFiles */, + 8EC3916C1C973429001E28E6 /* proc_uuid_policy.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -1821,16 +2035,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - BACC1D051377B3E6007728F4 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man8; - dstSubfolderSpec = 0; - files = ( - BACC1D0C1377B41B007728F4 /* makekey.8 in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; BACC1D411377B6E2007728F4 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1931,35 +2135,23 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - BAE58A2013799FFA0049DD3B /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man8; - dstSubfolderSpec = 0; - files = ( - BAE58A2A1379A07E0049DD3B /* sa1.8 in CopyFiles */, - BAE58A2B1379A0820049DD3B /* sa2.8 in CopyFiles */, - BAE58A2C1379A0860049DD3B /* sadc.8 in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - BAE58A391379A3F60049DD3B /* CopyFiles */ = { + BAE58A4A137D69A60049DD3B /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1; dstSubfolderSpec = 0; files = ( - BAE58A40137A59200049DD3B /* sar.1 in CopyFiles */, + BAE58A52137D69ED0049DD3B /* sc_usage.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - BAE58A4A137D69A60049DD3B /* CopyFiles */ = { + C20D8C671C1A102F00C1226B /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = /usr/share/man/man1; + dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( - BAE58A52137D69ED0049DD3B /* sc_usage.1 in CopyFiles */, + C21481451C1A131D003BCA63 /* gcore.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -1999,7 +2191,9 @@ dstPath = /AppleInternal/CoreOS/BATS/unit_tests; dstSubfolderSpec = 0; files = ( + 8EC391681C973400001E28E6 /* proc_uuid_policy.c in CopyFiles */, C9D64CD31B91067500CFA43B /* system_cmds.plist in CopyFiles */, + 8EC3916B1C97341E001E28E6 /* proc_uuid_policy.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -2011,9 +2205,12 @@ 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 = ""; }; + 1821B00B1C88BEE2000BAA0C /* usage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = usage.cpp; sourceTree = ""; }; + 1821B00C1C88BEE2000BAA0C /* usage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = usage.hpp; sourceTree = ""; }; + 18380CDC1C596E8900DC6B89 /* eostrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = eostrace.c; sourceTree = ""; }; + 18410FED1CC881FD00385C96 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; 1845E41418EB95810010F451 /* TraceFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TraceFile.cpp; sourceTree = ""; }; 1845E41518EB95810010F451 /* TraceFile.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TraceFile.hpp; sourceTree = ""; }; - 18597EC418CBC2A300531A50 /* kdprof */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = kdprof; sourceTree = BUILT_PRODUCTS_DIR; }; 18597EC818CBC2A300531A50 /* kdprof.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = kdprof.1; sourceTree = ""; }; 18597ECC18CBC35700531A50 /* Action.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Action.hpp; sourceTree = ""; }; 18597ECD18CBC35700531A50 /* CollectAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CollectAction.hpp; sourceTree = ""; }; @@ -2047,7 +2244,17 @@ 185B9771191022B200FCB84C /* VoucherContentSysctl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VoucherContentSysctl.cpp; sourceTree = ""; }; 185B97731910475500FCB84C /* WriteTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteTraceFileAction.cpp; sourceTree = ""; }; 185B97741910475500FCB84C /* WriteTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WriteTraceFileAction.hpp; sourceTree = ""; }; - 1865513618CA6F41003B92A7 /* libCPPUtil.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCPPUtil.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 185F75141CC2EFC600B0EA9E /* TypeFilterAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeFilterAction.cpp; sourceTree = ""; }; + 185F75151CC2EFC600B0EA9E /* TypeFilterAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TypeFilterAction.hpp; sourceTree = ""; }; + 185F75171CC337D400B0EA9E /* Machine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Machine.cpp; sourceTree = ""; }; + 185F75191CC34EBE00B0EA9E /* WriteTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteTraceFileAction.cpp; sourceTree = ""; }; + 185F751A1CC34EBE00B0EA9E /* WriteTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WriteTraceFileAction.hpp; sourceTree = ""; }; + 18624C851BF6400200FA0575 /* TypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TypeSummary.hpp; sourceTree = ""; }; + 18624C861BF64ED700FA0575 /* CPUTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CPUTypeSummary.hpp; sourceTree = ""; }; + 18624C871BF6503600FA0575 /* ProcessTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ProcessTypeSummary.hpp; sourceTree = ""; }; + 18624C881BF651EC00FA0575 /* ThreadTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ThreadTypeSummary.hpp; sourceTree = ""; }; + 186288CF1CC5DA71002950E0 /* UUIDMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UUIDMap.cpp; sourceTree = ""; }; + 186288D01CC5DA71002950E0 /* UUIDMap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UUIDMap.hpp; sourceTree = ""; }; 1865513A18CA70B5003B92A7 /* CPPUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPPUtil.h; sourceTree = ""; }; 1865513B18CA70B5003B92A7 /* UtilAbsInterval.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UtilAbsInterval.cpp; sourceTree = ""; }; 1865513C18CA70B5003B92A7 /* UtilAbsInterval.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilAbsInterval.hpp; sourceTree = ""; }; @@ -2079,7 +2286,6 @@ 1865515618CA70B5003B92A7 /* UtilTimer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTimer.hpp; sourceTree = ""; }; 1865515718CA70B5003B92A7 /* UtilTRange.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTRange.hpp; sourceTree = ""; }; 1865515818CA70B5003B92A7 /* UtilTRangeValue.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTRangeValue.hpp; sourceTree = ""; }; - 1865517C18CA7104003B92A7 /* msa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = msa; sourceTree = BUILT_PRODUCTS_DIR; }; 1865518018CA7104003B92A7 /* msa.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = msa.1; sourceTree = ""; }; 1865518C18CA72F7003B92A7 /* Action.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Action.hpp; sourceTree = ""; }; 1865518E18CA72F7003B92A7 /* EventProcessing.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EventProcessing.hpp; sourceTree = ""; }; @@ -2094,10 +2300,18 @@ 1865519818CA72F7003B92A7 /* Printing.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Printing.hpp; sourceTree = ""; }; 1865519918CA72F7003B92A7 /* ReadTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadTraceFileAction.cpp; sourceTree = ""; }; 1865519A18CA72F7003B92A7 /* ReadTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ReadTraceFileAction.hpp; sourceTree = ""; }; - 186551CD18CA7A1B003B92A7 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.Internal.sdk/System/Library/Frameworks/System.framework; sourceTree = DEVELOPER_DIR; }; + 1873F11E1CC52204008950A8 /* BinaryDataTraceEncoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = BinaryDataTraceEncoder.hpp; sourceTree = ""; }; + 1873F1211CC551DD008950A8 /* DeviceMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceMap.cpp; sourceTree = ""; }; + 1873F1221CC551DD008950A8 /* DeviceMap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DeviceMap.hpp; sourceTree = ""; }; + 1873F1261CC587E2008950A8 /* BinaryDataTraceDecoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = BinaryDataTraceDecoder.hpp; sourceTree = ""; }; + 1875DF421C443513004AC849 /* KDState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KDState.cpp; sourceTree = ""; }; 1888DB65191A8A4400A0541E /* PrintBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PrintBuffer.hpp; sourceTree = ""; }; 188959FC1958D287004576E8 /* TaskRequestedPolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TaskRequestedPolicy.hpp; sourceTree = ""; }; - 18C8727F18EA114F00F86DD9 /* libKDBG.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKDBG.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 189337C21CC7CB4800B2A6A4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 189337C41CC7DA8700B2A6A4 /* UtilCoreSymbolication.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = UtilCoreSymbolication.hpp; sourceTree = ""; }; + 189632961C5FD38E00FA9646 /* eostrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eostrace.h; sourceTree = ""; }; + 18C65BAD1CC1868D005194F4 /* TypeFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeFilter.cpp; sourceTree = ""; }; + 18C65BAE1CC1868D005194F4 /* TypeFilter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TypeFilter.hpp; sourceTree = ""; }; 18C8728718EA128B00F86DD9 /* CPUActivity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CPUActivity.hpp; sourceTree = ""; }; 18C8728818EA128B00F86DD9 /* CPUSummary.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CPUSummary.hpp; sourceTree = ""; }; 18C8728918EA128B00F86DD9 /* IOActivity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOActivity.hpp; sourceTree = ""; }; @@ -2133,7 +2347,12 @@ 18C872A718EA128B00F86DD9 /* TraceDataHeader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TraceDataHeader.hpp; sourceTree = ""; }; 18C872A818EA128B00F86DD9 /* VoucherInterval.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VoucherInterval.hpp; sourceTree = ""; }; 18D0E13119101CD200F93974 /* VoucherContentSysctl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VoucherContentSysctl.hpp; sourceTree = ""; }; + 18D6F9AF1C5A8EF000F472A7 /* eostraced.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eostraced.c; sourceTree = ""; }; + 18D6F9B11C5A8EFB00F472A7 /* com.apple.eostraced.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.eostraced.plist; sourceTree = ""; }; 18D8B66519535B92008847DF /* TaskEffectivePolicy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TaskEffectivePolicy.hpp; sourceTree = ""; }; + 18EA07101C99C76C006D3005 /* EmbeddedOSSupportHost.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EmbeddedOSSupportHost.framework; path = System/Library/PrivateFrameworks/EmbeddedOSSupportHost.framework; sourceTree = SDKROOT; }; + 18EA07121C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = copy_of_AppleEmbeddedOSSupport.c; path = eostrace/copy_of_AppleEmbeddedOSSupport.c; sourceTree = SOURCE_ROOT; }; + 18EA07131C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = copy_of_AppleEmbeddedOSSupport.h; path = eostrace/copy_of_AppleEmbeddedOSSupport.h; sourceTree = SOURCE_ROOT; }; 550C19E01804C55E001DA380 /* iosim.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = iosim.1; sourceTree = ""; }; 550C19E11804C55E001DA380 /* iosim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iosim.c; sourceTree = ""; }; 550C19EB1804D226001DA380 /* iosim */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = iosim; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2143,13 +2362,19 @@ 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; }; + 78DE9DE01B5045DE00FE6DF5 /* wait4path */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = wait4path; sourceTree = BUILT_PRODUCTS_DIR; }; + 78DE9DFC1B504D7F00FE6DF5 /* wait4path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wait4path.c; path = wait4path/wait4path.c; sourceTree = ""; }; + 78DE9DFD1B504D7F00FE6DF5 /* wait4path.version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wait4path.version; path = wait4path/wait4path.version; sourceTree = ""; }; + 78DE9EE51B505EBF00FE6DF5 /* wait4path.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = wait4path.1; path = wait4path/wait4path.1; sourceTree = ""; }; + 8EC391651C9733C2001E28E6 /* proc_uuid_policy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = proc_uuid_policy; sourceTree = BUILT_PRODUCTS_DIR; }; + 8EC391671C973400001E28E6 /* proc_uuid_policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = proc_uuid_policy.c; path = proc_uuid_policy.tproj/proc_uuid_policy.c; sourceTree = SOURCE_ROOT; }; + 8EC3916A1C97341E001E28E6 /* proc_uuid_policy.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = proc_uuid_policy.1; path = proc_uuid_policy.tproj/proc_uuid_policy.1; 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 = ""; }; + 9FAAF8741C158C0B00E6856D /* ThreadRequestedPolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ThreadRequestedPolicy.hpp; sourceTree = ""; }; + 9FAAF8761C158C2300E6856D /* ThreadEffectivePolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ThreadEffectivePolicy.hpp; 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 = ""; }; @@ -2164,7 +2389,6 @@ BA473DB31377B2230005CC19 /* login */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = login; sourceTree = BUILT_PRODUCTS_DIR; }; BA4B79BF1373A53700003422 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = ""; }; BA4B79CD1373A72800003422 /* dmesg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dmesg; sourceTree = BUILT_PRODUCTS_DIR; }; - BA4B79D51373A97000003422 /* libdp_notify_lib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdp_notify_lib.a; sourceTree = BUILT_PRODUCTS_DIR; }; BA4B79EC1373AF7A00003422 /* dynamic_pager */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dynamic_pager; sourceTree = BUILT_PRODUCTS_DIR; }; BA4B79F31373B01B00003422 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = ""; }; BA4B79FA1373B7C300003422 /* com.apple.dynamic_pager.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = com.apple.dynamic_pager.plist; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2232,10 +2456,7 @@ BA4FD2171372FAFA0025925C /* util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; BA4FD2201372FAFA0025925C /* dmesg.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dmesg.8; sourceTree = ""; }; BA4FD2211372FAFA0025925C /* dmesg.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dmesg.c; sourceTree = ""; }; - BA4FD2281372FAFA0025925C /* backing_store_alerts.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = backing_store_alerts.defs; sourceTree = ""; }; - BA4FD2291372FAFA0025925C /* backing_store_triggers.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = backing_store_triggers.defs; sourceTree = ""; }; BA4FD22A1372FAFA0025925C /* com.apple.dynamic_pager.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.dynamic_pager.plist; sourceTree = ""; }; - BA4FD22B1372FAFA0025925C /* default_pager_alerts.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = default_pager_alerts.defs; sourceTree = ""; }; BA4FD22C1372FAFA0025925C /* dynamic_pager.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dynamic_pager.8; sourceTree = ""; }; BA4FD22D1372FAFA0025925C /* dynamic_pager.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dynamic_pager.c; sourceTree = ""; }; BA4FD2301372FAFA0025925C /* fs_usage.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = fs_usage.1; sourceTree = ""; }; @@ -2274,8 +2495,6 @@ BA4FD2611372FAFA0025925C /* login */ = {isa = PBXFileReference; lastKnownFileType = text; path = login; sourceTree = ""; }; BA4FD2621372FAFA0025925C /* login.term */ = {isa = PBXFileReference; lastKnownFileType = text; path = login.term; sourceTree = ""; }; BA4FD2631372FAFA0025925C /* pathnames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = ""; }; - BA4FD2671372FAFA0025925C /* makekey.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = makekey.8; sourceTree = ""; }; - BA4FD2681372FAFA0025925C /* makekey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = makekey.c; sourceTree = ""; }; BA4FD26B1372FAFA0025925C /* mean.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mean.c; sourceTree = ""; }; BA4FD26E1372FAFA0025925C /* mkfile.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = mkfile.8; sourceTree = ""; }; BA4FD26F1372FAFA0025925C /* mkfile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mkfile.c; sourceTree = ""; }; @@ -2309,16 +2528,6 @@ BA4FD29B1372FAFA0025925C /* pdb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pdb.c; sourceTree = ""; }; BA4FD29C1372FAFA0025925C /* sa.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa.8; sourceTree = ""; }; BA4FD29D1372FAFA0025925C /* usrdb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = usrdb.c; sourceTree = ""; }; - BA4FD2A01372FAFA0025925C /* sa1.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa1.8; sourceTree = ""; }; - BA4FD2A11372FAFA0025925C /* sa1.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sa1.sh; sourceTree = ""; }; - BA4FD2A21372FAFA0025925C /* sa2.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa2.8; sourceTree = ""; }; - BA4FD2A31372FAFA0025925C /* sa2.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sa2.sh; sourceTree = ""; }; - BA4FD2A41372FAFA0025925C /* sadc.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sadc.8; sourceTree = ""; }; - BA4FD2A51372FAFA0025925C /* sadc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sadc.c; sourceTree = ""; }; - BA4FD2A61372FAFA0025925C /* sadc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sadc.h; sourceTree = ""; }; - BA4FD2A91372FAFA0025925C /* sar.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sar.1; sourceTree = ""; }; - BA4FD2AA1372FAFA0025925C /* sar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sar.c; sourceTree = ""; }; - BA4FD2AB1372FAFA0025925C /* sar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sar.h; sourceTree = ""; }; BA4FD2AE1372FAFA0025925C /* sc_usage.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sc_usage.1; sourceTree = ""; }; BA4FD2AF1372FAFA0025925C /* sc_usage.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sc_usage.c; sourceTree = ""; }; BA4FD2B21372FAFA0025925C /* kextmanager.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = kextmanager.defs; sourceTree = ""; }; @@ -2378,7 +2587,6 @@ BA9BF4DF139683580018C7BB /* vm_stat */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vm_stat; sourceTree = BUILT_PRODUCTS_DIR; }; BA9BF4EB139683EB0018C7BB /* zdump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zdump; sourceTree = BUILT_PRODUCTS_DIR; }; BA9BF4F7139684B40018C7BB /* zic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zic; sourceTree = BUILT_PRODUCTS_DIR; }; - BACC1D091377B3E6007728F4 /* makekey */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = makekey; sourceTree = BUILT_PRODUCTS_DIR; }; BACC1D151377B481007728F4 /* mean */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mean; sourceTree = BUILT_PRODUCTS_DIR; }; BACC1D451377B6E2007728F4 /* mkfile */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mkfile; sourceTree = BUILT_PRODUCTS_DIR; }; BACC1D551377B7A7007728F4 /* newgrp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = newgrp; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2389,16 +2597,40 @@ BAE589E3137902F50049DD3B /* pwd_mkdb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pwd_mkdb; sourceTree = BUILT_PRODUCTS_DIR; }; BAE589F01379044E0049DD3B /* reboot */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = reboot; sourceTree = BUILT_PRODUCTS_DIR; }; BAE58A1113799F610049DD3B /* sa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sa; sourceTree = BUILT_PRODUCTS_DIR; }; - BAE58A2513799FFA0049DD3B /* sadc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sadc; sourceTree = BUILT_PRODUCTS_DIR; }; - BAE58A3D1379A3F60049DD3B /* sar */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sar; sourceTree = BUILT_PRODUCTS_DIR; }; BAE58A4E137D69A60049DD3B /* sc_usage */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sc_usage; sourceTree = BUILT_PRODUCTS_DIR; }; + C20D8C691C1A102F00C1226B /* gcore */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gcore; sourceTree = BUILT_PRODUCTS_DIR; }; + C214810D1C1A11E6003BCA63 /* corefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = corefile.c; path = gcore.tproj/corefile.c; sourceTree = ""; }; + C214810E1C1A11E6003BCA63 /* corefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = corefile.h; path = gcore.tproj/corefile.h; sourceTree = ""; }; + C214810F1C1A11E6003BCA63 /* dyld_shared_cache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dyld_shared_cache.c; path = gcore.tproj/dyld_shared_cache.c; sourceTree = ""; }; + C21481101C1A11E6003BCA63 /* dyld_shared_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dyld_shared_cache.h; path = gcore.tproj/dyld_shared_cache.h; sourceTree = ""; }; + C21481111C1A11E6003BCA63 /* dyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dyld.c; path = gcore.tproj/dyld.c; sourceTree = ""; }; + C21481121C1A11E6003BCA63 /* dyld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dyld.h; path = gcore.tproj/dyld.h; sourceTree = ""; }; + C21481131C1A11E6003BCA63 /* gcore.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = gcore.1; path = gcore.tproj/gcore.1; sourceTree = ""; }; + C21481141C1A11E6003BCA63 /* loader_additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = loader_additions.h; path = gcore.tproj/loader_additions.h; sourceTree = ""; }; + C21481151C1A11E6003BCA63 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = gcore.tproj/main.c; sourceTree = ""; }; + C21481161C1A11E6003BCA63 /* options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = options.h; path = gcore.tproj/options.h; sourceTree = ""; }; + C21481171C1A11E6003BCA63 /* region.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = region.h; path = gcore.tproj/region.h; sourceTree = ""; }; + C21481181C1A11E6003BCA63 /* sparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sparse.c; path = gcore.tproj/sparse.c; sourceTree = ""; }; + C21481191C1A11E6003BCA63 /* sparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sparse.h; path = gcore.tproj/sparse.h; sourceTree = ""; }; + C214811A1C1A11E7003BCA63 /* threads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = threads.c; path = gcore.tproj/threads.c; sourceTree = ""; }; + C214811B1C1A11E7003BCA63 /* threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = threads.h; path = gcore.tproj/threads.h; sourceTree = ""; }; + C214811C1C1A11E7003BCA63 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utils.c; path = gcore.tproj/utils.c; sourceTree = ""; }; + C214811D1C1A11E7003BCA63 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = gcore.tproj/utils.h; sourceTree = ""; }; + C214811E1C1A11E7003BCA63 /* vanilla.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vanilla.c; path = gcore.tproj/vanilla.c; sourceTree = ""; }; + C214811F1C1A11E7003BCA63 /* vanilla.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vanilla.h; path = gcore.tproj/vanilla.h; sourceTree = ""; }; + C21481201C1A11E7003BCA63 /* vm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vm.c; path = gcore.tproj/vm.c; sourceTree = ""; }; + C21481211C1A11E7003BCA63 /* vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vm.h; path = gcore.tproj/vm.h; sourceTree = ""; }; + C248DBAF1C1A1D0500F6E9AF /* libcompression.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcompression.dylib; path = /usr/lib/libcompression.dylib; sourceTree = ""; }; C625B28816D6F27E00168EF7 /* taskpolicy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = taskpolicy; sourceTree = BUILT_PRODUCTS_DIR; }; C625B28A16D6F27E00168EF7 /* taskpolicy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = taskpolicy.c; sourceTree = ""; }; C625B28C16D6F27E00168EF7 /* taskpolicy.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = taskpolicy.8; sourceTree = ""; }; 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; }; + C97199F11C5206DE006D9758 /* libktrace.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libktrace.dylib; path = usr/lib/libktrace.dylib; sourceTree = SDKROOT; }; C9D64CCF1B91063200CFA43B /* system_cmds.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = system_cmds.plist; path = tests/system_cmds.plist; sourceTree = ""; }; + C9E0691B1C58BDA000C956EB /* CoreSymbolication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSymbolication.framework; path = System/Library/PrivateFrameworks/CoreSymbolication.framework; sourceTree = SDKROOT; }; + C9E0691D1C58BDB800C956EB /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; FEBEE5CF1B0EACEB00166A8B /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -2418,51 +2650,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 18597EC118CBC2A300531A50 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 18C872CC18EA1A5000F86DD9 /* libKDBG.a in Frameworks */, - 18597F1F18CBC3D000531A50 /* libCPPUtil.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1865513318CA6F41003B92A7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1865517918CA7104003B92A7 /* Frameworks */ = { + 550C19E51804D226001DA380 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 18C872CB18EA1A4600F86DD9 /* libKDBG.a in Frameworks */, - 1865518718CA7130003B92A7 /* libCPPUtil.a in Frameworks */, + 550C19E61804D226001DA380 /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18C8727C18EA114F00F86DD9 /* Frameworks */ = { + 55CCB16D16B84EDA00B56979 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 55CCB16E16B84EDA00B56979 /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 550C19E51804D226001DA380 /* Frameworks */ = { + 78DE9DDD1B5045DE00FE6DF5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 550C19E61804D226001DA380 /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 55CCB16D16B84EDA00B56979 /* Frameworks */ = { + 8EC3915E1C9733C2001E28E6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 55CCB16E16B84EDA00B56979 /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2499,10 +2713,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A6738D051AF6FFB5001EF064 /* CoreFoundation.framework in Frameworks */, + C9E0691E1C58BDB800C956EB /* IOKit.framework in Frameworks */, + C9E0691C1C58BDA000C956EB /* CoreSymbolication.framework in Frameworks */, + C9E0691A1C58BD7E00C956EB /* CoreFoundation.framework in Frameworks */, BA0A860B13968E8500D2272C /* libutil.dylib in Frameworks */, - A624DA861AF6F3CF00F56A5C /* CoreSymbolication.framework in Frameworks */, - A6738D031AF6FF9F001EF064 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2520,13 +2734,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BA4B79D21373A97000003422 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; BA4B79E41373AF7A00003422 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2540,6 +2747,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C97199F21C5206DE006D9758 /* libktrace.dylib in Frameworks */, BA4B7A0A1373BA4600003422 /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2704,13 +2912,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BACC1D041377B3E6007728F4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; BACC1D101377B481007728F4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2776,28 +2977,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BAE58A1F13799FFA0049DD3B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE58A281379A0670049DD3B /* CoreFoundation.framework in Frameworks */, - BAE58A291379A06B0049DD3B /* IOKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - BAE58A381379A3F60049DD3B /* Frameworks */ = { + BAE58A48137D69A60049DD3B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + BAE58A49137D69A60049DD3B /* libutil.dylib in Frameworks */, + BAE58A51137D69E30049DD3B /* libncurses.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - BAE58A48137D69A60049DD3B /* Frameworks */ = { + C20D8C661C1A102F00C1226B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BAE58A49137D69A60049DD3B /* libutil.dylib in Frameworks */, - BAE58A51137D69E30049DD3B /* libncurses.dylib in Frameworks */, + C20138731C1A17D0008EE53F /* libutil.dylib in Frameworks */, + C248DBB01C1A1D0500F6E9AF /* libcompression.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2836,6 +3030,17 @@ path = ltop.tproj; sourceTree = ""; }; + 18380CDB1C596E8900DC6B89 /* eostrace */ = { + isa = PBXGroup; + children = ( + 189632961C5FD38E00FA9646 /* eostrace.h */, + 18380CDC1C596E8900DC6B89 /* eostrace.c */, + 18EA07131C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.h */, + 18EA07121C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.c */, + ); + path = eostrace; + sourceTree = ""; + }; 18597EC518CBC2A300531A50 /* kdprof */ = { isa = PBXGroup; children = ( @@ -2868,6 +3073,13 @@ 18597EE618CBC35700531A50 /* SummaryPrinting.cpp */, 18597EE718CBC35700531A50 /* TraceFileAction.hpp */, 18597EE818CBC35700531A50 /* TraceFileAction.cpp */, + 185F75151CC2EFC600B0EA9E /* TypeFilterAction.hpp */, + 185F75141CC2EFC600B0EA9E /* TypeFilterAction.cpp */, + 1821B00C1C88BEE2000BAA0C /* usage.hpp */, + 1821B00B1C88BEE2000BAA0C /* usage.cpp */, + 185F751A1CC34EBE00B0EA9E /* WriteTraceFileAction.hpp */, + 185F75191CC34EBE00B0EA9E /* WriteTraceFileAction.cpp */, + 18410FED1CC881FD00385C96 /* entitlements.plist */, 18597EC818CBC2A300531A50 /* kdprof.1 */, ); path = kdprof; @@ -2883,6 +3095,7 @@ 1865513E18CA70B5003B92A7 /* UtilAbsTime.hpp */, 1865513F18CA70B5003B92A7 /* UtilAssert.hpp */, 1865514018CA70B5003B92A7 /* UtilBase.hpp */, + 189337C41CC7DA8700B2A6A4 /* UtilCoreSymbolication.hpp */, 1865514118CA70B5003B92A7 /* UtilException.hpp */, 1865514218CA70B5003B92A7 /* UtilFileDescriptor.hpp */, 1865514318CA70B5003B92A7 /* UtilLog.cpp */, @@ -2918,41 +3131,56 @@ 1865518E18CA72F7003B92A7 /* EventProcessing.hpp */, 1865518F18CA72F7003B92A7 /* EventRingBuffer.hpp */, 1865519018CA72F7003B92A7 /* global.h */, - 1865519118CA72F7003B92A7 /* Globals.cpp */, 1865519218CA72F7003B92A7 /* Globals.hpp */, - 1865519418CA72F7003B92A7 /* LiveTraceAction.cpp */, + 1865519118CA72F7003B92A7 /* Globals.cpp */, 1865519518CA72F7003B92A7 /* LiveTraceAction.hpp */, + 1865519418CA72F7003B92A7 /* LiveTraceAction.cpp */, 1865519618CA72F7003B92A7 /* main.cpp */, 1888DB65191A8A4400A0541E /* PrintBuffer.hpp */, - 1865519718CA72F7003B92A7 /* Printing.cpp */, 1865519818CA72F7003B92A7 /* Printing.hpp */, - 1865519918CA72F7003B92A7 /* ReadTraceFileAction.cpp */, + 1865519718CA72F7003B92A7 /* Printing.cpp */, 1865519A18CA72F7003B92A7 /* ReadTraceFileAction.hpp */, - 185B9771191022B200FCB84C /* VoucherContentSysctl.cpp */, + 1865519918CA72F7003B92A7 /* ReadTraceFileAction.cpp */, 18D0E13119101CD200F93974 /* VoucherContentSysctl.hpp */, - 185B97731910475500FCB84C /* WriteTraceFileAction.cpp */, + 185B9771191022B200FCB84C /* VoucherContentSysctl.cpp */, 185B97741910475500FCB84C /* WriteTraceFileAction.hpp */, + 185B97731910475500FCB84C /* WriteTraceFileAction.cpp */, 1865518018CA7104003B92A7 /* msa.1 */, ); path = msa; sourceTree = ""; }; + 189337C11CC7CB4800B2A6A4 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 189337C21CC7CB4800B2A6A4 /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 18C8728518EA11B900F86DD9 /* KDBG */ = { isa = PBXGroup; children = ( 18C8728D18EA128B00F86DD9 /* KDebug.h */, + 1873F1261CC587E2008950A8 /* BinaryDataTraceDecoder.hpp */, + 1873F11E1CC52204008950A8 /* BinaryDataTraceEncoder.hpp */, 18C8728718EA128B00F86DD9 /* CPUActivity.hpp */, 18C8728818EA128B00F86DD9 /* CPUSummary.hpp */, + 18624C861BF64ED700FA0575 /* CPUTypeSummary.hpp */, + 1873F1221CC551DD008950A8 /* DeviceMap.hpp */, + 1873F1211CC551DD008950A8 /* DeviceMap.cpp */, 18C8728918EA128B00F86DD9 /* IOActivity.hpp */, 18C8728B18EA128B00F86DD9 /* KDBG.hpp */, 18C8728A18EA128B00F86DD9 /* KDBG.cpp */, 18C8728C18EA128B00F86DD9 /* KDCPUMapEntry.hpp */, 18C8728E18EA128B00F86DD9 /* KDEvent.hpp */, 18C8728F18EA128B00F86DD9 /* KDState.hpp */, + 1875DF421C443513004AC849 /* KDState.cpp */, 18C8729018EA128B00F86DD9 /* KDThreadMapEntry.hpp */, - 18C8729118EA128B00F86DD9 /* Kernel.cpp */, 18C8729218EA128B00F86DD9 /* Kernel.hpp */, + 18C8729118EA128B00F86DD9 /* Kernel.cpp */, 18C8729318EA128B00F86DD9 /* Machine.hpp */, + 185F75171CC337D400B0EA9E /* Machine.cpp */, 18C8729418EA128B00F86DD9 /* Machine.impl.hpp */, 18C8729518EA128B00F86DD9 /* Machine.mutable-impl.hpp */, 18C8729618EA128B00F86DD9 /* MachineCPU.hpp */, @@ -2969,19 +3197,37 @@ 18C872A118EA128B00F86DD9 /* MetaTypes.hpp */, 18C872A218EA128B00F86DD9 /* NurseryMachMsg.hpp */, 18C872A318EA128B00F86DD9 /* ProcessSummary.hpp */, + 18624C871BF6503600FA0575 /* ProcessTypeSummary.hpp */, 18D8B66519535B92008847DF /* TaskEffectivePolicy.hpp */, + 9FAAF8761C158C2300E6856D /* ThreadEffectivePolicy.hpp */, 188959FC1958D287004576E8 /* TaskRequestedPolicy.hpp */, + 9FAAF8741C158C0B00E6856D /* ThreadRequestedPolicy.hpp */, 18C872A418EA128B00F86DD9 /* ThreadSummary.hpp */, + 18624C881BF651EC00FA0575 /* ThreadTypeSummary.hpp */, 18C872A618EA128B00F86DD9 /* TraceCodes.hpp */, 18C872A518EA128B00F86DD9 /* TraceCodes.cpp */, 18C872A718EA128B00F86DD9 /* TraceDataHeader.hpp */, 1845E41518EB95810010F451 /* TraceFile.hpp */, 1845E41418EB95810010F451 /* TraceFile.cpp */, + 18624C851BF6400200FA0575 /* TypeSummary.hpp */, + 18C65BAE1CC1868D005194F4 /* TypeFilter.hpp */, + 18C65BAD1CC1868D005194F4 /* TypeFilter.cpp */, + 186288D01CC5DA71002950E0 /* UUIDMap.hpp */, + 186288CF1CC5DA71002950E0 /* UUIDMap.cpp */, 18C872A818EA128B00F86DD9 /* VoucherInterval.hpp */, ); path = KDBG; sourceTree = ""; }; + 18D6F9A91C5A8EDB00F472A7 /* eostraced */ = { + isa = PBXGroup; + children = ( + 18D6F9AF1C5A8EF000F472A7 /* eostraced.c */, + 18D6F9B11C5A8EFB00F472A7 /* com.apple.eostraced.plist */, + ); + path = eostraced; + sourceTree = ""; + }; 550C19DF1804C55E001DA380 /* iosim.tproj */ = { isa = PBXGroup; children = ( @@ -3000,6 +3246,26 @@ path = vm_purgeable_stat.tproj; sourceTree = ""; }; + 78DE9DFB1B504D3300FE6DF5 /* wait4path */ = { + isa = PBXGroup; + children = ( + 78DE9EE51B505EBF00FE6DF5 /* wait4path.1 */, + 78DE9DFC1B504D7F00FE6DF5 /* wait4path.c */, + 78DE9DFD1B504D7F00FE6DF5 /* wait4path.version */, + ); + name = wait4path; + sourceTree = ""; + }; + 8EC391661C9733EC001E28E6 /* proc_uuid_policy.tproj */ = { + isa = PBXGroup; + children = ( + 8EC3916A1C97341E001E28E6 /* proc_uuid_policy.1 */, + 8EC391671C973400001E28E6 /* proc_uuid_policy.c */, + ); + name = proc_uuid_policy.tproj; + path = passwd.tproj; + sourceTree = ""; + }; 97999D2E1AE84C5700E8B10F /* lskq.tproj */ = { isa = PBXGroup; children = ( @@ -3048,19 +3314,10 @@ BA2DE9161372FA9100D1913C = { isa = PBXGroup; children = ( - C9D64CCF1B91063200CFA43B /* system_cmds.plist */, - A6738D041AF6FFB5001EF064 /* CoreFoundation.framework */, - A6738D021AF6FF9F001EF064 /* IOKit.framework */, - A624DA851AF6F3CF00F56A5C /* CoreSymbolication.framework */, - 08DC488C1A12C2C5008AAF38 /* kpgo.tproj */, - 186551CD18CA7A1B003B92A7 /* System.framework */, - 550C19DF1804C55E001DA380 /* iosim.tproj */, - ADA900781767A02700161ADF /* purge.tproj */, - B3F0E6DA16E9706E008FAD09 /* memory_pressure.tproj */, - 55CCB16716B84ED100B56979 /* vm_purgeable_stat.tproj */, - C96F50AA15BDCBA2008682F7 /* lsmp.tproj */, + 18EA07101C99C76C006D3005 /* EmbeddedOSSupportHost.framework */, BA4FD1E11372FAFA0025925C /* APPLE_LICENSE */, BA4FD2FB1372FB710025925C /* BSD.xcconfig */, + C9D64CCF1B91063200CFA43B /* system_cmds.plist */, BA4FD1D91372FAFA0025925C /* ac.tproj */, BA4FD1DD1372FAFA0025925C /* accton.tproj */, BA4FD1E21372FAFA0025925C /* arch.tproj */, @@ -3068,49 +3325,58 @@ BA4FD1F61372FAFA0025925C /* atrun.tproj */, BA4FD1FF1372FAFA0025925C /* chkpasswd.tproj */, BA4FD20A1372FAFA0025925C /* chpass.tproj */, + 1865513918CA6F8C003B92A7 /* CPPUtil */, BA4FD21E1372FAFA0025925C /* dmesg.tproj */, BA4FD2261372FAFA0025925C /* dynamic_pager.tproj */, BA4FD22E1372FAFA0025925C /* fs_usage.tproj */, + C21481371C1A11F0003BCA63 /* gcore.tproj */, BA4FD2321372FAFA0025925C /* getconf.tproj */, BA4FD23E1372FAFA0025925C /* getty.tproj */, BA4FD24B1372FAFA0025925C /* hostinfo.tproj */, + 550C19DF1804C55E001DA380 /* iosim.tproj */, BA4FD24F1372FAFA0025925C /* iostat.tproj */, + 18C8728518EA11B900F86DD9 /* KDBG */, + 18597EC518CBC2A300531A50 /* kdprof */, + 08DC488C1A12C2C5008AAF38 /* kpgo.tproj */, BA4FD2551372FAFA0025925C /* latency.tproj */, BA4FD2591372FAFA0025925C /* login.tproj */, 97999D2E1AE84C5700E8B10F /* lskq.tproj */, + C96F50AA15BDCBA2008682F7 /* lsmp.tproj */, 1523FE691595056C00661E82 /* ltop.tproj */, - BA4FD2651372FAFA0025925C /* makekey.tproj */, BA4FD2691372FAFA0025925C /* mean.tproj */, + B3F0E6DA16E9706E008FAD09 /* memory_pressure.tproj */, BA4FD26C1372FAFA0025925C /* mkfile.tproj */, + 1865517D18CA7104003B92A7 /* msa */, BA4FD2701372FAFA0025925C /* newgrp.tproj */, BA4FD2741372FAFA0025925C /* nologin.tproj */, BA4FD2791372FAFA0025925C /* nvram.tproj */, BA4FD27D1372FAFA0025925C /* pagesize.tproj */, BA4FD2811372FAFA0025925C /* passwd.tproj */, + 8EC391661C9733EC001E28E6 /* proc_uuid_policy.tproj */, + ADA900781767A02700161ADF /* purge.tproj */, BA4FD28A1372FAFA0025925C /* pwd_mkdb.tproj */, BA4FD2901372FAFA0025925C /* reboot.tproj */, BA4FD2951372FAFA0025925C /* sa.tproj */, - BA4FD29E1372FAFA0025925C /* sadc.tproj */, - BA4FD2A71372FAFA0025925C /* sar.tproj */, BA4FD2AC1372FAFA0025925C /* sc_usage.tproj */, BA4FD2B01372FAFA0025925C /* shutdown.tproj */, BA4FD2B61372FAFA0025925C /* sync.tproj */, BA4FD2BA1372FAFA0025925C /* sysctl.tproj */, + C625B28916D6F27E00168EF7 /* taskpolicy.tproj */, BA4FD2BF1372FAFA0025925C /* trace.tproj */, + 18380CDB1C596E8900DC6B89 /* eostrace */, + 18D6F9A91C5A8EDB00F472A7 /* eostraced */, BA4FD2C31372FAFA0025925C /* vifs.tproj */, BA4FD2C71372FAFA0025925C /* vipw.tproj */, + 55CCB16716B84ED100B56979 /* vm_purgeable_stat.tproj */, BA4FD2CD1372FAFA0025925C /* vm_stat.tproj */, + 78DE9DFB1B504D3300FE6DF5 /* wait4path */, B158E3A1185A836700474677 /* wordexp-helper.tproj */, BA4FD2D11372FAFA0025925C /* zdump.tproj */, BA4FD2D51372FAFA0025925C /* zic.tproj */, BA4FD2E31372FAFA0025925C /* zprint.tproj */, BA4B7A0D1373BBB600003422 /* Libraries */, - C625B28916D6F27E00168EF7 /* taskpolicy.tproj */, - 1865513918CA6F8C003B92A7 /* CPPUtil */, - 18C8728518EA11B900F86DD9 /* KDBG */, - 1865517D18CA7104003B92A7 /* msa */, - 18597EC518CBC2A300531A50 /* kdprof */, BA4FD2F01372FB3D0025925C /* Products */, + 189337C11CC7CB4800B2A6A4 /* Frameworks */, ); sourceTree = ""; }; @@ -3125,10 +3391,13 @@ BA4B7A0D1373BBB600003422 /* Libraries */ = { isa = PBXGroup; children = ( + C97199F11C5206DE006D9758 /* libktrace.dylib */, BA4B79BF1373A53700003422 /* libbsm.dylib */, BA4B7A9313765F8B00003422 /* libncurses.dylib */, BA4B7A091373BA4600003422 /* libutil.dylib */, BA9B767113739D36001BB39F /* libpam.dylib */, + C9E0691D1C58BDB800C956EB /* IOKit.framework */, + C9E0691B1C58BDA000C956EB /* CoreSymbolication.framework */, BA9B766D13739D27001BB39F /* CoreFoundation.framework */, BA4B79F31373B01B00003422 /* SystemConfiguration.framework */, BA9B766E13739D27001BB39F /* OpenDirectory.framework */, @@ -3265,10 +3534,7 @@ BA4FD2261372FAFA0025925C /* dynamic_pager.tproj */ = { isa = PBXGroup; children = ( - BA4FD2281372FAFA0025925C /* backing_store_alerts.defs */, - BA4FD2291372FAFA0025925C /* backing_store_triggers.defs */, BA4FD22A1372FAFA0025925C /* com.apple.dynamic_pager.plist */, - BA4FD22B1372FAFA0025925C /* default_pager_alerts.defs */, BA4FD22C1372FAFA0025925C /* dynamic_pager.8 */, BA4FD22D1372FAFA0025925C /* dynamic_pager.c */, BA4B79FB1373B7ED00003422 /* Processed LaunchDaemon plist */, @@ -3371,15 +3637,6 @@ path = pam.d; sourceTree = ""; }; - BA4FD2651372FAFA0025925C /* makekey.tproj */ = { - isa = PBXGroup; - children = ( - BA4FD2671372FAFA0025925C /* makekey.8 */, - BA4FD2681372FAFA0025925C /* makekey.c */, - ); - path = makekey.tproj; - sourceTree = ""; - }; BA4FD2691372FAFA0025925C /* mean.tproj */ = { isa = PBXGroup; children = ( @@ -3484,30 +3741,6 @@ path = sa.tproj; sourceTree = ""; }; - BA4FD29E1372FAFA0025925C /* sadc.tproj */ = { - isa = PBXGroup; - children = ( - BA4FD2A01372FAFA0025925C /* sa1.8 */, - BA4FD2A11372FAFA0025925C /* sa1.sh */, - BA4FD2A21372FAFA0025925C /* sa2.8 */, - BA4FD2A31372FAFA0025925C /* sa2.sh */, - BA4FD2A41372FAFA0025925C /* sadc.8 */, - BA4FD2A51372FAFA0025925C /* sadc.c */, - BA4FD2A61372FAFA0025925C /* sadc.h */, - ); - path = sadc.tproj; - sourceTree = ""; - }; - BA4FD2A71372FAFA0025925C /* sar.tproj */ = { - isa = PBXGroup; - children = ( - BA4FD2A91372FAFA0025925C /* sar.1 */, - BA4FD2AA1372FAFA0025925C /* sar.c */, - BA4FD2AB1372FAFA0025925C /* sar.h */, - ); - path = sar.tproj; - sourceTree = ""; - }; BA4FD2AC1372FAFA0025925C /* sc_usage.tproj */ = { isa = PBXGroup; children = ( @@ -3636,7 +3869,6 @@ BA9B766313739C20001BB39F /* chkpasswd */, BA9B768C1373A0D8001BB39F /* chpass */, BA4B79CD1373A72800003422 /* dmesg */, - BA4B79D51373A97000003422 /* libdp_notify_lib.a */, BA4B79EC1373AF7A00003422 /* dynamic_pager */, BA4B7A051373B9E900003422 /* fs_usage */, BA4B7A161373BE9D00003422 /* getconf */, @@ -3645,7 +3877,6 @@ BA4B7A7113765D3E00003422 /* iostat */, BA4B7A9013765F3C00003422 /* latency */, BA473DB31377B2230005CC19 /* login */, - BACC1D091377B3E6007728F4 /* makekey */, BACC1D151377B481007728F4 /* mean */, BACC1D451377B6E2007728F4 /* mkfile */, BACC1D551377B7A7007728F4 /* newgrp */, @@ -3655,8 +3886,6 @@ BAE589E3137902F50049DD3B /* pwd_mkdb */, BAE589F01379044E0049DD3B /* reboot */, BAE58A1113799F610049DD3B /* sa */, - BAE58A2513799FFA0049DD3B /* sadc */, - BAE58A3D1379A3F60049DD3B /* sar */, BAE58A4E137D69A60049DD3B /* sc_usage */, BA91CE62137F42ED00AE5160 /* shutdown */, BA9BF492139680CF0018C7BB /* sync */, @@ -3676,16 +3905,43 @@ ADA9007717679A8C00161ADF /* purge */, 550C19EB1804D226001DA380 /* iosim */, B158E3A0185A836700474677 /* wordexp-helper */, - 1865513618CA6F41003B92A7 /* libCPPUtil.a */, - 1865517C18CA7104003B92A7 /* msa */, - 18597EC418CBC2A300531A50 /* kdprof */, - 18C8727F18EA114F00F86DD9 /* libKDBG.a */, 08DC48851A12C21B008AAF38 /* kpgo */, 97999D2D1AE84C0E00E8B10F /* lskq */, + 78DE9DE01B5045DE00FE6DF5 /* wait4path */, + C20D8C691C1A102F00C1226B /* gcore */, + 8EC391651C9733C2001E28E6 /* proc_uuid_policy */, ); name = Products; sourceTree = ""; }; + C21481371C1A11F0003BCA63 /* gcore.tproj */ = { + isa = PBXGroup; + children = ( + C214810D1C1A11E6003BCA63 /* corefile.c */, + C214810E1C1A11E6003BCA63 /* corefile.h */, + C214810F1C1A11E6003BCA63 /* dyld_shared_cache.c */, + C21481101C1A11E6003BCA63 /* dyld_shared_cache.h */, + C21481111C1A11E6003BCA63 /* dyld.c */, + C21481121C1A11E6003BCA63 /* dyld.h */, + C21481131C1A11E6003BCA63 /* gcore.1 */, + C21481141C1A11E6003BCA63 /* loader_additions.h */, + C21481151C1A11E6003BCA63 /* main.c */, + C21481161C1A11E6003BCA63 /* options.h */, + C21481171C1A11E6003BCA63 /* region.h */, + C21481181C1A11E6003BCA63 /* sparse.c */, + C21481191C1A11E6003BCA63 /* sparse.h */, + C214811A1C1A11E7003BCA63 /* threads.c */, + C214811B1C1A11E7003BCA63 /* threads.h */, + C214811C1C1A11E7003BCA63 /* utils.c */, + C214811D1C1A11E7003BCA63 /* utils.h */, + C214811E1C1A11E7003BCA63 /* vanilla.c */, + C214811F1C1A11E7003BCA63 /* vanilla.h */, + C21481201C1A11E7003BCA63 /* vm.c */, + C21481211C1A11E7003BCA63 /* vm.h */, + ); + name = gcore.tproj; + sourceTree = ""; + }; C625B28916D6F27E00168EF7 /* taskpolicy.tproj */ = { isa = PBXGroup; children = ( @@ -3711,75 +3967,6 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 1865513418CA6F41003B92A7 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 1865515E18CA70B5003B92A7 /* UtilAssert.hpp in Headers */, - 1865516818CA70B5003B92A7 /* UtilNanoInterval.hpp in Headers */, - 1865517518CA70B5003B92A7 /* UtilTimer.hpp in Headers */, - 1865516318CA70B5003B92A7 /* UtilLog.hpp in Headers */, - 1865515D18CA70B5003B92A7 /* UtilAbsTime.hpp in Headers */, - 1865516018CA70B5003B92A7 /* UtilException.hpp in Headers */, - 1865516E18CA70B5003B92A7 /* UtilPrettyPrinting.hpp in Headers */, - 1865516418CA70B5003B92A7 /* UtilMakeUnique.hpp in Headers */, - 1865515B18CA70B5003B92A7 /* UtilAbsInterval.hpp in Headers */, - 1865516118CA70B5003B92A7 /* UtilFileDescriptor.hpp in Headers */, - 1865517218CA70B5003B92A7 /* UtilTerminalColor.hpp in Headers */, - 1865517018CA70B5003B92A7 /* UtilString.hpp in Headers */, - 1865515918CA70B5003B92A7 /* CPPUtil.h in Headers */, - 1865516A18CA70B5003B92A7 /* UtilNanoTime.hpp in Headers */, - 1865517318CA70B5003B92A7 /* UtilTime.hpp in Headers */, - 1865516718CA70B5003B92A7 /* UtilMemoryBuffer.hpp in Headers */, - 1865517718CA70B5003B92A7 /* UtilTRangeValue.hpp in Headers */, - 1865516C18CA70B5003B92A7 /* UtilPath.hpp in Headers */, - 1865515F18CA70B5003B92A7 /* UtilBase.hpp in Headers */, - 1865516618CA70B5003B92A7 /* UtilMappedFile.hpp in Headers */, - 1865517618CA70B5003B92A7 /* UtilTRange.hpp in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18C8727D18EA114F00F86DD9 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 18C872BE18EA128B00F86DD9 /* MachineProcess.mutable-impl.hpp in Headers */, - 18C872AF18EA128B00F86DD9 /* KDebug.h in Headers */, - 18C872B918EA128B00F86DD9 /* MachineCPU.impl.hpp in Headers */, - 18C872BB18EA128B00F86DD9 /* MachineMachMsg.hpp in Headers */, - 18C872B118EA128B00F86DD9 /* KDState.hpp in Headers */, - 18C872AB18EA128B00F86DD9 /* IOActivity.hpp in Headers */, - 18C872C518EA128B00F86DD9 /* ProcessSummary.hpp in Headers */, - 18C872B818EA128B00F86DD9 /* MachineCPU.hpp in Headers */, - 18C872C018EA128B00F86DD9 /* MachineThread.impl.hpp in Headers */, - 18C872C918EA128B00F86DD9 /* TraceDataHeader.hpp in Headers */, - 188959FD1958D287004576E8 /* TaskRequestedPolicy.hpp in Headers */, - 18C872C118EA128B00F86DD9 /* MachineThread.mutable-impl.hpp in Headers */, - 18C872BA18EA128B00F86DD9 /* MachineCPU.mutable-impl.hpp in Headers */, - 18C872C418EA128B00F86DD9 /* NurseryMachMsg.hpp in Headers */, - 18C872B618EA128B00F86DD9 /* Machine.impl.hpp in Headers */, - 18C872B018EA128B00F86DD9 /* KDEvent.hpp in Headers */, - 18C872B718EA128B00F86DD9 /* Machine.mutable-impl.hpp in Headers */, - 1845E41718EB95810010F451 /* TraceFile.hpp in Headers */, - 18C872AE18EA128B00F86DD9 /* KDCPUMapEntry.hpp in Headers */, - 18C872BF18EA128B00F86DD9 /* MachineThread.hpp in Headers */, - 18C872BD18EA128B00F86DD9 /* MachineProcess.impl.hpp in Headers */, - 18C872B518EA128B00F86DD9 /* Machine.hpp in Headers */, - 18C872C818EA128B00F86DD9 /* TraceCodes.hpp in Headers */, - 18C872C218EA128B00F86DD9 /* MachineVoucher.hpp in Headers */, - 18C872BC18EA128B00F86DD9 /* MachineProcess.hpp in Headers */, - 18C872CA18EA128B00F86DD9 /* VoucherInterval.hpp in Headers */, - 18C872C618EA128B00F86DD9 /* ThreadSummary.hpp in Headers */, - 18C872AA18EA128B00F86DD9 /* CPUSummary.hpp in Headers */, - 18C872B218EA128B00F86DD9 /* KDThreadMapEntry.hpp in Headers */, - 18C872AD18EA128B00F86DD9 /* KDBG.hpp in Headers */, - 18C872A918EA128B00F86DD9 /* CPUActivity.hpp in Headers */, - 18D8B66619537115008847DF /* TaskEffectivePolicy.hpp in Headers */, - 18C872C318EA128B00F86DD9 /* MetaTypes.hpp in Headers */, - 18C872B418EA128B00F86DD9 /* Kernel.hpp in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; BA4FD3481373077C0025925C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -3859,137 +4046,99 @@ productReference = 1523FE631595048900661E82 /* ltop */; productType = "com.apple.product-type.tool"; }; - 18597EC318CBC2A300531A50 /* kdprof */ = { + 550C19E21804D226001DA380 /* iosim */ = { isa = PBXNativeTarget; - buildConfigurationList = 18597ECB18CBC2A300531A50 /* Build configuration list for PBXNativeTarget "kdprof" */; + buildConfigurationList = 550C19E91804D226001DA380 /* Build configuration list for PBXNativeTarget "iosim" */; buildPhases = ( - 18597EC018CBC2A300531A50 /* Sources */, - 18597EC118CBC2A300531A50 /* Frameworks */, - 18597EC218CBC2A300531A50 /* CopyFiles */, + 550C19E31804D226001DA380 /* Sources */, + 550C19E51804D226001DA380 /* Frameworks */, + 550C19E71804D226001DA380 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 18C872CE18EA1A6200F86DD9 /* PBXTargetDependency */, - 18597F1E18CBC3C900531A50 /* PBXTargetDependency */, ); - name = kdprof; - productName = kdprof; - productReference = 18597EC418CBC2A300531A50 /* kdprof */; + name = iosim; + productName = ac; + productReference = 550C19EB1804D226001DA380 /* iosim */; productType = "com.apple.product-type.tool"; }; - 1865513518CA6F41003B92A7 /* CPPUtil */ = { + 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */ = { isa = PBXNativeTarget; - buildConfigurationList = 1865513818CA6F42003B92A7 /* Build configuration list for PBXNativeTarget "CPPUtil" */; + buildConfigurationList = 55CCB17116B84EDA00B56979 /* Build configuration list for PBXNativeTarget "vm_purgeable_stat" */; buildPhases = ( - 1865513218CA6F41003B92A7 /* Sources */, - 1865513318CA6F41003B92A7 /* Frameworks */, - 1865513418CA6F41003B92A7 /* Headers */, + 55CCB16B16B84EDA00B56979 /* Sources */, + 55CCB16D16B84EDA00B56979 /* Frameworks */, + 55CCB16F16B84EDA00B56979 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = CPPUtil; - productName = CPPUtil; - productReference = 1865513618CA6F41003B92A7 /* libCPPUtil.a */; - productType = "com.apple.product-type.library.static"; + name = vm_purgeable_stat; + productName = ac; + productReference = 55CCB17316B84EDA00B56979 /* vm_purgeable_stat */; + productType = "com.apple.product-type.tool"; }; - 1865517B18CA7104003B92A7 /* msa */ = { + 78DE9DDF1B5045DE00FE6DF5 /* wait4path */ = { isa = PBXNativeTarget; - buildConfigurationList = 1865518218CA7104003B92A7 /* Build configuration list for PBXNativeTarget "msa" */; + buildConfigurationList = 78DE9DE41B5045DE00FE6DF5 /* Build configuration list for PBXNativeTarget "wait4path" */; buildPhases = ( - 1865517818CA7104003B92A7 /* Sources */, - 1865517918CA7104003B92A7 /* Frameworks */, - 1865517A18CA7104003B92A7 /* CopyFiles */, + 78DE9DDC1B5045DE00FE6DF5 /* Sources */, + 78DE9DDD1B5045DE00FE6DF5 /* Frameworks */, + 78DE9DDE1B5045DE00FE6DF5 /* CopyFiles */, ); buildRules = ( + 78DE9DFF1B504DB800FE6DF5 /* PBXBuildRule */, ); dependencies = ( - 1865518918CA7137003B92A7 /* PBXTargetDependency */, - 18C872D018EA1A6F00F86DD9 /* PBXTargetDependency */, ); - name = msa; - productName = msa; - productReference = 1865517C18CA7104003B92A7 /* msa */; + name = wait4path; + productName = wait4path; + productReference = 78DE9DE01B5045DE00FE6DF5 /* wait4path */; productType = "com.apple.product-type.tool"; }; - 18C8727E18EA114F00F86DD9 /* KDBG */ = { + 8EC3915B1C9733C2001E28E6 /* proc_uuid_policy */ = { isa = PBXNativeTarget; - buildConfigurationList = 18C8728218EA114F00F86DD9 /* Build configuration list for PBXNativeTarget "KDBG" */; + buildConfigurationList = 8EC391621C9733C2001E28E6 /* Build configuration list for PBXNativeTarget "proc_uuid_policy" */; buildPhases = ( - 18C8727B18EA114F00F86DD9 /* Sources */, - 18C8727C18EA114F00F86DD9 /* Frameworks */, - 18C8727D18EA114F00F86DD9 /* Headers */, + 8EC3915C1C9733C2001E28E6 /* Sources */, + 8EC3915E1C9733C2001E28E6 /* Frameworks */, + 8EC391601C9733C2001E28E6 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 18C8728418EA115D00F86DD9 /* PBXTargetDependency */, ); - name = KDBG; - productName = KDBG; - productReference = 18C8727F18EA114F00F86DD9 /* libKDBG.a */; - productType = "com.apple.product-type.library.static"; + name = proc_uuid_policy; + productName = ac; + productReference = 8EC391651C9733C2001E28E6 /* proc_uuid_policy */; + productType = "com.apple.product-type.tool"; }; - 550C19E21804D226001DA380 /* iosim */ = { + 97999D211AE84C0E00E8B10F /* lskq */ = { isa = PBXNativeTarget; - buildConfigurationList = 550C19E91804D226001DA380 /* Build configuration list for PBXNativeTarget "iosim" */; + buildConfigurationList = 97999D2A1AE84C0E00E8B10F /* Build configuration list for PBXNativeTarget "lskq" */; buildPhases = ( - 550C19E31804D226001DA380 /* Sources */, - 550C19E51804D226001DA380 /* Frameworks */, - 550C19E71804D226001DA380 /* CopyFiles */, + 97999D221AE84C0E00E8B10F /* Sources */, + 97999D261AE84C0E00E8B10F /* Frameworks */, + 97999D281AE84C0E00E8B10F /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = iosim; + name = lskq; productName = ac; - productReference = 550C19EB1804D226001DA380 /* iosim */; + productReference = 97999D2D1AE84C0E00E8B10F /* lskq */; productType = "com.apple.product-type.tool"; }; - 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */ = { + ADA9006F17679A8C00161ADF /* purge */ = { isa = PBXNativeTarget; - buildConfigurationList = 55CCB17116B84EDA00B56979 /* Build configuration list for PBXNativeTarget "vm_purgeable_stat" */; + buildConfigurationList = ADA9007517679A8C00161ADF /* Build configuration list for PBXNativeTarget "purge" */; buildPhases = ( - 55CCB16B16B84EDA00B56979 /* Sources */, - 55CCB16D16B84EDA00B56979 /* Frameworks */, - 55CCB16F16B84EDA00B56979 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = vm_purgeable_stat; - productName = ac; - 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" */; - buildPhases = ( - ADA9007017679A8C00161ADF /* Sources */, - ADA9007217679A8C00161ADF /* Frameworks */, - ADA9007317679A8C00161ADF /* CopyFiles */, + ADA9007017679A8C00161ADF /* Sources */, + ADA9007217679A8C00161ADF /* Frameworks */, + ADA9007317679A8C00161ADF /* CopyFiles */, ); buildRules = ( ); @@ -4085,23 +4234,6 @@ productReference = BA4B79CD1373A72800003422 /* dmesg */; productType = "com.apple.product-type.tool"; }; - BA4B79D41373A97000003422 /* dp_notify_lib */ = { - isa = PBXNativeTarget; - buildConfigurationList = BA4B79D61373A97000003422 /* Build configuration list for PBXNativeTarget "dp_notify_lib" */; - buildPhases = ( - BA4B79D11373A97000003422 /* Sources */, - BA4B79D21373A97000003422 /* Frameworks */, - BA4B79DF1373AB0900003422 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = dp_notify_lib; - productName = dp_notify_lib; - productReference = BA4B79D51373A97000003422 /* libdp_notify_lib.a */; - productType = "com.apple.product-type.library.static"; - }; BA4B79E01373AF7A00003422 /* dynamic_pager */ = { isa = PBXNativeTarget; buildConfigurationList = BA4B79EA1373AF7A00003422 /* Build configuration list for PBXNativeTarget "dynamic_pager" */; @@ -4507,23 +4639,6 @@ productReference = BA9BF4F7139684B40018C7BB /* zic */; productType = "com.apple.product-type.tool"; }; - BACC1D011377B3E6007728F4 /* makekey */ = { - isa = PBXNativeTarget; - buildConfigurationList = BACC1D071377B3E6007728F4 /* Build configuration list for PBXNativeTarget "makekey" */; - buildPhases = ( - BACC1D021377B3E6007728F4 /* Sources */, - BACC1D041377B3E6007728F4 /* Frameworks */, - BACC1D051377B3E6007728F4 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = makekey; - productName = ac; - productReference = BACC1D091377B3E6007728F4 /* makekey */; - productType = "com.apple.product-type.tool"; - }; BACC1D0D1377B481007728F4 /* mean */ = { isa = PBXNativeTarget; buildConfigurationList = BACC1D131377B481007728F4 /* Build configuration list for PBXNativeTarget "mean" */; @@ -4678,56 +4793,38 @@ productReference = BAE58A1113799F610049DD3B /* sa */; productType = "com.apple.product-type.tool"; }; - BAE58A1813799FFA0049DD3B /* sadc */ = { + BAE58A45137D69A60049DD3B /* sc_usage */ = { isa = PBXNativeTarget; - buildConfigurationList = BAE58A2313799FFA0049DD3B /* Build configuration list for PBXNativeTarget "sadc" */; + buildConfigurationList = BAE58A4C137D69A60049DD3B /* Build configuration list for PBXNativeTarget "sc_usage" */; buildPhases = ( - BAE58A1913799FFA0049DD3B /* Sources */, - BAE58A1F13799FFA0049DD3B /* Frameworks */, - BAE58A2013799FFA0049DD3B /* CopyFiles */, - BAE58A2213799FFA0049DD3B /* ShellScript */, + BAE58A46137D69A60049DD3B /* Sources */, + BAE58A48137D69A60049DD3B /* Frameworks */, + BAE58A4A137D69A60049DD3B /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = sadc; + name = sc_usage; productName = ac; - productReference = BAE58A2513799FFA0049DD3B /* sadc */; + productReference = BAE58A4E137D69A60049DD3B /* sc_usage */; productType = "com.apple.product-type.tool"; }; - BAE58A351379A3F60049DD3B /* sar */ = { + C20D8C681C1A102F00C1226B /* gcore */ = { isa = PBXNativeTarget; - buildConfigurationList = BAE58A3B1379A3F60049DD3B /* Build configuration list for PBXNativeTarget "sar" */; + buildConfigurationList = C20D8C6F1C1A102F00C1226B /* Build configuration list for PBXNativeTarget "gcore" */; buildPhases = ( - BAE58A361379A3F60049DD3B /* Sources */, - BAE58A381379A3F60049DD3B /* Frameworks */, - BAE58A391379A3F60049DD3B /* CopyFiles */, + C20D8C651C1A102F00C1226B /* Sources */, + C20D8C661C1A102F00C1226B /* Frameworks */, + C20D8C671C1A102F00C1226B /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = sar; - productName = ac; - productReference = BAE58A3D1379A3F60049DD3B /* sar */; - productType = "com.apple.product-type.tool"; - }; - BAE58A45137D69A60049DD3B /* sc_usage */ = { - isa = PBXNativeTarget; - buildConfigurationList = BAE58A4C137D69A60049DD3B /* Build configuration list for PBXNativeTarget "sc_usage" */; - buildPhases = ( - BAE58A46137D69A60049DD3B /* Sources */, - BAE58A48137D69A60049DD3B /* Frameworks */, - BAE58A4A137D69A60049DD3B /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = sc_usage; - productName = ac; - productReference = BAE58A4E137D69A60049DD3B /* sc_usage */; + name = gcore; + productName = gcore; + productReference = C20D8C691C1A102F00C1226B /* gcore */; productType = "com.apple.product-type.tool"; }; C625B28716D6F27E00168EF7 /* taskpolicy */ = { @@ -4774,6 +4871,189 @@ TargetAttributes = { 08DC48841A12C21B008AAF38 = { CreatedOnToolsVersion = 6.3; + ProvisioningStyle = Manual; + }; + 1523FE5A1595048900661E82 = { + ProvisioningStyle = Manual; + }; + 1812F18C1C8F923900F3DC9E = { + ProvisioningStyle = Manual; + }; + 550C19E21804D226001DA380 = { + ProvisioningStyle = Manual; + }; + 55CCB16A16B84EDA00B56979 = { + ProvisioningStyle = Manual; + }; + 78DE9DDF1B5045DE00FE6DF5 = { + CreatedOnToolsVersion = 7.0; + ProvisioningStyle = Manual; + }; + 8EC3915B1C9733C2001E28E6 = { + ProvisioningStyle = Manual; + }; + 97999D211AE84C0E00E8B10F = { + ProvisioningStyle = Manual; + }; + ADA9006F17679A8C00161ADF = { + ProvisioningStyle = Manual; + }; + B158E39F185A836700474677 = { + ProvisioningStyle = Manual; + }; + B3F0E6CC16E96FC2008FAD09 = { + ProvisioningStyle = Manual; + }; + BA0A860713968E8500D2272C = { + ProvisioningStyle = Manual; + }; + BA473DA01377B2230005CC19 = { + ProvisioningStyle = Manual; + }; + BA4B79C51373A72800003422 = { + ProvisioningStyle = Manual; + }; + BA4B79E01373AF7A00003422 = { + ProvisioningStyle = Manual; + }; + BA4B79FD1373B9E900003422 = { + ProvisioningStyle = Manual; + }; + BA4B7A0E1373BE9D00003422 = { + ProvisioningStyle = Manual; + }; + BA4B7A3F137648E100003422 = { + ProvisioningStyle = Manual; + }; + BA4B7A5D13765CC700003422 = { + ProvisioningStyle = Manual; + }; + BA4B7A6913765D3E00003422 = { + ProvisioningStyle = Manual; + }; + BA4B7A7D13765F3C00003422 = { + ProvisioningStyle = Manual; + }; + BA4FD2EE1372FB3D0025925C = { + ProvisioningStyle = Manual; + }; + BA4FD2FE1372FE4E0025925C = { + ProvisioningStyle = Manual; + }; + BA4FD3041372FFD80025925C = { + ProvisioningStyle = Manual; + }; + BA4FD31A137300ED0025925C = { + ProvisioningStyle = Manual; + }; + BA4FD32F137305DD0025925C = { + ProvisioningStyle = Manual; + }; + BA4FD3381373073E0025925C = { + ProvisioningStyle = Manual; + }; + BA91CE59137F42ED00AE5160 = { + ProvisioningStyle = Manual; + }; + BA959E7E13968C8E00CA9C60 = { + ProvisioningStyle = Manual; + }; + BA9B763913739ABE001BB39F = { + ProvisioningStyle = Manual; + }; + BA9B765513739C20001BB39F = { + ProvisioningStyle = Manual; + }; + BA9B76781373A0D8001BB39F = { + ProvisioningStyle = Manual; + }; + BA9B76991373A246001BB39F = { + ProvisioningStyle = Manual; + }; + BA9B76A11373A2A2001BB39F = { + ProvisioningStyle = Manual; + }; + BA9BF48A139680CF0018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4971396812D0018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4A5139681910018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4BE139682BA0018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4CA139682F80018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4D7139683580018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4E3139683EB0018C7BB = { + ProvisioningStyle = Manual; + }; + BA9BF4EF139684B40018C7BB = { + ProvisioningStyle = Manual; + }; + BAAEB39C13730D5C003EA7A9 = { + ProvisioningStyle = Manual; + }; + BAAEB3A513730DFA003EA7A9 = { + ProvisioningStyle = Manual; + }; + BAAEB3AC13730E1C003EA7A9 = { + ProvisioningStyle = Manual; + }; + BACC1D0D1377B481007728F4 = { + ProvisioningStyle = Manual; + }; + BACC1D181377B4C9007728F4 = { + ProvisioningStyle = Manual; + }; + BACC1D3D1377B6E2007728F4 = { + ProvisioningStyle = Manual; + }; + BACC1D491377B7A7007728F4 = { + ProvisioningStyle = Manual; + }; + BACC1D591377B85C007728F4 = { + ProvisioningStyle = Manual; + }; + BAE5899B137836A00049DD3B = { + ProvisioningStyle = Manual; + }; + BAE589AA137837130049DD3B = { + ProvisioningStyle = Manual; + }; + BAE589BA1378FCAA0049DD3B = { + ProvisioningStyle = Manual; + }; + BAE589DB137902F50049DD3B = { + ProvisioningStyle = Manual; + }; + BAE589E81379044E0049DD3B = { + ProvisioningStyle = Manual; + }; + BAE589F5137904DF0049DD3B = { + ProvisioningStyle = Manual; + }; + BAE58A0913799F610049DD3B = { + ProvisioningStyle = Manual; + }; + BAE58A45137D69A60049DD3B = { + ProvisioningStyle = Manual; + }; + C20D8C681C1A102F00C1226B = { + CreatedOnToolsVersion = 7.2; + ProvisioningStyle = Manual; + }; + C625B28716D6F27E00168EF7 = { + ProvisioningStyle = Manual; + }; + C96F50AE15BDCEC3008682F7 = { + ProvisioningStyle = Manual; }; }; }; @@ -4791,6 +5071,7 @@ targets = ( BA4FD2FE1372FE4E0025925C /* All_MacOSX */, BACC1D181377B4C9007728F4 /* All_iOS */, + 1812F18C1C8F923900F3DC9E /* All_Bridge */, BA4FD2EE1372FB3D0025925C /* ac */, BA4FD3041372FFD80025925C /* accton */, BA4FD31A137300ED0025925C /* arch */, @@ -4805,74 +5086,55 @@ BA9B76991373A246001BB39F /* chfn */, BA9B76A11373A2A2001BB39F /* chsh */, BA4B79C51373A72800003422 /* dmesg */, - BA4B79D41373A97000003422 /* dp_notify_lib */, BA4B79E01373AF7A00003422 /* dynamic_pager */, BA4B79FD1373B9E900003422 /* fs_usage */, + C20D8C681C1A102F00C1226B /* gcore */, BA4B7A0E1373BE9D00003422 /* getconf */, BA4B7A3F137648E100003422 /* getty */, BA4B7A5D13765CC700003422 /* hostinfo */, + 550C19E21804D226001DA380 /* iosim */, BA4B7A6913765D3E00003422 /* iostat */, + 08DC48841A12C21B008AAF38 /* kpgo */, BA4B7A7D13765F3C00003422 /* latency */, BA473DA01377B2230005CC19 /* login */, 97999D211AE84C0E00E8B10F /* lskq */, + C96F50AE15BDCEC3008682F7 /* lsmp */, 1523FE5A1595048900661E82 /* ltop */, - BACC1D011377B3E6007728F4 /* makekey */, BACC1D0D1377B481007728F4 /* mean */, + B3F0E6CC16E96FC2008FAD09 /* memory_pressure */, BACC1D3D1377B6E2007728F4 /* mkfile */, BACC1D491377B7A7007728F4 /* newgrp */, BACC1D591377B85C007728F4 /* nologin */, BAE5899B137836A00049DD3B /* nvram */, BAE589AA137837130049DD3B /* pagesize */, BAE589BA1378FCAA0049DD3B /* passwd */, + 8EC3915B1C9733C2001E28E6 /* proc_uuid_policy */, + ADA9006F17679A8C00161ADF /* purge */, BAE589DB137902F50049DD3B /* pwd_mkdb */, BAE589E81379044E0049DD3B /* reboot */, BAE589F5137904DF0049DD3B /* halt */, BAE58A0913799F610049DD3B /* sa */, - BAE58A1813799FFA0049DD3B /* sadc */, - BAE58A351379A3F60049DD3B /* sar */, BAE58A45137D69A60049DD3B /* sc_usage */, BA91CE59137F42ED00AE5160 /* shutdown */, BA9BF48A139680CF0018C7BB /* sync */, BA9BF4971396812D0018C7BB /* sysctl */, + C625B28716D6F27E00168EF7 /* taskpolicy */, BA9BF4A5139681910018C7BB /* trace */, BA9BF4BE139682BA0018C7BB /* vifs */, BA9BF4CA139682F80018C7BB /* vipw */, + 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */, BA9BF4D7139683580018C7BB /* vm_stat */, + 78DE9DDF1B5045DE00FE6DF5 /* wait4path */, B158E39F185A836700474677 /* wordexp-helper */, BA9BF4E3139683EB0018C7BB /* zdump */, BA9BF4EF139684B40018C7BB /* zic */, BA959E7E13968C8E00CA9C60 /* zoneinfo */, BA0A860713968E8500D2272C /* zprint */, - C96F50AE15BDCEC3008682F7 /* lsmp */, - 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */, - C625B28716D6F27E00168EF7 /* taskpolicy */, - B3F0E6CC16E96FC2008FAD09 /* memory_pressure */, - ADA9006F17679A8C00161ADF /* purge */, - 550C19E21804D226001DA380 /* iosim */, - 1865513518CA6F41003B92A7 /* CPPUtil */, - 18C8727E18EA114F00F86DD9 /* KDBG */, - 1865517B18CA7104003B92A7 /* msa */, - 18597EC318CBC2A300531A50 /* kdprof */, - 08DC48841A12C21B008AAF38 /* kpgo */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - BA4B79DF1373AB0900003422 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "set -x\nset -e\n\nmkdir -p \"${DSTROOT}/usr/local/include/mach\"\n\n# A better solution would be to create a header using all of the archs, but this works for now.\nset -- ${ARCHS}\narch=$1\n\ninstall -m 0644 \"${DERIVED_SOURCES_DIR}\"/\"${arch}\"/backing_store_triggers.h \"${DSTROOT}\"/usr/local/include/mach/backing_store_triggers.h\ninstall -m 0644 \"${DERIVED_SOURCES_DIR}\"/\"${arch}\"/backing_store_alertsServer.h \"${DSTROOT}\"/usr/local/include/mach/backing_store_alerts_server.h\n"; - showEnvVarsInLog = 0; - }; BA4B79F91373B6A400003422 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -4886,7 +5148,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = ". ${SRCROOT}/dynamic_pager.tproj/generate_plist.sh"; + shellScript = ". \"${SRCROOT}/dynamic_pager.tproj/generate_plist.sh\""; }; BA4B7A221373C01600003422 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -4909,7 +5171,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -x\nset -e\n\ni=0\n\nwhile [ $i -lt ${SCRIPT_INPUT_FILE_COUNT} ]; do\n INPUT=\"SCRIPT_INPUT_FILE_${i}\"\n OUTPUT=\"SCRIPT_OUTPUT_FILE_${i}\"\n LC_ALL=C awk -f \"${SRCROOT}/getconf.tproj/fake-gperf.awk\" ${!INPUT} > ${!OUTPUT}\n i=$(($i + 1))\ndone\n"; + shellScript = "set -x\nset -e\n\ni=0\n\nwhile [ $i -lt ${SCRIPT_INPUT_FILE_COUNT} ]; do\n INPUT=\"SCRIPT_INPUT_FILE_${i}\"\n OUTPUT=\"SCRIPT_OUTPUT_FILE_${i}\"\n LC_ALL=C awk -f \"${SRCROOT}/getconf.tproj/fake-gperf.awk\" \"${!INPUT}\" > \"${!OUTPUT}\"\n i=$(($i + 1))\ndone\n"; showEnvVarsInLog = 0; }; BA4B7A4A137648E100003422 /* ShellScript */ = { @@ -4925,7 +5187,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = ". ${SRCROOT}/getty.tproj/generate_plist.sh"; + shellScript = ". \"${SRCROOT}/getty.tproj/generate_plist.sh\""; }; BA4FD335137306050025925C /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -5136,24 +5398,6 @@ shellScript = "set -x\nset -e\n\nln -fhv \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\nmkdir -p \"${DSTROOT}/usr/share/man/man8\"\necho \".so man8/reboot.8\" > \"${DSTROOT}/usr/share/man/man8/halt.8\"\n"; showEnvVarsInLog = 0; }; - BAE58A2213799FFA0049DD3B /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/sadc.tproj/sa1.sh", - "$(SRCROOT)/sadc.tproj/sa2.sh", - ); - outputPaths = ( - "$(DSTROOT)/usr/lib/sa/sa1", - "$(DSTROOT)/usr/lib/sa/sa2", - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "set -x\nset -e\n\nmkdir -p \"${DSTROOT}/private/var/log/sa\"\nmkdir -p \"${DSTROOT}/usr/lib/sa\"\ninstall \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\ninstall \"${SCRIPT_INPUT_FILE_1}\" \"${SCRIPT_OUTPUT_FILE_1}\"\n"; - showEnvVarsInLog = 0; - }; FD0AA4911630C39500606589 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; @@ -5187,82 +5431,36 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 18597EC018CBC2A300531A50 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18597EEB18CBC35700531A50 /* EnableAction.cpp in Sources */, - 18597EF118CBC35700531A50 /* PrintStateAction.cpp in Sources */, - 18597EEE18CBC35700531A50 /* InitializeAction.cpp in Sources */, - 18597EEA18CBC35700531A50 /* DisableAction.cpp in Sources */, - 18597EE918CBC35700531A50 /* CollectAction.cpp in Sources */, - 18597EF518CBC35700531A50 /* SummaryPrinting.cpp in Sources */, - 18597EED18CBC35700531A50 /* Globals.cpp in Sources */, - 18597EEF18CBC35700531A50 /* kdprof.cpp in Sources */, - 18597EF418CBC35700531A50 /* SleepAction.cpp in Sources */, - 18597EF018CBC35700531A50 /* NoWrapAction.cpp in Sources */, - 18597EEC18CBC35700531A50 /* EventPrinting.cpp in Sources */, - 18597EF318CBC35700531A50 /* SaveTraceAction.cpp in Sources */, - 18597EF218CBC35700531A50 /* RemoveAction.cpp in Sources */, - 18597EF618CBC35700531A50 /* TraceFileAction.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1865513218CA6F41003B92A7 /* Sources */ = { + 550C19E31804D226001DA380 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1865516518CA70B5003B92A7 /* UtilMappedFile.cpp in Sources */, - 1865515A18CA70B5003B92A7 /* UtilAbsInterval.cpp in Sources */, - 1865516218CA70B5003B92A7 /* UtilLog.cpp in Sources */, - 1865517418CA70B5003B92A7 /* UtilTimer.cpp in Sources */, - 1865516918CA70B5003B92A7 /* UtilNanoTime.cpp in Sources */, - 1865516F18CA70B5003B92A7 /* UtilString.cpp in Sources */, - 1865517118CA70B5003B92A7 /* UtilTerminalColor.cpp in Sources */, - 1865516B18CA70B5003B92A7 /* UtilPath.cpp in Sources */, - 1865515C18CA70B5003B92A7 /* UtilAbsTime.cpp in Sources */, - 1865516D18CA70B5003B92A7 /* UtilPrettyPrinting.cpp in Sources */, + 550C19EC1804D281001DA380 /* iosim.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 1865517818CA7104003B92A7 /* Sources */ = { + 55CCB16B16B84EDA00B56979 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 185B9772191022B200FCB84C /* VoucherContentSysctl.cpp in Sources */, - 1865519E18CA72F7003B92A7 /* Printing.cpp in Sources */, - 1865519F18CA72F7003B92A7 /* ReadTraceFileAction.cpp in Sources */, - 1865519B18CA72F7003B92A7 /* Globals.cpp in Sources */, - 1865519C18CA72F7003B92A7 /* LiveTraceAction.cpp in Sources */, - 1865519D18CA72F7003B92A7 /* main.cpp in Sources */, - 185B97751910475500FCB84C /* WriteTraceFileAction.cpp in Sources */, + 55CCB17416B84EF800B56979 /* vm_purgeable_stat.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18C8727B18EA114F00F86DD9 /* Sources */ = { + 78DE9DDC1B5045DE00FE6DF5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 18C872C718EA128B00F86DD9 /* TraceCodes.cpp in Sources */, - 1845E41618EB95810010F451 /* TraceFile.cpp in Sources */, - 18C872B318EA128B00F86DD9 /* Kernel.cpp in Sources */, - 18C872AC18EA128B00F86DD9 /* KDBG.cpp in Sources */, + 78DE9E001B504DE500FE6DF5 /* wait4path.version in Sources */, + 78DE9DFE1B504D7F00FE6DF5 /* wait4path.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 550C19E31804D226001DA380 /* Sources */ = { + 8EC3915C1C9733C2001E28E6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 550C19EC1804D281001DA380 /* iosim.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 55CCB16B16B84EDA00B56979 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 55CCB17416B84EF800B56979 /* vm_purgeable_stat.c in Sources */, + 8EC391691C973405001E28E6 /* proc_uuid_policy.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5323,23 +5521,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BA4B79D11373A97000003422 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BA4B79D81373A99200003422 /* backing_store_alerts.defs in Sources */, - BA4B79D91373A99600003422 /* backing_store_triggers.defs in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; BA4B79E11373AF7A00003422 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BA4B79EE1373AFFA00003422 /* dynamic_pager.c in Sources */, - BA4B79EF1373B00300003422 /* backing_store_alerts.defs in Sources */, - BA4B79F01373B00300003422 /* backing_store_triggers.defs in Sources */, - BA4B79F11373B00300003422 /* default_pager_alerts.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5545,14 +5731,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BACC1D021377B3E6007728F4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BACC1D0B1377B413007728F4 /* makekey.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; BACC1D0E1377B481007728F4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -5605,144 +5783,324 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BAE589DC137902F50049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE589E5137903680049DD3B /* pw_scan.c in Sources */, - BAE589E6137903680049DD3B /* pwd_mkdb.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + BAE589DC137902F50049DD3B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BAE589E5137903680049DD3B /* pw_scan.c in Sources */, + BAE589E6137903680049DD3B /* pwd_mkdb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BAE589E91379044E0049DD3B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BAE589F3137904B90049DD3B /* reboot.c in Sources */, + BAE589F2137904B50049DD3B /* kextmanager.defs in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BAE58A0A13799F610049DD3B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BAE58A1313799F950049DD3B /* db.c in Sources */, + BAE58A1413799F980049DD3B /* main.c in Sources */, + BAE58A1513799F9B0049DD3B /* pdb.c in Sources */, + BAE58A1613799F9F0049DD3B /* usrdb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BAE58A46137D69A60049DD3B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BAE58A50137D69DA0049DD3B /* sc_usage.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C20D8C651C1A102F00C1226B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C214813D1C1A122B003BCA63 /* dyld.c in Sources */, + C214813B1C1A122B003BCA63 /* corefile.c in Sources */, + C214813A1C1A1219003BCA63 /* utils.c in Sources */, + C214813C1C1A122B003BCA63 /* dyld_shared_cache.c in Sources */, + C21481381C1A1213003BCA63 /* vm.c in Sources */, + C21481391C1A1216003BCA63 /* vanilla.c in Sources */, + C214813E1C1A122B003BCA63 /* main.c in Sources */, + C214813F1C1A122B003BCA63 /* sparse.c in Sources */, + C21481401C1A122B003BCA63 /* threads.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C625B28416D6F27E00168EF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C625B28B16D6F27E00168EF7 /* taskpolicy.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C96F50AF15BDCEC3008682F7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C96F50BE15BDFF03008682F7 /* lsmp.c in Sources */, + 72F9316D18C26A8600D804C5 /* port_details.c in Sources */, + 72D1FDD918C4140600C1E05F /* task_details.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* 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 */; + targetProxy = 1523FE6E1595069900661E82 /* PBXContainerItemProxy */; + }; + 1523FE711595069F00661E82 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1523FE5A1595048900661E82 /* ltop */; + targetProxy = 1523FE701595069F00661E82 /* PBXContainerItemProxy */; + }; + 1812F18D1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C20D8C681C1A102F00C1226B /* gcore */; + targetProxy = 1812F18E1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F18F1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 78DE9DDF1B5045DE00FE6DF5 /* wait4path */; + targetProxy = 1812F1901C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1911C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97999D211AE84C0E00E8B10F /* lskq */; + targetProxy = 1812F1921C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1931C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 08DC48841A12C21B008AAF38 /* kpgo */; + targetProxy = 1812F1941C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1991C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 550C19E21804D226001DA380 /* iosim */; + targetProxy = 1812F19A1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F19B1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = ADA9006F17679A8C00161ADF /* purge */; + targetProxy = 1812F19C1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F19D1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C625B28716D6F27E00168EF7 /* taskpolicy */; + targetProxy = 1812F19E1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F19F1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */; + targetProxy = 1812F1A01C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1A11C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C96F50AE15BDCEC3008682F7 /* lsmp */; + targetProxy = 1812F1A21C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1A31C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1523FE5A1595048900661E82 /* ltop */; + targetProxy = 1812F1A41C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1A51C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA959E7E13968C8E00CA9C60 /* zoneinfo */; + targetProxy = 1812F1A61C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1A71C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA0A860713968E8500D2272C /* zprint */; + targetProxy = 1812F1A81C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1A91C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4BE139682BA0018C7BB /* vifs */; + targetProxy = 1812F1AA1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1AB1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4CA139682F80018C7BB /* vipw */; + targetProxy = 1812F1AC1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1AD1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4D7139683580018C7BB /* vm_stat */; + targetProxy = 1812F1AE1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1AF1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4E3139683EB0018C7BB /* zdump */; + targetProxy = 1812F1B01C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1B11C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4EF139684B40018C7BB /* zic */; + targetProxy = 1812F1B21C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1B31C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF48A139680CF0018C7BB /* sync */; + targetProxy = 1812F1B41C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1B51C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4971396812D0018C7BB /* sysctl */; + targetProxy = 1812F1B61C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1B71C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA9BF4A5139681910018C7BB /* trace */; + targetProxy = 1812F1B81C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1B91C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE58A45137D69A60049DD3B /* sc_usage */; + targetProxy = 1812F1BA1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1BB1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE58A0913799F610049DD3B /* sa */; + targetProxy = 1812F1BC1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1BD1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE589DB137902F50049DD3B /* pwd_mkdb */; + targetProxy = 1812F1BE1C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1BF1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE589E81379044E0049DD3B /* reboot */; + targetProxy = 1812F1C01C8F923900F3DC9E /* PBXContainerItemProxy */; + }; + 1812F1C11C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE589F5137904DF0049DD3B /* halt */; + targetProxy = 1812F1C21C8F923900F3DC9E /* PBXContainerItemProxy */; }; - BAE589E91379044E0049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE589F3137904B90049DD3B /* reboot.c in Sources */, - BAE589F2137904B50049DD3B /* kextmanager.defs in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1C31C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE589BA1378FCAA0049DD3B /* passwd */; + targetProxy = 1812F1C41C8F923900F3DC9E /* PBXContainerItemProxy */; }; - BAE58A0A13799F610049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE58A1313799F950049DD3B /* db.c in Sources */, - BAE58A1413799F980049DD3B /* main.c in Sources */, - BAE58A1513799F9B0049DD3B /* pdb.c in Sources */, - BAE58A1613799F9F0049DD3B /* usrdb.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1C51C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE5899B137836A00049DD3B /* nvram */; + targetProxy = 1812F1C61C8F923900F3DC9E /* PBXContainerItemProxy */; }; - BAE58A1913799FFA0049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE58A271379A0590049DD3B /* sadc.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1C71C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BAE589AA137837130049DD3B /* pagesize */; + targetProxy = 1812F1C81C8F923900F3DC9E /* PBXContainerItemProxy */; }; - BAE58A361379A3F60049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE58A3F137A59140049DD3B /* sar.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1C91C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BACC1D3D1377B6E2007728F4 /* mkfile */; + targetProxy = 1812F1CA1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - BAE58A46137D69A60049DD3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BAE58A50137D69DA0049DD3B /* sc_usage.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1CB1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BACC1D491377B7A7007728F4 /* newgrp */; + targetProxy = 1812F1CC1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - C625B28416D6F27E00168EF7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C625B28B16D6F27E00168EF7 /* taskpolicy.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1CD1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BACC1D591377B85C007728F4 /* nologin */; + targetProxy = 1812F1CE1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - C96F50AF15BDCEC3008682F7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C96F50BE15BDFF03008682F7 /* lsmp.c in Sources */, - 72F9316D18C26A8600D804C5 /* port_details.c in Sources */, - 72D1FDD918C4140600C1E05F /* task_details.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; + 1812F1CF1C8F923900F3DC9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA4FD2EE1372FB3D0025925C /* ac */; + targetProxy = 1812F1D01C8F923900F3DC9E /* PBXContainerItemProxy */; }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 08DC48901A12C6F0008AAF38 /* PBXTargetDependency */ = { + 1812F1D11C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 08DC48841A12C21B008AAF38 /* kpgo */; - targetProxy = 08DC488F1A12C6F0008AAF38 /* PBXContainerItemProxy */; + target = BA4FD3041372FFD80025925C /* accton */; + targetProxy = 1812F1D21C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 08DC48921A12C6FA008AAF38 /* PBXTargetDependency */ = { + 1812F1D31C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 08DC48841A12C21B008AAF38 /* kpgo */; - targetProxy = 08DC48911A12C6FA008AAF38 /* PBXContainerItemProxy */; + target = BA4FD31A137300ED0025925C /* arch */; + targetProxy = 1812F1D41C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 1523FE6F1595069900661E82 /* PBXTargetDependency */ = { + 1812F1D51C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1523FE5A1595048900661E82 /* ltop */; - targetProxy = 1523FE6E1595069900661E82 /* PBXContainerItemProxy */; + target = BA4FD32F137305DD0025925C /* machine */; + targetProxy = 1812F1D61C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 1523FE711595069F00661E82 /* PBXTargetDependency */ = { + 1812F1D71C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1523FE5A1595048900661E82 /* ltop */; - targetProxy = 1523FE701595069F00661E82 /* PBXContainerItemProxy */; + target = BA4B79C51373A72800003422 /* dmesg */; + targetProxy = 1812F1D81C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18597F1A18CBC3B000531A50 /* PBXTargetDependency */ = { + 1812F1D91C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18597EC318CBC2A300531A50 /* kdprof */; - targetProxy = 18597F1918CBC3B000531A50 /* PBXContainerItemProxy */; + target = BA4B79E01373AF7A00003422 /* dynamic_pager */; + targetProxy = 1812F1DA1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18597F1C18CBC3B900531A50 /* PBXTargetDependency */ = { + 1812F1DB1C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18597EC318CBC2A300531A50 /* kdprof */; - targetProxy = 18597F1B18CBC3B900531A50 /* PBXContainerItemProxy */; + target = BA4B79FD1373B9E900003422 /* fs_usage */; + targetProxy = 1812F1DC1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18597F1E18CBC3C900531A50 /* PBXTargetDependency */ = { + 1812F1DD1C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1865513518CA6F41003B92A7 /* CPPUtil */; - targetProxy = 18597F1D18CBC3C900531A50 /* PBXContainerItemProxy */; + target = BA4B7A0E1373BE9D00003422 /* getconf */; + targetProxy = 1812F1DE1C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 1865518918CA7137003B92A7 /* PBXTargetDependency */ = { + 1812F1DF1C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1865513518CA6F41003B92A7 /* CPPUtil */; - targetProxy = 1865518818CA7137003B92A7 /* PBXContainerItemProxy */; + target = BA4B7A3F137648E100003422 /* getty */; + targetProxy = 1812F1E01C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 1865518B18CA7151003B92A7 /* PBXTargetDependency */ = { + 1812F1E11C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1865517B18CA7104003B92A7 /* msa */; - targetProxy = 1865518A18CA7151003B92A7 /* PBXContainerItemProxy */; + target = BA4B7A5D13765CC700003422 /* hostinfo */; + targetProxy = 1812F1E21C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 186551D018CA8154003B92A7 /* PBXTargetDependency */ = { + 1812F1E31C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1865517B18CA7104003B92A7 /* msa */; - targetProxy = 186551CF18CA8154003B92A7 /* PBXContainerItemProxy */; + target = BA4B7A6913765D3E00003422 /* iostat */; + targetProxy = 1812F1E41C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18C8728418EA115D00F86DD9 /* PBXTargetDependency */ = { + 1812F1E51C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1865513518CA6F41003B92A7 /* CPPUtil */; - targetProxy = 18C8728318EA115D00F86DD9 /* PBXContainerItemProxy */; + target = BA4B7A7D13765F3C00003422 /* latency */; + targetProxy = 1812F1E61C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18C872CE18EA1A6200F86DD9 /* PBXTargetDependency */ = { + 1812F1E71C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18C8727E18EA114F00F86DD9 /* KDBG */; - targetProxy = 18C872CD18EA1A6200F86DD9 /* PBXContainerItemProxy */; + target = BA473DA01377B2230005CC19 /* login */; + targetProxy = 1812F1E81C8F923900F3DC9E /* PBXContainerItemProxy */; }; - 18C872D018EA1A6F00F86DD9 /* PBXTargetDependency */ = { + 1812F1EB1C8F923900F3DC9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18C8727E18EA114F00F86DD9 /* KDBG */; - targetProxy = 18C872CF18EA1A6F00F86DD9 /* PBXContainerItemProxy */; + target = BACC1D0D1377B481007728F4 /* mean */; + targetProxy = 1812F1EC1C8F923900F3DC9E /* PBXContainerItemProxy */; }; 550C19EF1804D2AD001DA380 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -5764,6 +6122,21 @@ target = 55CCB16A16B84EDA00B56979 /* vm_purgeable_stat */; targetProxy = 55CCB17916B851F300B56979 /* PBXContainerItemProxy */; }; + 78DE9DED1B5048D400FE6DF5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 78DE9DDF1B5045DE00FE6DF5 /* wait4path */; + targetProxy = 78DE9DEC1B5048D400FE6DF5 /* PBXContainerItemProxy */; + }; + 78DE9DFA1B504D1200FE6DF5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 78DE9DDF1B5045DE00FE6DF5 /* wait4path */; + targetProxy = 78DE9DF91B504D1200FE6DF5 /* PBXContainerItemProxy */; + }; + 8EC3916E1C973440001E28E6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8EC3915B1C9733C2001E28E6 /* proc_uuid_policy */; + targetProxy = 8EC3916D1C973440001E28E6 /* PBXContainerItemProxy */; + }; 97999D351AE84D3A00E8B10F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 97999D211AE84C0E00E8B10F /* lskq */; @@ -5819,11 +6192,6 @@ target = BA4B79C51373A72800003422 /* dmesg */; targetProxy = BA4B79DA1373A9CE00003422 /* PBXContainerItemProxy */; }; - BA4B79DD1373A9CE00003422 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BA4B79D41373A97000003422 /* dp_notify_lib */; - targetProxy = BA4B79DC1373A9CE00003422 /* PBXContainerItemProxy */; - }; BA4B79F81373B06B00003422 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BA4B79E01373AF7A00003422 /* dynamic_pager */; @@ -6069,11 +6437,6 @@ target = BA4B79C51373A72800003422 /* dmesg */; targetProxy = BACC1D231377B58A007728F4 /* PBXContainerItemProxy */; }; - BACC1D261377B58A007728F4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BA4B79D41373A97000003422 /* dp_notify_lib */; - targetProxy = BACC1D251377B58A007728F4 /* PBXContainerItemProxy */; - }; BACC1D281377B58A007728F4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BA4B79E01373AF7A00003422 /* dynamic_pager */; @@ -6114,21 +6477,11 @@ target = BA473DA01377B2230005CC19 /* login */; targetProxy = BACC1D351377B58A007728F4 /* PBXContainerItemProxy */; }; - BACC1D381377B58A007728F4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BACC1D011377B3E6007728F4 /* makekey */; - targetProxy = BACC1D371377B58A007728F4 /* PBXContainerItemProxy */; - }; BACC1D3A1377B58A007728F4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BACC1D0D1377B481007728F4 /* mean */; targetProxy = BACC1D391377B58A007728F4 /* PBXContainerItemProxy */; }; - BACC1D3C1377B5D9007728F4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BACC1D011377B3E6007728F4 /* makekey */; - targetProxy = BACC1D3B1377B5D9007728F4 /* PBXContainerItemProxy */; - }; BACC1D681377B8DC007728F4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BACC1D3D1377B6E2007728F4 /* mkfile */; @@ -6229,31 +6582,11 @@ target = BAE58A0913799F610049DD3B /* sa */; targetProxy = BAE58A2D1379A1260049DD3B /* PBXContainerItemProxy */; }; - BAE58A301379A1260049DD3B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BAE58A1813799FFA0049DD3B /* sadc */; - targetProxy = BAE58A2F1379A1260049DD3B /* PBXContainerItemProxy */; - }; BAE58A321379A1300049DD3B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BAE58A0913799F610049DD3B /* sa */; targetProxy = BAE58A311379A1300049DD3B /* PBXContainerItemProxy */; }; - BAE58A341379A1300049DD3B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BAE58A1813799FFA0049DD3B /* sadc */; - targetProxy = BAE58A331379A1300049DD3B /* PBXContainerItemProxy */; - }; - BAE58A42137A59300049DD3B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BAE58A351379A3F60049DD3B /* sar */; - targetProxy = BAE58A41137A59300049DD3B /* PBXContainerItemProxy */; - }; - BAE58A44137A59390049DD3B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BAE58A351379A3F60049DD3B /* sar */; - targetProxy = BAE58A43137A59390049DD3B /* PBXContainerItemProxy */; - }; BAE58A54137D69FB0049DD3B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BAE58A45137D69A60049DD3B /* sc_usage */; @@ -6264,6 +6597,16 @@ target = BAE58A45137D69A60049DD3B /* sc_usage */; targetProxy = BAE58A55137D6A050049DD3B /* PBXContainerItemProxy */; }; + C21481471C1A1447003BCA63 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C20D8C681C1A102F00C1226B /* gcore */; + targetProxy = C21481461C1A1447003BCA63 /* PBXContainerItemProxy */; + }; + C21481491C1A14AD003BCA63 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C20D8C681C1A102F00C1226B /* gcore */; + targetProxy = C21481481C1A14AD003BCA63 /* PBXContainerItemProxy */; + }; C625B29116D6F38700168EF7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C625B28716D6F27E00168EF7 /* taskpolicy */; @@ -6380,121 +6723,19 @@ }; name = Release; }; - 18597ECA18CBC2A300531A50 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NDEBUG=1", - "NS_BLOCK_ASSERTIONS=1", - ); - 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/OSX10.10.xctoolchain/usr/include, - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; - }; - name = Release; - }; - 1865513718CA6F42003B92A7 /* Release */ = { + 1812F1F01C8F923900F3DC9E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_NS_ASSERTIONS = NO; - EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NS_BLOCK_ASSERTIONS=1", - "NDEBUG=1", - ); - 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; - KEEP_PRIVATE_EXTERNS = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/CPPUtil; PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/CPPUtil; - SDKROOT = macosx.internal; - STRIP_INSTALLED_PRODUCT = NO; }; name = Release; }; - 1865518318CA7104003B92A7 /* Release */ = { + 1812F1F11C8F923900F3DC9E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NDEBUG=1", - "NS_BLOCK_ASSERTIONS=1", - ); - 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/OSX10.10.xctoolchain/usr/include, - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; }; - name = Release; + name = Debug; }; 18732FE218CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; @@ -6503,11 +6744,12 @@ DEBUG_INFORMATION_FORMAT = dwarf; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; - GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos"; + SUPPORTED_PLATFORMS = "macosx watchos iphoneos"; WARNING_CFLAGS = ( "-Wall", "-Wcast-align", @@ -6654,15 +6896,6 @@ }; name = Debug; }; - 18732FF318CBD4A700275344 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - OTHER_MIGFLAGS = "-R -untyped -DNO_DIRECT_RPC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; 18732FF418CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -6680,12 +6913,17 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); INSTALL_PATH = /usr/bin; PRODUCT_NAME = fs_usage; + VALID_ARCHS = "$(ARCHS_STANDARD)"; }; name = Debug; }; @@ -6770,14 +7008,6 @@ }; name = Debug; }; - 18732FFD18CBD4A700275344 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INSTALL_PATH = /usr/libexec; - PRODUCT_NAME = makekey; - }; - name = Debug; - }; 18732FFE18CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -6881,27 +7111,6 @@ }; name = Debug; }; - 1873300918CBD4A700275344 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INSTALL_MODE_FLAG = "u+s,a+rx,a-w"; - INSTALL_PATH = /usr/lib/sa; - PRODUCT_NAME = sadc; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=deprecated-declarations", - ); - }; - name = Debug; - }; - 1873300A18CBD4A700275344 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INSTALL_PATH = /usr/bin; - PRODUCT_NAME = sar; - }; - name = Debug; - }; 1873300B18CBD4A700275344 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7015,6 +7224,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); HEADER_SEARCH_PATHS = ( "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders/mach", @@ -7086,224 +7296,201 @@ INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = iosim; }; - name = Debug; + name = Debug; + }; + 550C19EA1804D226001DA380 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = iosim; + }; + name = Release; }; - 1873301E18CBD4A700275344 /* Debug */ = { + 55CCB17216B84EDA00B56979 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - 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; - KEEP_PRIVATE_EXTERNS = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/CPPUtil; - PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/CPPUtil; - SDKROOT = macosx.internal; - STRIP_INSTALLED_PRODUCT = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = vm_purgeable_stat; }; - name = Debug; + name = Release; }; - 1873301F18CBD4A700275344 /* Debug */ = { + 78DE9DE51B5045DE00FE6DF5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_INT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - GCC_SYMBOLS_PRIVATE_EXTERN = NO; + DARWIN_BUNDLE_IDENTIFIER = "\"com.apple.system_cmds.wait4path\""; + DARWIN_COPYRIGHT = "\"Copyright 2013 Apple Inc. All rights reserved.\""; + DARWIN_DISPLAY_NAME = "\"Darwin Filesystem Path Waiter\""; + DARWIN_DISPLAY_VERSION = "\"1.0.0\""; + DARWIN_INCREMENTAL_VERSION = "\"$CURRENT_PROJECT_VERSION\""; + DARWIN_VARIANT = RELEASE; + DARWIN_VARIANT_LOWER = "$(DARWIN_VARIANT_LOWER_$(DARWIN_VARIANT))"; + DARWIN_VARIANT_LOWER_DEBUG = debug; + DARWIN_VARIANT_LOWER_DEVELOPMENT = development; + DARWIN_VARIANT_LOWER_RELEASE = release; + DARWIN_VARIANT_SUFFIX = "$(DARWIN_VARIANT_SUFFIX_$(DARWIN_VARIANT))"; + DARWIN_VARIANT_SUFFIX_DEBUG = .debug; + DARWIN_VARIANT_SUFFIX_DEVELOPMENT = .development; + DARWIN_VARIANT_SUFFIX_RELEASE = ""; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; 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/OSX10.10.xctoolchain/usr/include, - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; + INSTALLED_PRODUCT_ASIDES = YES; + INSTALL_PATH = /bin; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + New_Setting14GCC_ENABLE_OBJC_GC = unsupported; + PRODUCT_NAME = wait4path; + SDKROOT = macosx; + STRIP_INSTALLED_PRODUCT_debug = NO; + USE_HEADERMAP = NO; + WANTS_GET_TASK_ALLOW = NO; + XPC_ALL_THE_DEBUGS2 = ""; + XPC_ALL_THE_DEBUGS2_yes = "-O0 -g -fno-inline -fno-limit-debug-info"; + XPC_BUILD_EXPORT_DEFAULTS = "-DXPC_PROJECT_EXPORT=XPC_EXPORT -DXPC_DEBUGEXPORT=XPC_NOEXPORT -DXPC_TESTEXPORT=XPC_NOEXPORT"; + XPC_BUILD_FILES_DIR = "$(PROJECT_DIR)/xcfiles"; + XPC_BUILD_HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(PROJECT_DIR)/src $(PROJECT_DIR)/interface $(PROJECT_DIR)/launch $(PROJECT_DIR)/support $(PROJECT_DIR)/development $(PROJECT_DIR)"; + XPC_BUILD_HOST = currentmajor; + XPC_BUILD_OTHER_CFLAGS = "$(XPC_ALL_THE_DEBUGS2_$(XPC_ALL_THE_DEBUGS)) $(XPC_COMPATIBILITY_DEFINES_$(XPC_BUILD_HOST)) -D__XPC_PROJECT_BUILD__=1"; + XPC_BUILD_XCCONFIG_DIR = "$(PROJECT_DIR)/xcconfig"; + XPC_BUILD_XCSCRIPTS_DIR = "$(PROJECT_DIR)/xcscripts"; + XPC_COMPATIBILITY_DEFINES_currentmajor = "-DHAVE_KDEBUG_TRACE=1 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=0 -DHAVE_GALARCH_AVAILABILITY=1"; + XPC_COMPATIBILITY_DEFINES_lastmajor = "-DHAVE_KDEBUG_TRACE=0 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=1 -DHAVE_GALARCH_AVAILABILITY=0"; + XPC_CRASHREPORTCLIENT_LDFLAGS = "-lCrashReporterClient"; + XPC_EXECUTABLE_OTHER_CFLAGS = "$(XPC_BUILD_OTHER_CFLAGS) $(XPC_BUILD_EXPORT_DEFAULTS) -DXPC_BUILD_TARGET_EXECUTABLE=1"; + XPC_EXECUTABLE_OTHER_LDFLAGS = "$(XPC_EXECUTABLE_WORKAROUND_14483011) $(XPC_CRASHREPORTCLIENT_LDFLAGS)"; + XPC_EXECUTABLE_WORKAROUND_14483011 = "-lSystem -lobjc"; + XPC_NOSTRIP = no; + XPC_NOSTRIP2_no = YES; + XPC_NOSTRIP2_yes = NO; }; - name = Debug; + name = Release; }; - 1873302018CBD4A700275344 /* Debug */ = { + 78DE9DE61B5045DE00FE6DF5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_INT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)"; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - GCC_SYMBOLS_PRIVATE_EXTERN = NO; + DARWIN_BUNDLE_IDENTIFIER = "\"com.apple.system_cmds.wait4path\""; + DARWIN_COPYRIGHT = "\"Copyright 2013 Apple Inc. All rights reserved.\""; + DARWIN_DISPLAY_NAME = "\"Darwin Filesystem Path Waiter\""; + DARWIN_DISPLAY_VERSION = "\"1.0.0\""; + DARWIN_INCREMENTAL_VERSION = "\"$CURRENT_PROJECT_VERSION\""; + DARWIN_VARIANT = RELEASE; + DARWIN_VARIANT_LOWER = "$(DARWIN_VARIANT_LOWER_$(DARWIN_VARIANT))"; + DARWIN_VARIANT_LOWER_DEBUG = debug; + DARWIN_VARIANT_LOWER_DEVELOPMENT = development; + DARWIN_VARIANT_LOWER_RELEASE = release; + DARWIN_VARIANT_SUFFIX = "$(DARWIN_VARIANT_SUFFIX_$(DARWIN_VARIANT))"; + DARWIN_VARIANT_SUFFIX_DEBUG = .debug; + DARWIN_VARIANT_SUFFIX_DEVELOPMENT = .development; + DARWIN_VARIANT_SUFFIX_RELEASE = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ""; 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/OSX10.10.xctoolchain/usr/include, - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; + INSTALLED_PRODUCT_ASIDES = YES; + INSTALL_PATH = /bin; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + New_Setting14GCC_ENABLE_OBJC_GC = unsupported; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = wait4path; + SDKROOT = macosx; + STRIP_INSTALLED_PRODUCT_debug = NO; + USE_HEADERMAP = NO; + WANTS_GET_TASK_ALLOW = NO; + XPC_ALL_THE_DEBUGS2 = ""; + XPC_ALL_THE_DEBUGS2_yes = "-O0 -g -fno-inline -fno-limit-debug-info"; + XPC_BUILD_EXPORT_DEFAULTS = "-DXPC_PROJECT_EXPORT=XPC_EXPORT -DXPC_DEBUGEXPORT=XPC_NOEXPORT -DXPC_TESTEXPORT=XPC_NOEXPORT"; + XPC_BUILD_FILES_DIR = "$(PROJECT_DIR)/xcfiles"; + XPC_BUILD_HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(PROJECT_DIR)/src $(PROJECT_DIR)/interface $(PROJECT_DIR)/launch $(PROJECT_DIR)/support $(PROJECT_DIR)/development $(PROJECT_DIR)"; + XPC_BUILD_HOST = currentmajor; + XPC_BUILD_OTHER_CFLAGS = "$(XPC_ALL_THE_DEBUGS2_$(XPC_ALL_THE_DEBUGS)) $(XPC_COMPATIBILITY_DEFINES_$(XPC_BUILD_HOST)) -D__XPC_PROJECT_BUILD__=1"; + XPC_BUILD_XCCONFIG_DIR = "$(PROJECT_DIR)/xcconfig"; + XPC_BUILD_XCSCRIPTS_DIR = "$(PROJECT_DIR)/xcscripts"; + XPC_COMPATIBILITY_DEFINES_currentmajor = "-DHAVE_KDEBUG_TRACE=1 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=0 -DHAVE_GALARCH_AVAILABILITY=1"; + XPC_COMPATIBILITY_DEFINES_lastmajor = "-DHAVE_KDEBUG_TRACE=0 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=1 -DHAVE_GALARCH_AVAILABILITY=0"; + XPC_CRASHREPORTCLIENT_LDFLAGS = "-lCrashReporterClient"; + XPC_EXECUTABLE_OTHER_CFLAGS = "$(XPC_BUILD_OTHER_CFLAGS) $(XPC_BUILD_EXPORT_DEFAULTS) -DXPC_BUILD_TARGET_EXECUTABLE=1"; + XPC_EXECUTABLE_OTHER_LDFLAGS = "$(XPC_EXECUTABLE_WORKAROUND_14483011) $(XPC_CRASHREPORTCLIENT_LDFLAGS)"; + XPC_EXECUTABLE_WORKAROUND_14483011 = "-lSystem -lobjc"; + XPC_NOSTRIP = no; + XPC_NOSTRIP2_no = YES; + XPC_NOSTRIP2_yes = NO; }; name = Debug; }; - 18C8728018EA114F00F86DD9 /* Release */ = { + 8EC391631C9733C2001E28E6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - AXLE_ENABLE_DEBUG_INFO = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_ASSIGN_ENUM = 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_NS_ASSERTIONS = NO; - EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NDEBUG=1", - "NS_BLOCK_ASSERTIONS=1", - ); - 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; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); - KEEP_PRIVATE_EXTERNS = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/KDBG; + INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/KDBG; - SDKROOT = macosx.internal; - STRIP_INSTALLED_PRODUCT = NO; }; name = Release; }; - 18C8728118EA114F00F86DD9 /* Debug */ = { + 8EC391641C9733C2001E28E6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - AXLE_ENABLE_DEBUG_INFO = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_ASSIGN_ENUM = 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - 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; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); - KEEP_PRIVATE_EXTERNS = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/KDBG; + INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = "$(TARGET_NAME)"; - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/KDBG; - SDKROOT = macosx.internal; - STRIP_INSTALLED_PRODUCT = NO; }; name = Debug; }; - 550C19EA1804D226001DA380 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = ""; - INSTALL_PATH = /usr/local/bin; - PRODUCT_NAME = iosim; - }; - name = Release; - }; - 55CCB17216B84EDA00B56979 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = ""; - INSTALL_PATH = /usr/local/bin; - PRODUCT_NAME = vm_purgeable_stat; - }; - name = Release; - }; 97999D2B1AE84C0E00E8B10F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7360,6 +7547,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); HEADER_SEARCH_PATHS = ( "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders/mach", @@ -7378,9 +7566,10 @@ GCC_DYNAMIC_NO_PIC = NO; GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos"; + SUPPORTED_PLATFORMS = "macosx watchos iphoneos"; WARNING_CFLAGS = ( "-Wall", "-Wcast-align", @@ -7414,15 +7603,6 @@ }; name = Release; }; - BA4B79D71373A97000003422 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - OTHER_MIGFLAGS = "-R -untyped -DNO_DIRECT_RPC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; BA4B79EB1373AF7A00003422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7440,12 +7620,17 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); INSTALL_PATH = /usr/bin; PRODUCT_NAME = fs_usage; + VALID_ARCHS = "$(ARCHS_STANDARD)"; }; name = Release; }; @@ -7708,14 +7893,6 @@ }; name = Release; }; - BACC1D081377B3E6007728F4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INSTALL_PATH = /usr/libexec; - PRODUCT_NAME = makekey; - }; - name = Release; - }; BACC1D141377B481007728F4 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7826,39 +8003,86 @@ }; name = Release; }; - BAE58A2413799FFA0049DD3B /* Release */ = { + BAE58A4D137D69A60049DD3B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - INSTALL_MODE_FLAG = "u+s,a+rx,a-w"; - INSTALL_PATH = /usr/lib/sa; - PRODUCT_NAME = sadc; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=deprecated-declarations", + GCC_TREAT_WARNINGS_AS_ERRORS = NO; + HEADER_SEARCH_PATHS = ( + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", + "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", ); + INSTALL_PATH = /usr/bin; + PRODUCT_NAME = sc_usage; }; name = Release; }; - BAE58A3C1379A3F60049DD3B /* Release */ = { + C20D8C6D1C1A102F00C1226B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; + FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - PRODUCT_NAME = sar; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - BAE58A4D137D69A60049DD3B /* Release */ = { + C20D8C6E1C1A102F00C1226B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_TREAT_WARNINGS_AS_ERRORS = NO; - HEADER_SEARCH_PATHS = ( - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; + FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework/PrivateHeaders"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", ); + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - PRODUCT_NAME = sc_usage; + PRODUCT_NAME = "$(TARGET_NAME)"; }; - name = Release; + name = Debug; }; C625B28E16D6F27E00168EF7 /* Release */ = { isa = XCBuildConfiguration; @@ -7902,56 +8126,47 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18597ECB18CBC2A300531A50 /* Build configuration list for PBXNativeTarget "kdprof" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18597ECA18CBC2A300531A50 /* Release */, - 1873302018CBD4A700275344 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1865513818CA6F42003B92A7 /* Build configuration list for PBXNativeTarget "CPPUtil" */ = { + 1812F1EF1C8F923900F3DC9E /* Build configuration list for PBXAggregateTarget "All_Bridge" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1865513718CA6F42003B92A7 /* Release */, - 1873301E18CBD4A700275344 /* Debug */, + 1812F1F01C8F923900F3DC9E /* Release */, + 1812F1F11C8F923900F3DC9E /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1865518218CA7104003B92A7 /* Build configuration list for PBXNativeTarget "msa" */ = { + 550C19E91804D226001DA380 /* Build configuration list for PBXNativeTarget "iosim" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1865518318CA7104003B92A7 /* Release */, - 1873301F18CBD4A700275344 /* Debug */, + 550C19EA1804D226001DA380 /* Release */, + 1873301D18CBD4A700275344 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18C8728218EA114F00F86DD9 /* Build configuration list for PBXNativeTarget "KDBG" */ = { + 55CCB17116B84EDA00B56979 /* Build configuration list for PBXNativeTarget "vm_purgeable_stat" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18C8728018EA114F00F86DD9 /* Release */, - 18C8728118EA114F00F86DD9 /* Debug */, + 55CCB17216B84EDA00B56979 /* Release */, + 1873301918CBD4A700275344 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 550C19E91804D226001DA380 /* Build configuration list for PBXNativeTarget "iosim" */ = { + 78DE9DE41B5045DE00FE6DF5 /* Build configuration list for PBXNativeTarget "wait4path" */ = { isa = XCConfigurationList; buildConfigurations = ( - 550C19EA1804D226001DA380 /* Release */, - 1873301D18CBD4A700275344 /* Debug */, + 78DE9DE51B5045DE00FE6DF5 /* Release */, + 78DE9DE61B5045DE00FE6DF5 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 55CCB17116B84EDA00B56979 /* Build configuration list for PBXNativeTarget "vm_purgeable_stat" */ = { + 8EC391621C9733C2001E28E6 /* Build configuration list for PBXNativeTarget "proc_uuid_policy" */ = { isa = XCConfigurationList; buildConfigurations = ( - 55CCB17216B84EDA00B56979 /* Release */, - 1873301918CBD4A700275344 /* Debug */, + 8EC391631C9733C2001E28E6 /* Release */, + 8EC391641C9733C2001E28E6 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -8028,15 +8243,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BA4B79D61373A97000003422 /* Build configuration list for PBXNativeTarget "dp_notify_lib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BA4B79D71373A97000003422 /* Release */, - 18732FF318CBD4A700275344 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; BA4B79EA1373AF7A00003422 /* Build configuration list for PBXNativeTarget "dynamic_pager" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8316,15 +8522,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BACC1D071377B3E6007728F4 /* Build configuration list for PBXNativeTarget "makekey" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BACC1D081377B3E6007728F4 /* Release */, - 18732FFD18CBD4A700275344 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; BACC1D131377B481007728F4 /* Build configuration list for PBXNativeTarget "mean" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8433,29 +8630,20 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BAE58A2313799FFA0049DD3B /* Build configuration list for PBXNativeTarget "sadc" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BAE58A2413799FFA0049DD3B /* Release */, - 1873300918CBD4A700275344 /* Debug */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - BAE58A3B1379A3F60049DD3B /* Build configuration list for PBXNativeTarget "sar" */ = { + BAE58A4C137D69A60049DD3B /* Build configuration list for PBXNativeTarget "sc_usage" */ = { isa = XCConfigurationList; buildConfigurations = ( - BAE58A3C1379A3F60049DD3B /* Release */, - 1873300A18CBD4A700275344 /* Debug */, + BAE58A4D137D69A60049DD3B /* Release */, + 1873300B18CBD4A700275344 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BAE58A4C137D69A60049DD3B /* Build configuration list for PBXNativeTarget "sc_usage" */ = { + C20D8C6F1C1A102F00C1226B /* Build configuration list for PBXNativeTarget "gcore" */ = { isa = XCConfigurationList; buildConfigurations = ( - BAE58A4D137D69A60049DD3B /* Release */, - 1873300B18CBD4A700275344 /* Debug */, + C20D8C6D1C1A102F00C1226B /* Release */, + C20D8C6E1C1A102F00C1226B /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/system_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme b/system_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme index 88af258..4a3bb2e 100644 --- a/system_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme +++ b/system_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme @@ -23,31 +23,42 @@ + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + + + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + + + + + buildConfiguration = "Release" + includeDebugSupportFiles = "YES"> diff --git a/system_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme b/system_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme index c1c1e62..5251285 100644 --- a/system_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme +++ b/system_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme @@ -23,31 +23,42 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> + + + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + + + + + buildConfiguration = "Release" + includeDebugSupportFiles = "YES"> diff --git a/taskpolicy.tproj/taskpolicy.8 b/taskpolicy.tproj/taskpolicy.8 index 4eff832..c6c9a41 100644 --- a/taskpolicy.tproj/taskpolicy.8 +++ b/taskpolicy.tproj/taskpolicy.8 @@ -45,7 +45,7 @@ like "default" or "throttle", which is interpreted case-insensitively. Run the program after calling .Xr setiopolicy_np 3 with an iotype of IOPOL_TYPE_DISK, a scope of IOPOL_SCOPE_DARWIN_BG, and the -specified policy. The argument is interpreted in the same manor as +specified policy. The argument is interpreted in the same manner as .Fl d . .It Fl c Ar clamp Run the program using the specified QoS clamp. The argument can be either @@ -65,8 +65,6 @@ Set throughput tier of the process to .It Fl l Set latency tier of the process to .Ar latency_tier . - - .El .Pp .Sh SEE ALSO diff --git a/taskpolicy.tproj/taskpolicy.c b/taskpolicy.tproj/taskpolicy.c index 0688200..b5e9a60 100644 --- a/taskpolicy.tproj/taskpolicy.c +++ b/taskpolicy.tproj/taskpolicy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Apple Inc. All rights reserved. + * Copyright (c) 2013-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -58,7 +58,7 @@ int main(int argc, char * argv[]) int flagd = -1, flagg = -1; struct task_qos_policy qosinfo = { LATENCY_QOS_TIER_UNSPECIFIED, THROUGHPUT_QOS_TIER_UNSPECIFIED }; uint64_t qos_clamp = POSIX_SPAWN_PROC_CLAMP_NONE; - + while ((ch = getopt(argc, argv, "xXbBd:g:c:t:l:p:")) != -1) { switch (ch) { case 'x': @@ -131,7 +131,7 @@ int main(int argc, char * argv[]) warnx("Incompatible option(s) used with -p"); usage(); } - + if (flagx && flagX){ warnx("Incompatible options -x, -X"); usage(); @@ -206,25 +206,24 @@ int main(int argc, char * argv[]) err(EX_SOFTWARE, "task_policy_set(...TASK_OVERRIDE_QOS_POLICY...)"); } } - + if (pid != 0) return 0; - - + ret = posix_spawnattr_init(&attr); if (ret != 0) errc(EX_NOINPUT, ret, "posix_spawnattr_init"); - + ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC); if (ret != 0) errc(EX_NOINPUT, ret, "posix_spawnattr_setflags"); - + if (qos_clamp != POSIX_SPAWN_PROC_CLAMP_NONE) { ret = posix_spawnattr_set_qos_clamp_np(&attr, qos_clamp); if (ret != 0) errc(EX_NOINPUT, ret, "posix_spawnattr_set_qos_clamp_np"); } - + ret = posix_spawnp(&pid, argv[0], NULL, &attr, argv, environ); if (ret != 0) errc(EX_NOINPUT, ret, "posix_spawn"); - + return EX_OSERR; } @@ -240,14 +239,14 @@ static int parse_disk_policy(const char *strpolicy) { long policy; char *endptr = NULL; - + /* first try as an integer */ policy = strtol(strpolicy, &endptr, 0); if (endptr && (endptr[0] == '\0') && (strpolicy[0] != '\0')) { /* parsed complete string as a number */ return (int)policy; } - + if (0 == strcasecmp(strpolicy, "DEFAULT") ) { return IOPOL_DEFAULT; } else if (0 == strcasecmp(strpolicy, "IMPORTANT")) { @@ -268,7 +267,7 @@ static int parse_disk_policy(const char *strpolicy) static int parse_qos_tier(const char *strtier, int parameter){ long policy; char *endptr = NULL; - + /* first try as an integer */ policy = strtol(strtier, &endptr, 0); if (endptr && (endptr[0] == '\0') && (strtier[0] != '\0')) { @@ -301,7 +300,7 @@ static int parse_qos_tier(const char *strtier, int parameter){ } static uint64_t parse_qos_clamp(const char *qos_string) { - + if (0 == strcasecmp(qos_string, "utility") ) { return POSIX_SPAWN_PROC_CLAMP_UTILITY; } else if (0 == strcasecmp(qos_string, "background")) { diff --git a/trace.tproj/trace.1 b/trace.tproj/trace.1 index d860ee0..ac9d270 100644 --- a/trace.tproj/trace.1 +++ b/trace.tproj/trace.1 @@ -219,20 +219,30 @@ Additional trace codes files specified will still be used. .Pp Empty the current kernel trace buffer into .Ar rawfile -in a binary format. +in a binary format. If +.Ar rawfile +is +.Li - , +the file will be written to +.Xr stdout 4 . .\" .\" ## 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 +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. +have elapsed, stop recording and exit. If +.Ar rawfile +is +.Li - , +the file will be written to +.Xr stdout 4 . .El .\" .\" ## trace -R ## @@ -240,7 +250,7 @@ have elapsed, stop recording and exit. .Pp Read events from .Ar rawfile -and print them in a human-readable format. +and print them in a human-readable format. .Bl -tag -width " " .It Fl F Ar frequency If diff --git a/trace.tproj/trace.c b/trace.tproj/trace.c index d664890..190e8b2 100644 --- a/trace.tproj/trace.c +++ b/trace.tproj/trace.c @@ -2,6 +2,10 @@ cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -arch x86_64 -arch i386 -O -o trace trace.c */ +/* + * NOTE: There exists another copy of this file in the kernel_tools. Changes + * made here may also need to be made there. + */ #include #include @@ -47,7 +51,6 @@ #include #include - int nbufs = 0; int enable_flag=0; int execute_flag=0; @@ -106,14 +109,8 @@ uint8_t* type_filter_bitmap; #define CSC_MASK 0xffff0000 -#define VFS_LOOKUP 0x03010090 #define BSC_exit 0x040c0004 #define BSC_thread_terminate 0x040c05a4 -#define TRACE_DATA_NEWTHREAD 0x07000004 -#define TRACE_STRING_NEWTHREAD 0x07010004 -#define TRACE_STRING_EXEC 0x07010008 -#define TRACE_LOST_EVENTS 0x07020008 -#define TRACE_INFO_STRING 0x07020010 #define MACH_SCHEDULED 0x01400000 #define MACH_MAKERUNNABLE 0x01400018 #define MACH_STKHANDOFF 0x01400008 @@ -130,8 +127,8 @@ kd_threadmap *mapptr = 0; kd_cpumap_header* cpumap_header = NULL; kd_cpumap* cpumap = NULL; -/* - If NUMPARMS changes from the kernel, +/* + If NUMPARMS changes from the kernel, then PATHLENGTH will also reflect the change This is for the vfslookup entries that return pathnames @@ -143,7 +140,7 @@ kd_cpumap* cpumap = NULL; #define US_TO_SLEEP 50000 #define BASE_EVENTS 500000 - +mach_timebase_info_data_t mach_timebase; double divisor; typedef struct { @@ -170,7 +167,7 @@ typedef struct lookup *lookup_t; struct lookup { lookup_t lk_next; - + uintptr_t lk_thread; uintptr_t lk_dvp; long *lk_pathptr; @@ -181,13 +178,13 @@ typedef struct threadmap *threadmap_t; struct threadmap { threadmap_t tm_next; - + uintptr_t tm_thread; uintptr_t tm_pthread; boolean_t tm_deleteme; char tm_command[MAXCOMLEN + 1]; }; - + #define HASH_SIZE 1024 #define HASH_MASK 1023 @@ -234,6 +231,7 @@ static void set_pidexclude(int, int); static void set_numbufs(int); static void set_freerun(); static void get_bufinfo(kbufinfo_t *); +static int get_ktrace_state(void); static void set_init(); static void set_kval_list(); static void readtrace(char *); @@ -250,7 +248,7 @@ static void execute_process(char * const argv[]); static int writetrace(int); static int write_command_map(int); -static int debugid_compar(code_type_t *, code_type_t *); +static int debugid_compar(const void *, const void *); static threadmap_t find_thread_entry(uintptr_t); @@ -328,12 +326,12 @@ void set_enable(int val) } } -void set_remove() +void set_remove(void) { extern int errno; - + errno = 0; - + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDREMOVE; @@ -359,7 +357,7 @@ void set_numbufs(int nbufs) mib[5] = 0; if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) quit_args("trace facility failure, KERN_KDSETBUF: %s\n", strerror(errno)); - + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDSETUP; @@ -370,7 +368,7 @@ void set_numbufs(int nbufs) quit_args("trace facility failure, KERN_KDSETUP: %s\n", strerror(errno)); } -void set_nowrap() +void set_nowrap(void) { mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; @@ -386,7 +384,7 @@ void set_nowrap() void set_pidcheck(int pid, int on_off_flag) { kd_regtype kr; - + kr.type = KDBG_TYPENONE; kr.value1 = pid; kr.value2 = on_off_flag; @@ -420,7 +418,7 @@ void set_pidcheck(int pid, int on_off_flag) void set_pidexclude(int pid, int on_off_flag) { kd_regtype kr; - + kr.type = KDBG_TYPENONE; kr.value1 = pid; kr.value2 = on_off_flag; @@ -442,7 +440,7 @@ void set_pidexclude(int pid, int on_off_flag) } } -void set_freerun() +void set_freerun(void) { mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; @@ -454,6 +452,18 @@ void set_freerun() quit_args("trace facility failure, KDBG_FREERUN: %s\n", strerror(errno)); } +static int get_ktrace_state(void) +{ + int state; + size_t state_size = sizeof(state); + int err = sysctlbyname("ktrace.state", &state, &state_size, NULL, 0); + if (err) { + fprintf(stderr, "error: could not query ktrace.state sysctl (%d: %s)\n", errno, strerror(errno)); + exit(1); + } + return state; +} + void get_bufinfo(kbufinfo_t *val) { needed = sizeof (*val); @@ -467,10 +477,10 @@ void get_bufinfo(kbufinfo_t *val) quit_args("trace facility failure, KERN_KDGETBUF: %s\n", strerror(errno)); } -void set_init() +void set_init(void) { kd_regtype kr; - + kr.type = KDBG_RANGETYPE; kr.value1 = 0; kr.value2 = -1; @@ -483,7 +493,7 @@ void set_init() mib[5] = 0; if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) quit_args("trace facility failure, KERN_KDSETREG (rangetype): %s\n", strerror(errno)); - + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDSETUP; @@ -494,7 +504,6 @@ void set_init() quit_args("trace facility failure, KERN_KDSETUP: %s\n", strerror(errno)); } - static void set_filter(void) { @@ -507,10 +516,10 @@ set_filter(void) } } -void set_kval_list() +void set_kval_list(void) { kd_regtype kr; - + kr.type = KDBG_VALCHECK; kr.value1 = value1; kr.value2 = value2; @@ -532,7 +541,7 @@ void readtrace(char *buffer) { mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; + mib[2] = KERN_KDREADTR; mib[3] = 0; mib[4] = 0; mib[5] = 0; @@ -567,8 +576,15 @@ int write_command_map(int fd) mib[4] = 0; mib[5] = 0; - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) - return 1; + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) { + if (errno == ENODATA) { + if (verbose_flag) { + printf("Cannot write thread map -- this is not fatal\n"); + } + } else { + return 1; + } + } return 0; } @@ -699,7 +715,7 @@ uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now) evp_prev = evp; for (evp = evp->ev_next; evp; evp = evp->ev_next) { - + if (evp->ev_thread == thread && evp->ev_debugid == debugid) { evp_prev->ev_next = evp->ev_next; break; @@ -709,7 +725,7 @@ uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now) } if (evp) { elapsed = now - evp->ev_timestamp; - + evp->ev_next = event_freelist; event_freelist = evp; } @@ -717,16 +733,20 @@ uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now) return (elapsed); } - void -log_trace() +log_trace(void) { int fd = -1; int ret = 0; char *buffer; uint32_t buffer_size = 1000000 * sizeof(kd_buf); - fd = open(logfile, O_TRUNC | O_WRONLY | O_CREAT, 0777); + if (logfile[0] == '-' && logfile[1] == '\0') { + fd = STDOUT_FILENO; + } else { + fd = open(logfile, O_TRUNC | O_WRONLY | O_CREAT, 0777); + } + if (fd == -1) { perror("Can't open logfile"); exit(1); @@ -775,29 +795,31 @@ log_trace() close(fd); } +/* + * Why does this function exist? + * trace -L needs millisecond level wait times. + * When this code is running remotely, the mach_timebase_info_t data may + * be from a device with a different timebase. This code avoids using + * mach_absolute_time(), so that time calculations come out correct both + * locally and remotely. + */ +static uint64_t current_millis() { + struct timeval time; + gettimeofday(&time, NULL); + return (time.tv_sec * 1000) + (time.tv_usec / 1000); +} void -Log_trace() +Log_trace(void) { - int size; - kd_buf kd_tmp; size_t len; - int num_cpus; - int try_writetrace = 1; + int num_cpus = 0; int fd; - char *buffer; - kd_buf *kd; - uint64_t sample_window_abs; - uint64_t next_window_begins; - uint64_t current_abs; - uint64_t ending_abstime; + uint64_t current_ms; + uint64_t ending_ms = 0; uint64_t last_time_written; - uint32_t us_to_sleep; - uint32_t us_to_adjust; uint32_t ms_to_run; - memset(&kd_tmp, 0, sizeof(kd_tmp)); - if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) { perror("Can't open logfile"); exit(1); @@ -826,13 +848,6 @@ Log_trace() if (kval_flag) set_kval_list(); } - /* Get kernel buffer information */ - get_bufinfo(&bufinfo); - - buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf)); - if (buffer == (char *) 0) - quit("can't allocate memory for tracing info\n"); - memset(buffer, 0, bufinfo.nkdbufs * sizeof(kd_buf)); if (use_current_buf == 0) set_enable(1); @@ -841,82 +856,41 @@ Log_trace() 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; + last_time_written = current_millis(); if (secs_to_run) { - ending_abstime = mach_absolute_time() + (uint64_t)((double)secs_to_run * (double)1000000 * divisor); ms_to_run = secs_to_run * 1000; + ending_ms = last_time_written + ms_to_run; } else ms_to_run = 0; - last_time_written = mach_absolute_time(); while (LogRAW_flag) { - current_abs = mach_absolute_time(); + needed = ms_to_run; - if (try_writetrace) { - needed = ms_to_run; - - if (writetrace(fd)) - try_writetrace = 0; - else { - if (needed) { - current_abs = mach_absolute_time(); + if (writetrace(fd)) { + perror("KDWRITETR returned error"); - printf("wrote %d events - elapsed time = %.1f secs\n", - (int)needed, ((double)(current_abs - last_time_written) / divisor) / 1000000); - - last_time_written = current_abs; - } - } + /* Clean up and exit in case of write fail */ + break; } - if (try_writetrace == 0) { - - if (next_window_begins > current_abs) - us_to_adjust = US_TO_SLEEP - (uint32_t)((double)(next_window_begins - current_abs) / divisor); - else - us_to_adjust = US_TO_SLEEP; - - next_window_begins = current_abs + sample_window_abs; - - us_to_sleep = US_TO_SLEEP - us_to_adjust; - next_window_begins = current_abs + (uint64_t)((double)(us_to_sleep + US_TO_SLEEP) * divisor); + if (needed) { + current_ms = current_millis(); - if (us_to_sleep) - usleep(us_to_sleep); - - get_bufinfo(&bufinfo); - - if (bufinfo.flags & KDBG_WRAPPED) - printf("lost events\n"); + printf("wrote %d events - elapsed time = %.1f secs\n", + (int)needed, (double)(current_ms - last_time_written) / 1000.0); - needed = bufinfo.nkdbufs * sizeof(kd_buf); - - readtrace(buffer); - - if (bufinfo.flags & KDBG_WRAPPED) { - - kd = (kd_buf *) buffer; - - kd_tmp.timestamp = kd[0].timestamp; - kd_tmp.debugid = TRACE_LOST_EVENTS; - - write(fd, &kd_tmp, sizeof(kd_tmp)); - } - write(fd, buffer, needed * sizeof(kd_buf)); - - if (verbose_flag && needed > nbufs) - printf("needed = %ld\n", needed); + last_time_written = current_ms; } + if (secs_to_run) { - current_abs = mach_absolute_time(); + current_ms = current_millis(); - if (current_abs > ending_abstime) + if (current_ms > ending_ms) break; - ms_to_run = (ending_abstime - current_abs) / (1000 * 1000); - + + ms_to_run = (uint32_t)(ending_ms - current_ms); + if (ms_to_run == 0) break; } @@ -929,13 +903,13 @@ Log_trace() } -void read_trace() +void read_trace(void) { char *buffer; uint32_t buffer_size; kd_buf *kd; int fd; - int firsttime = 1; + int firsttime = 1; int lines = 0; int io_lines = 0; uint64_t bias = 0; @@ -981,6 +955,34 @@ void read_trace() perror("read failed"); exit(2); } + } else if (raw_header.version_no == RAW_VERSION1) { +#if defined(__ILP32__) + /* + * If the raw trace file was written by armv7k, the 64-bit alignment + * of TOD_secs causes RAW_header to be 24 bytes. If we only read 20 + * bytes, the next 4 bytes might be a legitimate thread_id, but it might + * also be 0 or a leaked kernel pointer from an armv7k trace file. For + * both those cases, consume the 4 bytes and look for the thread map + * after it. + */ + if (sizeof(raw_header) == 20) { + uint32_t alignment_garbage; + + if (read(fd, &alignment_garbage, sizeof(alignment_garbage)) != sizeof(alignment_garbage)) { + perror("read failed"); + exit(2); + } + + if ((alignment_garbage == 0) || (alignment_garbage >= 0x80000000)) { + if (verbose_flag) { + printf("Skipping 4 bytes to find valid thread map\n"); + } + } else { + /* oops, go back to where we were */ + lseek(fd, -(off_t)sizeof(alignment_garbage), SEEK_CUR); + } + } +#endif } count_of_names = raw_header.thread_count; trace_time = (time_t) (raw_header.TOD_secs); @@ -993,7 +995,7 @@ void read_trace() if (buffer == (char *) 0) quit("can't allocate memory for tracing info\n"); - kd = (kd_buf *)buffer; + kd = (kd_buf *)(uintptr_t)buffer; read_command_map(fd, count_of_names); read_cpu_map(fd); @@ -1002,12 +1004,12 @@ void read_trace() uint32_t count; uint64_t now = 0; uint64_t prev; - uint64_t prevdelta; - uint32_t cpunum; + uint64_t prevdelta = 0; + uint32_t cpunum = 0; uintptr_t thread; double x = 0.0; double y = 0.0; - double event_elapsed_time; + double event_elapsed_time = 0; kd_buf *kdp; lookup_t lkp; boolean_t ending_event; @@ -1024,7 +1026,7 @@ void read_trace() mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; + mib[2] = KERN_KDREADTR; mib[3] = 0; mib[4] = 0; mib[5] = 0; @@ -1033,12 +1035,12 @@ void read_trace() if (needed == 0) break; - count = needed; + count = (uint32_t)needed; } else { uint32_t bytes_read; - bytes_read = read(fd, buffer, buffer_size); + bytes_read = (uint32_t)read(fd, buffer, buffer_size); if (bytes_read == -1) { perror("read failed"); @@ -1056,11 +1058,34 @@ void read_trace() debugid_base = debugid & DBG_FUNC_MASK; now = kdp->timestamp & KDBG_TIMESTAMP_MASK; + /* + * Is this event from an IOP? If so, there will be no + * thread command, label it with the symbolic IOP name + */ + if (cpumap && (cpunum < cpumap_header->cpu_count) && (cpumap[cpunum].flags & KDBG_CPUMAP_IS_IOP)) { + command = cpumap[cpunum].name; + } else { + find_thread_command(kdp, &command); + } + + /* + * The internal use TRACE points clutter the output. + * Print them only if in verbose mode. + */ + if (!verbose_flag) + { + /* Is this entry of Class DBG_TRACE */ + if ((debugid >> 24) == DBG_TRACE) { + if (((debugid >> 16) & 0xff) != DBG_TRACE_INFO) + continue; + } + } + if (firsttime) bias = now; now -= bias; - cpunum = kdbg_get_cpu(kdp); + cpunum = kdbg_get_cpu(kdp); thread = kdp->arg5; if (lines == 64 || firsttime) @@ -1076,8 +1101,8 @@ void read_trace() fprintf(output_file, "\n\nNumber of microsecs since in last page %8.1f\n", x); } prevdelta = now; - - /* + + /* * Output description row to output file (make sure to format correctly for 32-bit and 64-bit) */ fprintf(output_file, @@ -1087,9 +1112,9 @@ void read_trace() " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n" #endif ); - + lines = 0; - + if (io_lines > 15000) { fcntl(output_fd, F_FLUSH_DATA, 0); @@ -1104,6 +1129,7 @@ void read_trace() if ( !lkp || !(debugid & DBG_FUNC_END)) continue; } + x = (double)now; x /= divisor; @@ -1114,31 +1140,9 @@ void read_trace() last_event_time = x; ending_event = FALSE; - /* - * Is this event from an IOP? If so, there will be no - * thread command, label it with the symbolic IOP name - */ - if (cpumap && (cpunum < cpumap_header->cpu_count) && (cpumap[cpunum].flags & KDBG_CPUMAP_IS_IOP)) { - command = cpumap[cpunum].name; - } else { - find_thread_command(kdp, &command); - } - - /* - * The internal use TRACE points clutter the output. - * Print them only if in verbose mode. - */ - if (!verbose_flag) - { - /* Is this entry of Class DBG_TRACE */ - if ((debugid >> 24) == DBG_TRACE) { - if (((debugid >> 16) & 0xff) != DBG_TRACE_INFO) - continue; - } - } if ( !lkp) { int t_debugid; - int t_thread; + uintptr_t t_thread; if ((debugid & DBG_FUNC_START) || debugid == MACH_MAKERUNNABLE) { @@ -1153,7 +1157,7 @@ void read_trace() } } else if ((debugid & DBG_FUNC_END) || debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) { - + if (debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) { t_debugid = MACH_MAKERUNNABLE; t_thread = kdp->arg2; @@ -1218,7 +1222,7 @@ void read_trace() /* * print the tail end of the pathname */ - len = strlen(strptr); + len = (int)strlen(strptr); if (len > 51) len -= 51; else @@ -1253,7 +1257,7 @@ void read_trace() -void signal_handler(int sig) +void signal_handler(int sig) { ptrace(PT_KILL, pid, (caddr_t)0, 0); /* @@ -1269,18 +1273,13 @@ void signal_handler_RAW(int sig) } - -int main(argc, argv, env) -int argc; -char **argv; -char **env; +int main (int argc, char* argv[], char *envp[]) { extern char *optarg; extern int optind; int ch; int i; char *output_filename = NULL; - char *filter_filename = NULL; unsigned int parsed_arg; for (i = 1; i < argc; i++) { @@ -1407,7 +1406,7 @@ char **env; case 'p': filter_flag = 1; parsed_arg = argtoi('p', "decimal, hex, or octal number", optarg, 0); - if (parsed_arg > 0xFF) + if (parsed_arg > 0xFF) quit_args("argument '-p %s' parsed as %u, " "end range value must be 0-255\n", optarg, parsed_arg); saw_filter_end_range(parsed_arg); @@ -1485,9 +1484,17 @@ char **env; if (LogRAW_flag) { get_bufinfo(&bufinfo); + int ktrace_state = get_ktrace_state(); - if (bufinfo.nolog == 0) + /* + * Only use the current kdebug configuration when foreground + * tracing is enabled. Both checks are necessary because the + * background tool might have enabled tracing, but as soon as we + * try to write a header, that configuration is removed for us. + */ + if ((ktrace_state == 1) && (bufinfo.nolog == 0)) { use_current_buf = 1; + } } if (disable_flag) @@ -1511,7 +1518,7 @@ char **env; set_remove(); exit(0); } - + if (bufset_flag ) { if (!init_flag && !LogRAW_flag) @@ -1521,15 +1528,50 @@ char **env; } set_numbufs(nbufs); } - + if (nowrap_flag) set_nowrap(); if (freerun_flag) set_freerun(); - + if (bufget_flag) { + printf("The kernel tracing settings are:\n"); + + /* determine the state of ktrace */ + int state = get_ktrace_state(); + + /* get the name of the last process to configure ktrace */ + char execname[20] = { 0 }; + size_t execname_size = sizeof(execname); + int err = sysctlbyname("ktrace.configured_by", &execname, &execname_size, NULL, 0); + if (err) { + fprintf(stderr, "error: could not query ktrace.configured_by sysctl (%d: %s)\n", errno, strerror(errno)); + exit(1); + } + + printf("\tTracing is "); + switch (state) { + case 0: + printf("off"); + break; + case 1: + printf("active (foreground)"); + break; + case 2: + printf("active (background)"); + break; + default: + printf("in an invalid state"); + break; + } + printf("\n"); + + printf("\tLast configured by \"%s\"\n", execname[0] == '\0' ? "" : execname); + + /* get kdebug info */ + get_bufinfo(&bufinfo); printf("The kernel buffer settings are:\n"); @@ -1572,7 +1614,7 @@ char **env; printf("\tCollecting specific code values is enabled\n"); else printf("\tCollecting specific code values is disabled\n"); - + if (bufinfo.flags & KDBG_TYPEFILTER_CHECK) printf("\tCollection based on a filter is enabled\n"); else @@ -1592,6 +1634,50 @@ char **env; printf("\tKernel buffer is not controlled by any process.\n"); else printf("\tKernel buffer is controlled by proc id [%d]\n", bufinfo.bufid); + + + if (bufinfo.flags & KDBG_TYPEFILTER_CHECK) { + if (verbose_flag) { + bool (^should_print)(uint8_t*) = ^bool(uint8_t* ptr) { + for (uint32_t i=0; i<32; ++i) { + if (ptr[i] > 0) return true; + } + + return false; + }; + + uint8_t* typefilter = (uint8_t*)kdebug_typefilter(); + if (typefilter) { + bool header = false; + + // Reduce noise, only print lines that are allowing events. + for (uint32_t tclass = 0; tclass < 0x100; ++tclass) { + uint8_t* base = &typefilter[tclass * 32]; + if (should_print(base)) { + if (!header) { + header = true; + printf("\tTypefilter:\n"); + printf("%18s ",""); + for (uint32_t tsubclass=0; tsubclass<32; ++tsubclass) { + printf("%02x ", tsubclass * 8); + } + printf("\n"); + printf("%18s ",""); + for (uint32_t tsubclass=0; tsubclass<32; ++tsubclass) { + printf("---"); + } + printf("\n"); + } + printf("%16s%02x: ", "", tclass); + for (uint32_t tsubclass=0; tsubclass<32; ++tsubclass) { + printf("%02X ", typefilter[(tclass * 32) + tsubclass]); + } + printf("\n"); + } + } + } + } + } } if (init_flag) @@ -1631,7 +1717,7 @@ char **env; usage(SHORT_HELP); } setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE); - + if (fcntl(output_fd, F_NOCACHE, 1) < 0) { /* Not fatal */ @@ -1696,7 +1782,7 @@ execute_process(char * const argv[]) } static void -quit_args(const char *fmt, ...) +quit_args(const char *fmt, ...) { char buffer[1024]; @@ -1733,7 +1819,7 @@ quit(char *s) printf("trace: "); if (s) - printf("%s ", s); + printf("%s", s); exit(1); } @@ -1841,9 +1927,9 @@ usage(int short_help) (void)fprintf(stderr, "\tcollection of kernel trace elements for that process.\n"); (void)fprintf(stderr, "\tSee -e(enable) flag for option descriptions.\n\n"); - (void)fprintf(stderr, "usage: trace -t [-o OutputFilename] [-N] [ExtraCodeFilename1 ExtraCodeFilename2 ...] \n"); + (void)fprintf(stderr, "usage: trace -t [-o OutputFilename] [-N] [ExtraCodeFilename1 ExtraCodeFilename2 ...] \n"); (void)fprintf(stderr, "\tCollect the kernel buffer trace data and print it.\n\n"); - (void)fprintf(stderr, "\t -N Do not import /usr/share/misc/trace.codes (for raw hex tracing or supplying an alternate set of codefiles)\n"); + (void)fprintf(stderr, "\t -N Do not import /usr/share/misc/trace.codes (for raw hex tracing or supplying an alternate set of codefiles)\n"); (void)fprintf(stderr, "\t -o OutputFilename Print trace output to OutputFilename. Default is stdout.\n\n"); (void)fprintf(stderr, @@ -1851,7 +1937,7 @@ usage(int short_help) (void)fprintf(stderr, "\tRead raw trace file and print it.\n\n"); (void)fprintf(stderr, "\t -X Force trace to interpret trace data as 32 bit. \n"); (void)fprintf(stderr, "\t Default is to match the bit width of the current system. \n"); - (void)fprintf(stderr, "\t -N Do not import /usr/share/misc/trace.codes (for raw hex tracing or supplying an alternate set of codefiles)\n"); + (void)fprintf(stderr, "\t -N Do not import /usr/share/misc/trace.codes (for raw hex tracing or supplying an alternate set of codefiles)\n"); (void)fprintf(stderr, "\t -F frequency Specify the frequency of the clock used to timestamp entries in RawFilename.\n\t Use command \"sysctl hw.tbfrequency\" on the target device, to get target frequency.\n"); (void)fprintf(stderr, "\t -o OutputFilename Print trace output to OutputFilename. Default is stdout.\n\n"); @@ -1917,10 +2003,7 @@ usage(int short_help) static int -argtoi(flag, req, str, base) -int flag; -char *req, *str; -int base; +argtoi(int flag, char *req, char *str, int base) { char *cp; int ret; @@ -1931,12 +2014,8 @@ int base; return (ret); } - static unsigned long -argtoul(flag, req, str, base) -int flag; -char *req, *str; -int base; +argtoul(int flag, char *req, char *str, int base) { char *cp; unsigned long ret; @@ -1947,24 +2026,24 @@ int base; return (ret); } - /* * comparison function for qsort * sort by debugid */ -int debugid_compar(p1, p2) - code_type_t *p1; - code_type_t *p2; +int +debugid_compar(const void *p1, const void *p2) { - if (p1->debugid > p2->debugid) - return(1); - else if (p1->debugid == p2->debugid) - return(0); + const code_type_t *q1 = (const code_type_t *)p1; + const code_type_t *q2 = (const code_type_t *)p2; + + if (q1->debugid > q2->debugid) + return (1); + else if (q1->debugid == q2->debugid) + return (0); else - return(-1); + return (-1); } - /* * Filter args parsing state machine: * @@ -2121,7 +2200,7 @@ set_filter_subclass(uint8_t class, uint8_t subclass) uint16_t csc = ENCODE_CSC_LOW(class, subclass); - if (verbose_flag && !setting_class) + if (verbose_flag && !setting_class) printf("tracing subclass: 0x%4.4x\n", csc); if (verbose_flag && isset(type_filter_bitmap, csc)) @@ -2173,7 +2252,8 @@ set_filter_range(uint8_t class, uint8_t end) */ static void -parse_filter_file(char *filename) { +parse_filter_file(char *filename) +{ FILE* file; uint32_t current_line = 0; uint32_t parsed_arg = 0; @@ -2191,7 +2271,7 @@ parse_filter_file(char *filename) { while( fgets(line, sizeof(line), file) != NULL ) { current_line++; - + switch (line[0]) { case 'C': rval = sscanf(line, "C 0x%x\n", &parsed_arg); @@ -2237,14 +2317,11 @@ parse_filter_file(char *filename) { fclose(file); } - /* * Find the debugid code in the list and return its index */ -static int binary_search(list, lowbound, highbound, code) - code_type_t *list; - int lowbound, highbound; - unsigned int code; +static int +binary_search(code_type_t *list, int lowbound, int highbound, unsigned int code) { int low, high, mid; int tries = 0; @@ -2282,10 +2359,10 @@ static int parse_codefile(const char *filename) { int fd; - int i, j, line; + int j, line; size_t count; struct stat stat_buf; - unsigned long file_size; + size_t file_size; char *file_addr, *endp; if ((fd = open(filename, O_RDONLY, 0)) == -1) @@ -2304,11 +2381,11 @@ parse_codefile(const char *filename) * For some reason mapping files with zero size fails * so it has to be handled specially. */ - file_size = stat_buf.st_size; + file_size = (size_t)stat_buf.st_size; if (stat_buf.st_size != 0) { - if ((file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, + if ((file_addr = mmap(0, file_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FILE, fd, 0)) == (char*) -1) { printf("Error: Can't map file: %s\n", filename); @@ -2368,23 +2445,23 @@ parse_codefile(const char *filename) j++; line++; } - + /* Skip leading whitespace */ while (file_addr[j] == ' ' || file_addr[j] == '\t') j++; /* Get the debugid code */ - codesc[codesc_idx].debugid = strtoul(file_addr + j, &endp, 16); - j = endp - file_addr; + codesc[codesc_idx].debugid = (uint32_t)strtoul(file_addr + j, &endp, 16); + j = (int)(endp - file_addr); - if (codesc[codesc_idx].debugid == 0) + if (codesc[codesc_idx].debugid == 0) { /* We didn't find a debugid code - skip this line */ if (verbose_flag) printf("Error: while parsing line %d, skip\n", line); while (file_addr[j] != '\n' && j < file_size) j++; - codesc_idx--; + codesc_idx--; line++; continue; } @@ -2401,13 +2478,13 @@ parse_codefile(const char *filename) printf("Error: while parsing line %d, (0x%x) skip\n", line, codesc[codesc_idx].debugid); j++; - codesc_idx--; + codesc_idx--; line++; continue; } /* Next is the debugid string terminated by a newline */ - codesc[codesc_idx].debug_string = &file_addr[j]; + codesc[codesc_idx].debug_string = &file_addr[j]; /* Null out the newline terminator */ while ((j < file_size) && (file_addr[j] != '\n')) @@ -2426,25 +2503,27 @@ parse_codefile(const char *filename) } /* sort */ - qsort((void *)codesc, codesc_idx, sizeof(code_type_t), debugid_compar); + qsort((void *)codesc, codesc_idx, sizeof(code_type_t), debugid_compar); if (verbose_flag) { - printf("Sorted %zd codes in %s\n", codesc_idx, filename); + printf("Sorted %zd codes in %s\n", codesc_idx, filename); printf("lowbound [%6d]: 0x%8x %s\n", 0, codesc[0].debugid, codesc[0].debug_string); - printf("highbound [%6zd]: 0x%8x %s\n\n", codesc_idx - 1, codesc[codesc_idx - 1].debugid, codesc[codesc_idx - 1].debug_string); + printf("highbound [%6zd]: 0x%8x %s\n\n", codesc_idx - 1, codesc[codesc_idx - 1].debugid, codesc[codesc_idx - 1].debug_string); } codesc_find_dupes(); #if 0 /* Dump the codefile */ + int i; for (i = 0; i < codesc_idx; i++) printf("[%d] 0x%x %s\n",i+1, codesc[i].debugid, codesc[i].debug_string); #endif return(0); } -static void codesc_find_dupes(void) +static void +codesc_find_dupes(void) { boolean_t found_dupes = FALSE; if (codesc_idx == 0) @@ -2469,8 +2548,8 @@ static void codesc_find_dupes(void) } } - -int match_debugid(unsigned int xx, char * debugstr, int * yy) +int +match_debugid(unsigned int xx, char * debugstr, int * yy) { int indx; @@ -2506,7 +2585,7 @@ read_cpu_map(int fd) * cpumap size is one page. */ cpumap_header = malloc(PAGE_SIZE); - + if (readRAW_flag) { /* * cpu maps exist in a RAW_VERSION1+ header only @@ -2524,11 +2603,11 @@ read_cpu_map(int fd) } } else { int mib[3]; - + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDCPUMAP; - + size_t temp = PAGE_SIZE; if (sysctl(mib, 3, cpumap_header, &temp, NULL, 0) == 0) { if (PAGE_SIZE >= temp) { @@ -2619,7 +2698,7 @@ read_command_map(int fd, uint32_t count) if (verbose_flag) { /* Dump the initial map */ - + printf("Size of maptable returned is %ld, thus %ld entries\n", size, (size/sizeof(kd_threadmap))); printf("Thread Command\n"); @@ -2633,8 +2712,8 @@ read_command_map(int fd, uint32_t count) return (int)size; } - -void create_map_entry(uintptr_t thread, char *command) +void +create_map_entry(uintptr_t thread, char *command) { threadmap_t tme; int hashid; @@ -2656,8 +2735,8 @@ void create_map_entry(uintptr_t thread, char *command) threadmap_hash[hashid] = tme; } - -void delete_thread_entry(uintptr_t thread) +void +delete_thread_entry(uintptr_t thread) { threadmap_t tme = 0; threadmap_t tme_prev; @@ -2686,8 +2765,8 @@ void delete_thread_entry(uintptr_t thread) } } - -void find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) +void +find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) { threadmap_t tme = 0; threadmap_t tme_prev; @@ -2721,8 +2800,8 @@ void find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) } } - -void create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) +void +create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) { threadmap_t tme; @@ -2756,8 +2835,8 @@ find_thread_entry(uintptr_t thread) return (0); } - -void find_thread_name(uintptr_t thread, char **command, boolean_t deleteme) +void +find_thread_name(uintptr_t thread, char **command, boolean_t deleteme) { threadmap_t tme; @@ -2770,8 +2849,8 @@ void find_thread_name(uintptr_t thread, char **command, boolean_t deleteme) *command = EMPTYSTRING; } - -void find_thread_command(kd_buf *kbufp, char **command) +void +find_thread_command(kd_buf *kbufp, char **command) { uintptr_t thread; threadmap_t tme; @@ -2817,16 +2896,13 @@ void find_thread_command(kd_buf *kbufp, char **command) find_thread_name(thread, command, (debugid_base == BSC_thread_terminate)); } - -static -void getdivisor() +static void +getdivisor(void) { - mach_timebase_info_data_t info; + (void) mach_timebase_info (&mach_timebase); if (frequency == 0) { - (void) mach_timebase_info (&info); - - divisor = ( (double)info.denom / (double)info.numer) * 1000; + divisor = ( (double)mach_timebase.denom / (double)mach_timebase.numer) * 1000; } else divisor = (double)frequency / 1000000; diff --git a/vifs.tproj/vifs.c b/vifs.tproj/vifs.c index 59c37ae..967cc1d 100644 --- a/vifs.tproj/vifs.c +++ b/vifs.tproj/vifs.c @@ -1,14 +1,14 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2005-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (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. - * + * * This 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, @@ -16,7 +16,7 @@ * 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@ */ diff --git a/vipw.tproj/pw_util.c b/vipw.tproj/pw_util.c index 3af548f..8364496 100644 --- a/vipw.tproj/pw_util.c +++ b/vipw.tproj/pw_util.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /*- @@ -87,17 +87,15 @@ extern char *tempname; static pid_t editpid = -1; static int lockfd; -void -pw_cont(sig) - int sig; +static void +pw_cont(int sig) { - if (editpid != -1) kill(editpid, sig); } void -pw_init() +pw_init(void) { struct rlimit rlim; @@ -127,9 +125,9 @@ pw_init() } int -pw_lock() +pw_lock(void) { - /* + /* * If the master password file doesn't exist, the system is hosed. * Might as well try to build one. Set the close-on-exec bit so * that users can't get at the encrypted passwords while editing. @@ -144,13 +142,13 @@ pw_lock() } int -pw_tmp() +pw_tmp(void) { static char path[MAXPATHLEN] = _PATH_MASTERPASSWD; int fd; char *p; - if (p = strrchr(path, '/')) + if ((p = strrchr(path, '/'))) ++p; else p = path; @@ -162,7 +160,7 @@ pw_tmp() } int -pw_mkdb() +pw_mkdb(void) { int pstat; pid_t pid; @@ -181,17 +179,16 @@ pw_mkdb() } void -pw_edit(notsetuid) - int notsetuid; +pw_edit(int notsetuid) { int pstat; char *p, *editor; if (!(editor = getenv("EDITOR"))) editor = _PATH_VI; - if (p = strrchr(editor, '/')) + if ((p = strrchr(editor, '/'))) ++p; - else + else p = editor; if (!(editpid = vfork())) { @@ -217,7 +214,7 @@ pw_edit(notsetuid) } void -pw_prompt() +pw_prompt(void) { int c; @@ -231,9 +228,7 @@ pw_prompt() } void -pw_error(name, err, eval) - char *name; - int err, eval; +pw_error(char *name, int err, int eval) { if (err) warn("%s", name); diff --git a/vipw.tproj/pw_util.h b/vipw.tproj/pw_util.h index b5811b0..6202815 100644 --- a/vipw.tproj/pw_util.h +++ b/vipw.tproj/pw_util.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /*- diff --git a/vipw.tproj/vipw.c b/vipw.tproj/vipw.c index a258899..4bbad91 100644 --- a/vipw.tproj/vipw.c +++ b/vipw.tproj/vipw.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /* @@ -83,9 +83,7 @@ void copyfile __P((int, int)); void usage __P((void)); int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { int pfd, tfd; struct stat begin, end; @@ -97,7 +95,7 @@ main(argc, argv) default: usage(); } - + argc -= optind; argv += optind; @@ -128,12 +126,11 @@ main(argc, argv) } void -copyfile(from, to) - int from, to; +copyfile(int from, int to) { - int nr, nw, off; + long nr, nw, off; char buf[8*1024]; - + while ((nr = read(from, buf, sizeof(buf))) > 0) for (off = 0; off < nr; nr -= nw, off += nw) if ((nw = write(to, buf + off, nr)) < 0) @@ -143,9 +140,8 @@ copyfile(from, to) } void -usage() +usage(void) { - (void)fprintf(stderr, "usage: vipw\n"); exit(1); } diff --git a/vm_purgeable_stat.tproj/vm_purgeable_stat.c b/vm_purgeable_stat.tproj/vm_purgeable_stat.c index 1fea5f7..bfef539 100644 --- a/vm_purgeable_stat.tproj/vm_purgeable_stat.c +++ b/vm_purgeable_stat.tproj/vm_purgeable_stat.c @@ -1,3 +1,27 @@ +/* + * Copyright (c) 1999-2016 Apple 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 @@ -82,7 +106,7 @@ int get_system_tasks(task_array_t *tasks, mach_msg_type_number_t *count) fprintf(stderr, "%s\n", PRIV_ERR_MSG); return -1; } - + ret = host_processor_sets(mach_host_self(), &psets, &psetCount); if (ret != KERN_SUCCESS) { fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret)); @@ -175,7 +199,7 @@ void print_purge_info_summary(int sleep_duration) int main(int argc, char *argv[]) { - + char ch; int pid; int sleep_duration; @@ -216,7 +240,7 @@ int main(int argc, char *argv[]) case '?': case 'h': default: - printf("%s", USAGE); + printf("%s", USAGE); } break; } @@ -224,5 +248,3 @@ int main(int argc, char *argv[]) printf("%s", USAGE); return 0; } - - diff --git a/vm_stat.tproj/vm_stat.c b/vm_stat.tproj/vm_stat.c index 5ff3b6d..7bedc31 100644 --- a/vm_stat.tproj/vm_stat.c +++ b/vm_stat.tproj/vm_stat.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2016 Apple 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 @@ -10,7 +10,7 @@ * 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, @@ -18,7 +18,7 @@ * 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@ */ /* @@ -37,9 +37,9 @@ * * 25-mar-99 A.Ramesh at Apple * Ported to MacOS X - * + * * 22-Jan-09 R.Branche at Apple - * Changed some fields to 64-bit to alleviate overflows + * Changed some fields to 64-bit to alleviate overflows ************************************************************************ */ @@ -68,7 +68,6 @@ void pstat(uint64_t n, int width); int main(int argc, char *argv[]) { - double delay = 0.0; int count = 0; @@ -126,7 +125,6 @@ usage(void) void snapshot(void) { - get_stats(&vm_stat); printf("Mach Virtual Memory Statistics: (page size of %llu bytes)\n", (mach_vm_size_t)vm_kernel_page_size); diff --git a/wait4path/wait4path.1 b/wait4path/wait4path.1 new file mode 100644 index 0000000..7635261 --- /dev/null +++ b/wait4path/wait4path.1 @@ -0,0 +1,37 @@ +."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@ +." +.Dd 14 December, 2013 +.Dt WAIT4PATH 1 +.Os Darwin +.Sh NAME +.Nm wait4path +.Nd wait for given path to show up in the namespace +.Sh SYNOPSIS +.Nm +.Ao Ar path Ac +.Sh DESCRIPTION +The +.Nm +program simply checks to see if the given path exists, and if so, it exits. +Otherwise, it sleeps until the mount table is updated and checks again. The +program will loop indefinitely until the path shows up in the file system +namespace. diff --git a/wait4path/wait4path.c b/wait4path/wait4path.c new file mode 100644 index 0000000..997f433 --- /dev/null +++ b/wait4path/wait4path.c @@ -0,0 +1,64 @@ +/* + * 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 + +int +main(int argc, char *argv[]) +{ + int kq = kqueue(); + struct kevent kev; + struct stat sb; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + EV_SET(&kev, 0, EVFILT_FS, EV_ADD, 0, 0, 0); + + if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) { + fprintf(stderr, "adding EVFILT_FS to kqueue failed: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (stat(argv[1], &sb) == 0) { + exit(EXIT_SUCCESS); + } + + for (;;) { + kevent(kq, NULL, 0, &kev, 1, NULL); + if (stat(argv[1], &sb) == 0) { + break; + } + } + + exit(EXIT_SUCCESS); +} diff --git a/wait4path/wait4path.version b/wait4path/wait4path.version new file mode 100644 index 0000000..b01adfa --- /dev/null +++ b/wait4path/wait4path.version @@ -0,0 +1,5 @@ +DARWIN_BUNDLE_IDENTIFIER="com.apple.system_cmds.wait4path" +DARWIN_DISPLAY_NAME="Darwin Filesystem Path Waiter" +DARWIN_DISPLAY_VERSION="1.0.0" +DARWIN_INCREMENTAL_VERSION="$CURRENT_PROJECT_VERSION" +DARWIN_COPYRIGHT="Copyright 2015 Apple Inc. All rights reserved." diff --git a/wordexp-helper.tproj/wordexp-helper.c b/wordexp-helper.tproj/wordexp-helper.c index ab82c10..7ed025a 100644 --- a/wordexp-helper.tproj/wordexp-helper.c +++ b/wordexp-helper.tproj/wordexp-helper.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All rights reserved. + * Copyright (c) 2013-2016 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, @@ -17,7 +17,7 @@ * 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@ */ diff --git a/xcconfigs/base.xcconfig b/xcconfigs/base.xcconfig new file mode 100644 index 0000000..c01bea8 --- /dev/null +++ b/xcconfigs/base.xcconfig @@ -0,0 +1,88 @@ +#include "/Makefiles/CoreOS/Xcode/BSD.xcconfig" +#include "/AppleInternal/XcodeConfig/PlatformSupport.xcconfig" + +XPC_BUILD_FILES_DIR = $(PROJECT_DIR)/xcfiles +XPC_BUILD_XCSCRIPTS_DIR = $(PROJECT_DIR)/xcscripts +XPC_BUILD_XCCONFIG_DIR = $(PROJECT_DIR)/xcconfig + +XPC_BUILD_HEADER_SEARCH_PATHS = $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(PROJECT_DIR)/src $(PROJECT_DIR)/interface $(PROJECT_DIR)/launch $(PROJECT_DIR)/support $(PROJECT_DIR)/development $(PROJECT_DIR) + +XPC_ALL_THE_DEBUGS2 = +XPC_ALL_THE_DEBUGS2_yes = -O0 -g -fno-inline -fno-limit-debug-info + +XPC_COMPATIBILITY_DEFINES_currentmajor = -DHAVE_KDEBUG_TRACE=1 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=0 -DHAVE_GALARCH_AVAILABILITY=1 +XPC_COMPATIBILITY_DEFINES_lastmajor = -DHAVE_KDEBUG_TRACE=0 -DCONFIG_EMULATE_XNU_INITPROC_SELECTION=1 -DHAVE_GALARCH_AVAILABILITY=0 +XPC_BUILD_HOST = currentmajor + +XPC_BUILD_EXPORT_DEFAULTS = -DXPC_PROJECT_EXPORT=XPC_EXPORT -DXPC_DEBUGEXPORT=XPC_NOEXPORT -DXPC_TESTEXPORT=XPC_NOEXPORT +XPC_BUILD_OTHER_CFLAGS = $(XPC_ALL_THE_DEBUGS2_$(XPC_ALL_THE_DEBUGS)) $(XPC_COMPATIBILITY_DEFINES_$(XPC_BUILD_HOST)) -D__XPC_PROJECT_BUILD__=1 + +XPC_CRASHREPORTCLIENT_LDFLAGS = -lCrashReporterClient + +XPC_NOSTRIP = no +XPC_NOSTRIP2_no = YES +XPC_NOSTRIP2_yes = NO + +// Building. +ARCHS = $(ARCHS_STANDARD) +ONLY_ACTIVE_ARCH = NO +GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VARIABLE = YES +GCC_TREAT_WARNINGS_AS_ERRORS = YES +GCC_SYMBOLS_PRIVATE_EXTERN = YES +GCC_ENABLE_OBJC_GC = unsupported +GCC_ENABLE_BUILTIN_FUNCTIONS = YES +GCC_WARN_UNINITIALIZED_AUTOS = YES +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNINITIALIZED_AUTOS = YES +GCC_WARN_UNUSED_VARIABLE = YES + +CLANG_WARN_CONSTANT_CONVERSION = YES +CLANG_WARN_INT_CONVERSION = YES +CLANG_WARN_EMPTY_BODY = YES +CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym + +OTHER_CFLAGS = $(XPC_BUILD_OTHER_CFLAGS) + +// We pretty much want to avoid anything having to do with Xcode's default +// header search behavior. +ALWAYS_SEARCH_USER_PATHS = NO +USE_HEADERMAP = NO +HEADER_SEARCH_PATHS = $(XPC_BUILD_HEADER_SEARCH_PATHS) + +// Deployment and linking. +// By default, clang will link any binary using Objective-C against Foundation. +// We need to opt out of this to avoid a layering inversion. +// +// +CLANG_LINK_OBJC_RUNTIME = NO +CLANG_MODULES_AUTOLINK = NO + +DYLIB_CURRENT_VERSION = $(RC_ProjectSourceVersion) +DYLIB_COMPATIBILITY_VERSION = 1 +DEPLOYMENT_LOCATION = YES + +// Preprocessing the Info.plist sends it through the C preprocessor. You cannot +// use both of these options together, since they emit different files to +// different places. I'm putting them here mostly just so I don't forget what +// they're called in case we do want to start using them in the future. +INFOPLIST_PREPROCESS = NO +INFOPLIST_EXPAND_BUILD_SETTINGS = NO + +// SEPARATE_STRIP will tell the linker to not strip the emitted binary. Instead, +// the strip will happen as a separate invocation of the strip(1) tool, leaving +// the binaries in our OBJROOT untouched but stripping the ones that go into the +// DSTROOT and SYMROOT. INSTALLED_PRODUCT_ASIDES makes it so that the stuff in +// the SYMROOT is not just symlinked into the DSTROOT, which lets us preserve +// the symbols for the stuff in there. +STRIP_INSTALLED_PRODUCT = $(XPC_NOSTRIP2_$(XPC_NOSTRIP)) + +// STRIP_INSTALLED_PRODUCT does not appear to be respected on a per-variant +// basis, so this does nothing. +STRIP_INSTALLED_PRODUCT_debug = NO +INSTALLED_PRODUCT_ASIDES = YES +SEPARATE_STRIP = YES diff --git a/xcconfigs/development.xcconfig b/xcconfigs/development.xcconfig new file mode 100644 index 0000000..16edd7b --- /dev/null +++ b/xcconfigs/development.xcconfig @@ -0,0 +1,29 @@ +// This is the configuration file for building XPC's executables' development +// support bundle, which houses code that we want to be able to use internally +// in certain tools, but we don't want to ship externally. +#include "executable.xcconfig" + +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator +VALID_ARCHS[sdk=macosx*] = i386 x86_64 + +XPC_SUPPORT_INSTALL_PATH = /usr/local/lib/xpc + +OTHER_CFLAGS = $(XPC_EXECUTABLE_OTHER_CFLAGS) -D__XPC_BUILDING_XPCDEVELOPMENT__=1 +HEADER_SEARCH_PATHS = $(XPC_BUILD_HEADER_SEARCH_PATHS) $(PROJECT_DIR)/development + +// This is a bundle, which is not stamped by our version-stamping script, so we +// expand the build variables in the Info.plist. +INFOPLIST_EXPAND_BUILD_SETTINGS = YES +INFOPLIST_FILE = development/Info.plist + +GCC_ENABLE_OBJC_GC = unsupported +// +GCC_ENABLE_OBJC_GC[sdk=macosx*] = supported + +// Deployment and linking. +MACH_O_TYPE = mh_bundle +PRODUCT_NAME = development +WRAPPER_EXTENSION = bundle +INSTALL_PATH_ACTUAL = $(XPC_SUPPORT_INSTALL_PATH) +OTHER_LDFLAGS = $(XPC_EXECUTABLE_OTHER_LDFLAGS) +STRIP_STYLE = non-global diff --git a/xcconfigs/executable.xcconfig b/xcconfigs/executable.xcconfig new file mode 100644 index 0000000..57a600a --- /dev/null +++ b/xcconfigs/executable.xcconfig @@ -0,0 +1,45 @@ +// This configuration file contains common build settings for all of libxpc's +// executable targets. +#include "base.xcconfig" + +XPC_EXECUTABLE_OTHER_CFLAGS = $(XPC_BUILD_OTHER_CFLAGS) $(XPC_BUILD_EXPORT_DEFAULTS) -DXPC_BUILD_TARGET_EXECUTABLE=1 +XPC_EXECUTABLE_OTHER_LDFLAGS = $(XPC_CRASHREPORTCLIENT_LDFLAGS) +XPC_EXECUTABLE_WORKAROUND_14483011 = -lSystem -lobjc + +// Building. +VALID_ARCHS[sdk=macosx*] = x86_64 +GCC_ENABLE_OBJC_EXCEPTIONS = YES +INFOPLIST_FILE = +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator +OTHER_CFLAGS = $(XPC_EXECUTABLE_OTHER_CFLAGS) + +// Work around asinine default tools behavior of adding entitlements to every +// generated binary. +// +// +// +WANTS_GET_TASK_ALLOW = NO + +// Deployment linking. +MACH_O_TYPE = mh_execute +PRODUCT_NAME = xpc_executables +EXECUTABLE_PREFIX = +FRAMEWORK_SEARCH_PATHS = $(SDKROOT)/System/Library/PrivateFrameworks $(inherited) +STRIP_STYLE = all +XPC_EXECUTABLE_OTHER_LDFLAGS = $(XPC_EXECUTABLE_WORKAROUND_14483011) $(XPC_CRASHREPORTCLIENT_LDFLAGS) +CREATE_INFOPLIST_SECTION_IN_BINARY = YES + +// Output our launchd plist as binary on iOS. +APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*] = YES +PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*] = binary + +// For building variants +DARWIN_VARIANT_LOWER_RELEASE = release +DARWIN_VARIANT_SUFFIX_RELEASE = +DARWIN_VARIANT_LOWER_DEVELOPMENT = development +DARWIN_VARIANT_SUFFIX_DEVELOPMENT = .development +DARWIN_VARIANT_LOWER_DEBUG = debug +DARWIN_VARIANT_SUFFIX_DEBUG = .debug + +DARWIN_VARIANT_LOWER = $(DARWIN_VARIANT_LOWER_$(DARWIN_VARIANT)) +DARWIN_VARIANT_SUFFIX = $(DARWIN_VARIANT_SUFFIX_$(DARWIN_VARIANT)) diff --git a/xcconfigs/wait4path.xcconfig b/xcconfigs/wait4path.xcconfig new file mode 100644 index 0000000..81909c4 --- /dev/null +++ b/xcconfigs/wait4path.xcconfig @@ -0,0 +1,16 @@ +#include "executable.xcconfig" + +SUPPORTED_PLATFORMS = macosx + +DARWIN_VARIANT = RELEASE +#include "../wait4path/wait4path.version" + +HEADER_SEARCH_PATHS = $(XPC_BUILD_HEADER_SEARCH_PATHS) $(PROJECT_DIR)/wait4path +OTHER_CFLAGS = $(XPC_EXECUTABLE_OTHER_CFLAGS) $(XPC_BUILD_EXPORT_DEFAULTS) -D__XPC_BUILDING_WAIT4PATH__=1 +OTHER_LDFLAGS = $(XPC_EXECUTABLE_OTHER_LDFLAGS) + +# wait4path doesn't actually need -lCrashReporterClient +XPC_CRASHREPORTCLIENT_LDFLAGS = "" + +INSTALL_PATH = /bin +PRODUCT_NAME = wait4path diff --git a/xscripts/darwinversion.sh b/xscripts/darwinversion.sh new file mode 100644 index 0000000..965bc35 --- /dev/null +++ b/xscripts/darwinversion.sh @@ -0,0 +1,228 @@ +#!/bin/sh + +# This script is intended to generate version information for single-file +# products (i.e. things that don't ship in bundles). It takes an input file +# with the suffix ".version" that defines: +# +# DARWIN_BUNDLE_IDENTIFIER +# The CFBundleIdentifier for the product. +# DARWIN_DISPLAY_NAME +# The "marketing" name of the product ("Darwin System Bootstrapper" as opposed +# to "launchd" or "Darwin Kernel" as opposed to "xnu"). +# DARWIN_DISPLAY_VERSION +# The major release version (think "7.0" for iOS 7, "10.9" for Mavericks, +# etc.). +# DARWIN_INCREMENTAL_VERSION +# The incremental version (think 12A132, svn revision, project tag, etc.). +# DARWIN_COPYRIGHT +# The copyright string. +# +# It produces a header (darwin_version.h) that declares: +# +# __darwin_builder_version +# The integer representation of the version of OS X which built the project +# (think 1090, 1091, etc.). +# __darwin_builder_build +# The integer representation of the build of OS X which built the project, +# represented in hex (think 0x12A132). +# __darwin_build_inc_version +# A string representation of the given DARWIN_INCREMENTAL_VERSION. +# __darwin_version_string +# A composed version string which can serve as useful for identifying the +# version, variant and origin of a given build. It is formatted as: +# +# $DARWIN_DISPLAY_NAME Version $DARWIN_DISPLAY_VERSION `date`; `whoami`: +# +# is a symbolic link in the OBJROOT pointing to the subdirectory +# containing the objects for the target being built. The link's name is +# formatted as: +# +# ${BASE_PRODUCT_NAME}/${DARWIN_VARIANT}_${UPPER_CASE_CURRENT_ARCH} +# +# The BASE_PRODUCT_NAME is the first part of the target's PRODUCT_NAME, prior +# to a '.' character (so the base product name of "launchd.development" is +# simply "launchd"). +# +# This link points to the appropriate location in the build root. If the SDK +# being built for is the Simulator, the variant is formatted as: +# +# ${DARWIN_VARIANT}_SIMULATOR_${UPPER_CASE_CURRENT_ARCH} +# +# It produces an XML Info.plist from this information and embeds it in the +# __TEXT,__info_plist section of the resulting binary. + +. ${INPUT_FILE_PATH} + +baseproductname=${PRODUCT_NAME/.*/} +builder_version=`sw_vers -productVersion` +builder_build=`sw_vers -buildVersion` +brewedondate=`date` +brewedby=`whoami` + +if [ $SUDO_USER ]; then + brewedby="$SUDO_USER" +fi + +release="Unknown" +if [[ "$DARWIN_VARIANT" != "RELEASE" && -n "$RC_RELEASE" ]]; then + release="$RC_RELEASE" +fi + +# Distill the version down to its base OS. The builders could be running 10.7.2, +# for example, but the availability macros on OS X only handle major version +# availability. +builder_version_int=${builder_version/.} +builder_version_int=${builder_version_int/.*} +builder_version_int="${builder_version_int}0" + +# Builders don't typically run on later SU trains. They'll usually move to the +# next major release. +if [[ "$builder_build" =~ [g-zG-Z] ]]; then + builder_build="1A1" +fi + +destdir="${DERIVED_SOURCES_DIR}/${CURRENT_ARCH}" +mkdir -p "$destdir" + +thehfile="$destdir/darwin_version.h" +thecfile="$destdir/darwin_version.c" + +# Hack to emulate how xnu's version works. It has the nice feature of printing +# the OBJROOT of the current xnu, which is different based on build variant and +# architecture. But in our case, the OBJROOT is buried a few levels deep, so we +# create a symlink in the OBJROOT to point to that, or else we'd have to embed +# a much longer path in the version. +mkdir -p "${OBJROOT}/$baseproductname" +cd "${OBJROOT}/$baseproductname" + +rootwithslash="${OBJROOT}/" +objpath=`eval echo -n \\$OBJECT_FILE_DIR_\$CURRENT_VARIANT` + +capsarch=`echo $CURRENT_ARCH | tr "[:lower:]" "[:upper:]"` +# Xcode does not provide an OBJECT_FILE_DIR_$CURRENT_VARIANT_$CURRENT_ARCH, so +# we have to interpolate the last part of the path. +objpath=$objpath/$CURRENT_ARCH +subpath=${objpath#${rootwithslash}} + +if [[ "${PLATFORM_NAME}" =~ "simulator" ]]; then + linkname="${DARWIN_VARIANT}_SIMULATOR_${capsarch}" +else + linkname="${DARWIN_VARIANT}_${capsarch}" +fi + +objects=`basename ${OBJROOT}` +if [[ "$objects" = "Objects" ]]; then + # Newer XBSs put the OBJROOT in an "Objects" subdirectory under the build + # root. + oldwd=`pwd` + cd "${OBJROOT}" + cd .. + + objects=`dirname ${OBJROOT}` + objects=`basename $objects` + objects="${objects/_install/}" + + ln -fs "Objects" "$objects" + + cd "$oldwd" +fi +objects="$objects/$baseproductname/$linkname" + +ln -s ../${subpath} $linkname +version_string="$DARWIN_DISPLAY_NAME Version $DARWIN_DISPLAY_VERSION: $brewedondate; $brewedby:$objects" + +# Generate the symbol root. +binarywithsyms="$SYMROOT/$PRODUCT_NAME" +if [[ $SYMROOT =~ ^/BinaryCache/ ]]; then + # XBS tosses symbols and roots into /BinaryCache on the builder, so sniff + # that out and generate the appropriate path. Otherwise, just use the given + # local SYMROOT. + symrootsubpath=${SYMROOT#"/BinaryCache/"} + binarywithsyms="~rc/Software/$release/BuildRecords/$symrootsubpath/$PRODUCT_NAME" +fi + +echo "*** Stamping project build:" +echo "*** Release: $release" +echo "*** Builder Version: $builder_version" +echo "*** Builder Build: $builder_build" +echo "*** Project Version: $CURRENT_PROJECT_VERSION" +echo "*** Version String: $version_string" +echo "*** Object Root: $objects" +echo "*** Debugging Binary: $binarywithsyms" + +# Generate Info.plist +infoplist="$destdir"/Info.plist +/usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $DARWIN_BUNDLE_IDENTIFIER" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleName string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleName $PRODUCT_NAME" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleDisplayName string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $DARWIN_DISPLAY_NAME" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleExecutable string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable $EXECUTABLE_NAME" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleInfoDictionaryVersion string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleInfoDictionaryVersion 6.0" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $DARWIN_DISPLAY_VERSION" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :CFBundleVersion string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $DARWIN_INCREMENTAL_VERSION" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :NSHumanReadableCopyright string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :NSHumanReadableCopyright $DARWIN_COPYRIGHT" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DarwinVariant string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DarwinVariant $DARWIN_VARIANT" -c "Save" $infoplist > /dev/null +# codesign can't deal with the Info.plist for each slice having different +# content, so don't encode architecture-specific information for now. +# +# +#/usr/libexec/PlistBuddy -c "Add :DarwinArchitecture string" -c "Save" $infoplist > /dev/null +#/usr/libexec/PlistBuddy -c "Set :DarwinArchitecture $CURRENT_ARCH" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DarwinBuilderVersion string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DarwinBuilderVersion $builder_version" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DarwinBuilderBuild string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DarwinBuilderBuild $builder_build" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTSDKName string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTSDKName $SDK_NAME" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTSDKBuild string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTSDKBuild $PLATFORM_PRODUCT_BUILD_VERSION" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTXcodeBuild string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTXcodeBuild $XCODE_PRODUCT_BUILD_VERSION" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTCompiler string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTCompiler $DEFAULT_COMPILER" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTPlatformName string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTPlatformName $PLATFORM_NAME" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTPlatformVersion string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTPlatformVersion $IPHONEOS_DEPLOYMENT_TARGET" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Add :DTXcode string" -c "Save" $infoplist > /dev/null +/usr/libexec/PlistBuddy -c "Set :DTXcode $XCODE_VERSION_ACTUAL" -c "Save" $infoplist > /dev/null +infoplistcontents=`cat $infoplist` + +rm -f "$thehfile" +echo "#ifndef __DARWIN_VERSION_H__" >> "$thehfile" +echo "#define __DARWIN_VERSION_H__" >> "$thehfile" +echo "const unsigned long __darwin_builder_version;" >> "$thehfile" +echo "const unsigned long __darwin_builder_build;" >> "$thehfile" +echo "const char *__darwin_build_inc_version;" >> "$thehfile" +echo "const char *__darwin_version_string;" >> "$thehfile" +echo "const char *__darwin_variant;" >> "$thehfile" +echo "const char *__darwin_debug_binary;" >> "$thehfile" +echo "#endif // __DARWIN_VERSION_H__" >> "$thehfile" +echo "" >> "$thehfile" + +rm -f "$thecfile" +echo "__attribute__((__used__)) const unsigned long __darwin_builder_version = $builder_version_int;" >> "$thecfile" +echo "__attribute__((__used__)) const unsigned long __darwin_builder_build = 0x$builder_build;" >> "$thecfile" +echo "__attribute__((__used__)) const char *__darwin_build_inc_version = \"$CURRENT_PROJECT_VERSION\";" >> "$thecfile" +echo "__attribute__((__used__)) const char *__darwin_version_string = \"$version_string\";" >> "$thecfile" +echo "__attribute__((__used__)) const char *__darwin_variant = \"$DARWIN_VARIANT\";" >> "$thecfile" +echo "__attribute__((__used__)) const char *__darwin_version_string_heywhat = \"@(#)VERSION:$version_string\";" >> "$thecfile" +echo "__attribute__((__used__)) const char *__darwin_debug_binary = \"$binarywithsyms\";" >> "$thecfile" + +# Embed the Info.plist in the __TEXT,__info_plist section. +echo "__attribute__((__used__))" >> "$thecfile" + +echo "__attribute__((__section__(\"__TEXT,__info_plist\")))" >> "$thecfile" +echo -n "static const char __darwin_info_plist[] = \"" >> "$thecfile" +echo -n "$infoplistcontents" | sed -e 's/\"/\\"/g' | tr -d '\n' >> "$thecfile" +echo "\";" >> "$thecfile" + +echo "" >> "$thecfile" diff --git a/zdump.tproj/zdump.c b/zdump.tproj/zdump.c index 6779ea1..7068cdf 100644 --- a/zdump.tproj/zdump.c +++ b/zdump.tproj/zdump.c @@ -1,7 +1,8 @@ static const char elsieid[] = "@(#)zdump.c 7.31"; #ifndef lint -static const char rcsid[] = +#include +__unused static const char rcsid[] = "$FreeBSD: src/usr.sbin/zic/zdump.c,v 1.10 2008/02/19 07:09:19 ru Exp $"; #endif /* not lint */ @@ -135,16 +136,14 @@ static void show P((char * zone, time_t t, int v)); static void usage(void); int -main(argc, argv) -int argc; -char * argv[]; +main(int argc, char *argv[]) { - register int i; - register int c; - register int vflag; - register char * cutoff; - register int cutyear; - register long cuttime; + int i; + int c; + int vflag; + char * cutoff; + int cutyear; + long cuttime; char ** fakeenv; time_t now; time_t t; @@ -203,8 +202,8 @@ char * argv[]; continue; #endif { - register int from; - register int to; + int from; + int to; for (i = 0; environ[i] != NULL; ++i) continue; @@ -304,10 +303,7 @@ _("usage: zdump [--version] [-v] [-c cutoff] zonename ...\n")); } static time_t -hunt(name, lot, hit) -char * name; -time_t lot; -time_t hit; +hunt(char *name, time_t lot, time_t hit) { time_t t; struct tm lotm; @@ -340,9 +336,7 @@ time_t hit; */ static long -delta(newp, oldp) -struct tm * newp; -struct tm * oldp; +delta(struct tm *newp, struct tm *oldp) { long result; int tmy; @@ -363,10 +357,7 @@ struct tm * oldp; } static void -show(zone, t, v) -char * zone; -time_t t; -int v; +show(char *zone, time_t t, int v) { struct tm * tmp; @@ -387,10 +378,9 @@ int v; } static char * -abbr(tmp) -struct tm * tmp; +abbr(struct tm *tmp) { - register char * result; + char * result; static char nada; if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) diff --git a/zic.tproj/generate_zone_file_list.sh b/zic.tproj/generate_zone_file_list.sh index 839dd63..c28c4da 100755 --- a/zic.tproj/generate_zone_file_list.sh +++ b/zic.tproj/generate_zone_file_list.sh @@ -1,4 +1,6 @@ #!/bin/sh +set -e +set -x # we need to know where the data files are... if [ $# -ne 1 ]; then @@ -7,7 +9,7 @@ if [ $# -ne 1 ]; then fi DATFILES="$1" -ZONE_FILES="$(egrep --files-with-match '^(Zone|Rule|Link)' ${DATFILES}/* | awk -F "/" '{print $NF}')" +ZONE_FILES="$(egrep --files-with-match '^(Zone|Rule|Link)' "${DATFILES}"/* | awk -F "/" '{print $NF}')" for tz in ${ZONE_FILES}; do if [ ${tz} = "backward" ]; then diff --git a/zic.tproj/generate_zoneinfo.sh b/zic.tproj/generate_zoneinfo.sh index 6b921d1..16484d1 100755 --- a/zic.tproj/generate_zoneinfo.sh +++ b/zic.tproj/generate_zoneinfo.sh @@ -44,14 +44,14 @@ VERSIONFILE="${ZONEINFO}/+VERSION" mkdir -p "${DATFILES}" mkdir -p "${ZONEINFO}" tar zxf "${TARBALL}" -C "${DATFILES}" -ZONE_FILES="$(${SRCROOT}/zic.tproj/generate_zone_file_list.sh ${DATFILES})" +ZONE_FILES="$("${SRCROOT}"/zic.tproj/generate_zone_file_list.sh "${DATFILES}")" for tz in ${ZONE_FILES}; do if [ ${tz} = "northamerica" ]; then ARG="-p America/New_York" else ARG="" fi - ${ZICHOST} ${ARG} -L /dev/null -d "${ZONEINFO}" \ + "${ZICHOST}" ${ARG} -L /dev/null -d "${ZONEINFO}" \ -y "${DATFILES}/yearistype.sh" "${DATFILES}/${tz}" || exit 1 done @@ -67,7 +67,13 @@ if [ $? -ne 0 ]; then exit 1 fi -case "$PLATFORM_NAME" in +if [ -n "$RC_BRIDGE" ]; then + ACTUAL_PLATFORM_NAME="bridge${PLATFORM_NAME#watch}" +else + ACTUAL_PLATFORM_NAME="${PLATFORM_NAME}" +fi + +case "$ACTUAL_PLATFORM_NAME" in iphone*|appletv*|watch*) mkdir -p "${PRIVATEDIR}/var/db" mkdir -p -m a+rx "${PRIVATEDIR}/var/db/timezone" @@ -75,12 +81,12 @@ iphone*|appletv*|watch*) # 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" ;; -macosx) +macosx|bridge*) mkdir -p "${PRIVATEDIR}/etc" ln -hfs "/usr/share/zoneinfo/${LOCALTIME}" "${PRIVATEDIR}/etc/localtime" ;; *) - echo "Unsupported platform: $PLATFORM_NAME" + echo "Unsupported platform: $ACTUAL_PLATFORM_NAME" exit 1 ;; esac diff --git a/zic.tproj/ialloc.c b/zic.tproj/ialloc.c index c81ef8b..fabe0c6 100644 --- a/zic.tproj/ialloc.c +++ b/zic.tproj/ialloc.c @@ -1,11 +1,12 @@ +#include #ifndef lint #ifndef NOID -static const char elsieid[] = "@(#)ialloc.c 8.29"; +__unused static const char elsieid[] = "@(#)ialloc.c 8.29"; #endif /* !defined NOID */ #endif /* !defined lint */ #ifndef lint -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/usr.sbin/zic/ialloc.c,v 1.6 2000/11/28 18:18:56 charnier Exp $"; #endif /* not lint */ @@ -16,39 +17,32 @@ static const char rcsid[] = #define nonzero(n) (((n) == 0) ? 1 : (n)) char * -imalloc(n) -const int n; +imalloc(const size_t n) { - return malloc((size_t) nonzero(n)); + return malloc(nonzero(n)); } char * -icalloc(nelem, elsize) -int nelem; -int elsize; +icalloc(size_t nelem, size_t elsize) { if (nelem == 0 || elsize == 0) nelem = elsize = 1; - return calloc((size_t) nelem, (size_t) elsize); + return calloc(nelem, elsize); } void * -irealloc(pointer, size) -void * const pointer; -const int size; +irealloc(void * const pointer, const size_t size) { if (pointer == NULL) return imalloc(size); - return realloc((void *) pointer, (size_t) nonzero(size)); + return realloc((void *) pointer, nonzero(size)); } char * -icatalloc(old, new) -char * const old; -const char * const new; +icatalloc(char * const old, const char * const new) { - register char * result; - register int oldsize, newsize; + char * result; + size_t oldsize, newsize; newsize = (new == NULL) ? 0 : strlen(new); if (old == NULL) @@ -63,23 +57,20 @@ const char * const new; } char * -icpyalloc(string) -const char * const string; +icpyalloc(const char * const string) { return icatalloc((char *) NULL, string); } void -ifree(p) -char * const p; +ifree(char * const p) { if (p != NULL) (void) free(p); } void -icfree(p) -char * const p; +icfree(char * const p) { if (p != NULL) (void) free(p); diff --git a/zic.tproj/install_zoneinfo.sh b/zic.tproj/install_zoneinfo.sh index 94846aa..9bb9af9 100755 --- a/zic.tproj/install_zoneinfo.sh +++ b/zic.tproj/install_zoneinfo.sh @@ -2,16 +2,22 @@ set -e set -x -case "$PLATFORM_NAME" in +if [ -n "$RC_BRIDGE" ]; then + ACTUAL_PLATFORM_NAME="bridge${PLATFORM_NAME#watch}" +else + ACTUAL_PLATFORM_NAME="${PLATFORM_NAME}" +fi + +case "$ACTUAL_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) +macosx|bridge*) ditto "${BUILT_PRODUCTS_DIR}/zoneinfo" "${DSTROOT}/usr/share/zoneinfo" ;; *) - echo "Unsupported platform: $PLATFORM_NAME" + echo "Unsupported platform: $ACTUAL_PLATFORM_NAME" exit 1 ;; esac diff --git a/zic.tproj/private.h b/zic.tproj/private.h index 47d9cb2..4ffd069 100644 --- a/zic.tproj/private.h +++ b/zic.tproj/private.h @@ -104,11 +104,11 @@ static const char privatehid[] = "@(#)private.h 7.53"; /* ** Private function declarations. */ -char * icalloc P((int nelem, int elsize)); +char * icalloc P((size_t nelem, size_t elsize)); char * icatalloc P((char * old, const char * new)); char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); +char * imalloc P((size_t n)); +void * irealloc P((void * pointer, size_t size)); void icfree P((char * pointer)); void ifree P((char * pointer)); char * scheck P((const char *string, const char *format)); diff --git a/zic.tproj/scheck.c b/zic.tproj/scheck.c index 009ef1e..dcd4d01 100644 --- a/zic.tproj/scheck.c +++ b/zic.tproj/scheck.c @@ -1,11 +1,12 @@ #ifndef lint #ifndef NOID -static const char elsieid[] = "@(#)scheck.c 8.15"; +#include +__unused static const char elsieid[] = "@(#)scheck.c 8.15"; #endif /* !defined lint */ #endif /* !defined NOID */ #ifndef lint -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/usr.sbin/zic/scheck.c,v 1.7 2001/07/18 11:27:04 dd Exp $"; #endif /* not lint */ @@ -14,17 +15,15 @@ static const char rcsid[] = #include "private.h" char * -scheck(string, format) -const char * const string; -const char * const format; +scheck(const char * const string, const char * const format) { - register char * fbuf; - register const char * fp; - register char * tp; - register int c; - register char * result; - char dummy; - static char nada; + char * fbuf; + const char * fp; + char * tp; + int c; + char * result; + char dummy; + static char nada; result = &nada; if (string == NULL || format == NULL) diff --git a/zic.tproj/zic.c b/zic.tproj/zic.c index 7d02a4c..8efedaa 100644 --- a/zic.tproj/zic.c +++ b/zic.tproj/zic.c @@ -1,7 +1,8 @@ static const char elsieid[] = "@(#)zic.c 7.116"; +#include #ifndef lint -static const char rcsid[] = +__unused static const char rcsid[] = "$FreeBSD: src/usr.sbin/zic/zic.c,v 1.18 2007/12/03 10:45:44 kevlo Exp $"; #endif /* not lint */ @@ -349,8 +350,7 @@ static char roll[TZ_MAX_LEAPS]; */ static char * -memcheck(ptr) -char * const ptr; +memcheck(char * const ptr) { if (ptr == NULL) errx(EXIT_FAILURE, _("memory exhausted")); @@ -368,8 +368,7 @@ char * const ptr; #if !(HAVE_STRERROR - 0) static char * -strerror(errnum) -int errnum; +strerror(int errnum) { extern char * sys_errlist[]; extern int sys_nerr; @@ -380,11 +379,8 @@ int errnum; #endif /* !(HAVE_STRERROR - 0) */ static void -eats(name, num, rname, rnum) -const char * const name; -const int num; -const char * const rname; -const int rnum; +eats(const char * const name, const int num, const char * const rname, + const int rnum) { filename = name; linenum = num; @@ -393,16 +389,13 @@ const int rnum; } static void -eat(name, num) -const char * const name; -const int num; +eat(const char * const name, const int num) { eats(name, num, (char *) NULL, -1); } static void -error(string) -const char * const string; +error(const char * const string) { /* ** Match the format of "cc" to allow sh users to @@ -419,8 +412,7 @@ const char * const string; } static void -warning(string) -const char * const string; +warning(const char * const string) { char * cp; @@ -453,13 +445,11 @@ static mode_t mflag = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); int -main(argc, argv) -int argc; -char * argv[]; +main(int argc, char * argv[]) { - register int i; - register int j; - register int c; + int i; + int j; + int c; #ifdef unix (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); @@ -586,12 +576,10 @@ _("more than one -L option specified")); } static void -dolink(fromfile, tofile) -const char * const fromfile; -const char * const tofile; +dolink(const char * const fromfile, const char * const tofile) { - register char * fromname; - register char * toname; + char * fromname; + char * toname; if (fromfile[0] == '/') fromname = ecpyalloc(fromfile); @@ -625,7 +613,7 @@ const char * const tofile; access(fromname, F_OK) == 0 && !itsdir(fromname)) { const char *s = tofile; - register char * symlinkcontents = NULL; + char * symlinkcontents = NULL; while ((s = strchr(s+1, '/')) != NULL) symlinkcontents = ecatalloc(symlinkcontents, "../"); symlinkcontents = ecatalloc(symlinkcontents, fromfile); @@ -685,11 +673,10 @@ setboundaries P((void)) } static int -itsdir(name) -const char * const name; +itsdir(const char * const name) { - register char * myname; - register int accres; + char * myname; + int accres; myname = ecpyalloc(name); myname = ecatalloc(myname, "/."); @@ -707,9 +694,7 @@ const char * const name; */ static int -rcomp(cp1, cp2) -const void * cp1; -const void * cp2; +rcomp(const void *cp1, const void *cp2) { return strcmp(((const struct rule *) cp1)->r_name, ((const struct rule *) cp2)->r_name); @@ -718,10 +703,10 @@ const void * cp2; static void associate P((void)) { - register struct zone * zp; - register struct rule * rp; - register int base, out; - register int i, j; + struct zone * zp; + struct rule * rp; + int base, out; + int i, j; if (nrules != 0) { (void) qsort((void *) rules, (size_t) nrules, @@ -792,17 +777,16 @@ associate P((void)) } static void -infile(name) -const char * name; +infile(const char * name) { - register FILE * fp; - register char ** fields; - register char * cp; - register const struct lookup * lp; - register int nfields; - register int wantcont; - register int num; - char buf[BUFSIZ]; + FILE * fp; + char ** fields; + char * cp; + const struct lookup * lp; + int nfields; + int wantcont; + int num; + char buf[BUFSIZ]; if (strcmp(name, "-") == 0) { name = _("standard input"); @@ -880,10 +864,7 @@ _("panic: invalid l_value %d"), lp->l_value); */ static long -gethms(string, errstring, signable) -const char * string; -const char * const errstring; -const int signable; +gethms(const char *string, const char * const errstring, const int signable) { int hh, mm, ss, sign; @@ -919,9 +900,7 @@ const int signable; } static void -inrule(fields, nfields) -register char ** const fields; -const int nfields; +inrule(char ** const fields, const int nfields) { static struct rule r; @@ -946,11 +925,9 @@ const int nfields; } static int -inzone(fields, nfields) -register char ** const fields; -const int nfields; +inzone(char ** const fields, const int nfields) { - register int i; + int i; static char * buf; if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { @@ -991,9 +968,7 @@ _("duplicate zone name %s (file \"%s\", line %d)"), } static int -inzcont(fields, nfields) -register char ** const fields; -const int nfields; +inzcont(char ** const fields, const int nfields) { if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { error(_("wrong number of fields on Zone continuation line")); @@ -1003,17 +978,14 @@ const int nfields; } static int -inzsub(fields, nfields, iscont) -register char ** const fields; -const int nfields; -const int iscont; +inzsub(char ** const fields, const int nfields, const int iscont) { - register char * cp; + char * cp; static struct zone z; - register int i_gmtoff, i_rule, i_format; - register int i_untilyear, i_untilmonth; - register int i_untilday, i_untiltime; - register int hasuntil; + int i_gmtoff, i_rule, i_format; + int i_untilyear, i_untilmonth; + int i_untilday, i_untiltime; + int hasuntil; if (iscont) { i_gmtoff = ZFC_GMTOFF; @@ -1080,16 +1052,14 @@ const int iscont; } static void -inleap(fields, nfields) -register char ** const fields; -const int nfields; +inleap(char ** const fields, const int nfields) { - register const char * cp; - register const struct lookup * lp; - register int i, j; - int year, month, day; - long dayoff, tod; - time_t t; + const char * cp; + const struct lookup * lp; + int i, j; + int year, month, day; + long dayoff, tod; + time_t t; if (nfields != LEAP_FIELDS) { error(_("wrong number of fields on Leap line")); @@ -1149,8 +1119,8 @@ const int nfields; tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); cp = fields[LP_CORR]; { - register int positive; - int count; + int positive; + int count; if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */ positive = FALSE; @@ -1177,9 +1147,7 @@ const int nfields; } static void -inlink(fields, nfields) -register char ** const fields; -const int nfields; +inlink(char ** const fields, const int nfields) { struct link l; @@ -1205,19 +1173,15 @@ const int nfields; } static void -rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep) -register struct rule * const rp; -const char * const loyearp; -const char * const hiyearp; -const char * const typep; -const char * const monthp; -const char * const dayp; -const char * const timep; +rulesub(struct rule * const rp, const char * const loyearp, + const char * const hiyearp, const char * const typep, + const char * const monthp, const char * const dayp, + const char * const timep) { - register const struct lookup * lp; - register const char * cp; - register char * dp; - register char * ep; + const struct lookup * lp; + const char * cp; + char * dp; + char * ep; if ((lp = byword(monthp, mon_names)) == NULL) { error(_("invalid month name")); @@ -1361,21 +1325,17 @@ const char * const timep; } static void -convert(val, buf) -const long val; -char * const buf; +convert(const long val, char * const buf) { - register int i; - register long shift; + int i; + long shift; for (i = 0, shift = 24; i < 4; ++i, shift -= 8) buf[i] = val >> shift; } static void -puttzcode(val, fp) -const long val; -FILE * const fp; +puttzcode(const long val, FILE * const fp) { char buf[4]; @@ -1384,23 +1344,20 @@ FILE * const fp; } static int -atcomp(avp, bvp) -void * avp; -void * bvp; +atcomp(const void *avp, const void *bvp) { - if (((struct attype *) avp)->at < ((struct attype *) bvp)->at) + if (((const struct attype *) avp)->at < ((const struct attype *) bvp)->at) return -1; - else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at) + else if (((const struct attype *) avp)->at > ((const struct attype *) bvp)->at) return 1; else return 0; } static void -writezone(name) -const char * const name; +writezone(const char * const name) { - register FILE * fp; - register int i, j; + FILE * fp; + int i, j; static char * fullname; static struct tzhead tzh; time_t ats[TZ_MAX_TIMES]; @@ -1537,11 +1494,8 @@ const char * const name; } static void -doabbr(abbr, format, letters, isdst) -char * const abbr; -const char * const format; -const char * const letters; -const int isdst; +doabbr(char * const abbr, const char * const format, const char * const letters, + const int isdst) { if (strchr(format, '/') == NULL) { if (letters == NULL) @@ -1556,23 +1510,21 @@ const int isdst; } static void -outzone(zpfirst, zonecount) -const struct zone * const zpfirst; -const int zonecount; +outzone(const struct zone * const zpfirst, const int zonecount) { - register const struct zone * zp; - register struct rule * rp; - register int i, j; - register int usestart, useuntil; - register time_t starttime, untiltime; - register long gmtoff; - register long stdoff; - register int year; - register long startoff; - register int startttisstd; - register int startttisgmt; - register int type; - char startbuf[BUFSIZ]; + const struct zone * zp; + struct rule * rp; + int i, j; + int usestart, useuntil; + time_t starttime, untiltime; + long gmtoff; + long stdoff; + int year; + long startoff; + int startttisstd; + int startttisgmt; + int type; + char startbuf[BUFSIZ]; INITIALIZE(untiltime); INITIALIZE(starttime); @@ -1632,10 +1584,10 @@ const int zonecount; rp->r_temp = rpytime(rp, year); } for ( ; ; ) { - register int k; - register time_t jtime, ktime; - register long offset; - char buf[BUFSIZ]; + int k; + time_t jtime, ktime; + long offset; + char buf[BUFSIZ]; INITIALIZE(ktime); if (useuntil) { @@ -1744,9 +1696,7 @@ error(_("can't determine time zone abbreviation to use just after until time")); } static void -addtt(starttime, type) -const time_t starttime; -int type; +addtt(const time_t starttime, int type) { if (starttime <= min_time || (timecnt == 1 && attypes[0].at < min_time)) { @@ -1757,7 +1707,7 @@ int type; if (abbrinds[type] != 0) (void) strcpy(chars, &chars[abbrinds[type]]); abbrinds[0] = 0; - charcnt = strlen(chars) + 1; + charcnt = (int)strlen(chars) + 1; typecnt = 1; timecnt = 0; type = 0; @@ -1772,14 +1722,10 @@ int type; } static int -addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt) -const long gmtoff; -const char * const abbr; -const int isdst; -const int ttisstd; -const int ttisgmt; +addtype(const long gmtoff, const char * const abbr, const int isdst, + const int ttisstd, const int ttisgmt) { - register int i, j; + int i, j; if (isdst != TRUE && isdst != FALSE) { error(_("internal error - addtype called with bad isdst")); @@ -1828,13 +1774,9 @@ const int ttisgmt; } static void -leapadd(t, positive, rolling, count) -const time_t t; -const int positive; -const int rolling; -int count; +leapadd(const time_t t, const int positive, const int rolling, int count) { - register int i, j; + int i, j; if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { error(_("too many leap seconds")); @@ -1864,8 +1806,8 @@ int count; static void adjleap P((void)) { - register int i; - register long last = 0; + int i; + long last = 0; /* ** propagate leap seconds forward @@ -1877,9 +1819,7 @@ adjleap P((void)) } static int -yearistype(year, type) -const int year; -const char * const type; +yearistype(const int year, const char * const type) { static char * buf; int result; @@ -1902,17 +1842,15 @@ const char * const type; } static int -lowerit(a) -int a; +lowerit(int a) { a = (unsigned char) a; return (isascii(a) && isupper(a)) ? tolower(a) : a; } +/* case-insensitive equality */ static int -ciequal(ap, bp) /* case-insensitive equality */ -register const char * ap; -register const char * bp; +ciequal(const char *ap, const char *bp) { while (lowerit(*ap) == lowerit(*bp++)) if (*ap++ == '\0') @@ -1921,9 +1859,7 @@ register const char * bp; } static int -itsabbr(abbr, word) -register const char * abbr; -register const char * word; +itsabbr(const char *abbr, const char *word) { if (lowerit(*abbr) != lowerit(*word)) return FALSE; @@ -1937,12 +1873,10 @@ register const char * word; } static const struct lookup * -byword(word, table) -register const char * const word; -register const struct lookup * const table; +byword(const char * const word, const struct lookup * const table) { - register const struct lookup * foundlp; - register const struct lookup * lp; + const struct lookup * foundlp; + const struct lookup * lp; if (word == NULL || table == NULL) return NULL; @@ -1966,12 +1900,11 @@ register const struct lookup * const table; } static char ** -getfields(cp) -register char * cp; +getfields(char *cp) { - register char * dp; - register char ** array; - register int nsubs; + char * dp; + char ** array; + int nsubs; if (cp == NULL) return NULL; @@ -2005,11 +1938,9 @@ register char * cp; } static long -oadd(t1, t2) -const long t1; -const long t2; +oadd(const long t1, const long t2) { - register long t; + long t; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { @@ -2020,11 +1951,9 @@ const long t2; } static time_t -tadd(t1, t2) -const time_t t1; -const long t2; +tadd(const time_t t1, const long t2) { - register time_t t; + time_t t; if (t1 == max_time && t2 > 0) return max_time; @@ -2044,13 +1973,11 @@ const long t2; */ static time_t -rpytime(rp, wantedy) -register const struct rule * const rp; -register const int wantedy; +rpytime(const struct rule * const rp, const int wantedy) { - register int y, m, i; - register long dayoff; /* with a nod to Margaret O. */ - register time_t t; + int y, m, i; + long dayoff; /* with a nod to Margaret O. */ + time_t t; if (wantedy == INT_MIN) return min_time; @@ -2086,7 +2013,7 @@ register const int wantedy; --i; dayoff = oadd(dayoff, eitol(i)); if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { - register long wday; + long wday; #define LDAYSPERWEEK ((long) DAYSPERWEEK) wday = eitol(EPOCH_WDAY); @@ -2128,12 +2055,11 @@ register const int wantedy; } static void -newabbr(string) -const char * const string; +newabbr(const char * const string) { - register int i; + int i; - i = strlen(string) + 1; + i = (int)strlen(string) + 1; if (charcnt + i > TZ_MAX_CHARS) { error(_("too many, or too long, time zone abbreviations")); (void) exit(EXIT_FAILURE); @@ -2143,11 +2069,10 @@ const char * const string; } static int -mkdirs(argname) -char * const argname; +mkdirs(char * const argname) { - register char * name; - register char * cp; + char * name; + char * cp; if (argname == NULL || *argname == '\0' || Dflag) return 0; @@ -2185,8 +2110,7 @@ char * const argname; } static long -eitol(i) -const int i; +eitol(const int i) { long l; @@ -2200,9 +2124,7 @@ const int i; #include static void -setgroup(flag, name) - gid_t *flag; - const char *name; +setgroup(gid_t *flag, const char *name) { struct group *gr; @@ -2216,7 +2138,7 @@ setgroup(flag, name) ul = strtoul(name, &ep, 10); if (ul == (unsigned long)(gid_t)ul && *ep == '\0') { - *flag = ul; + *flag = (gid_t)ul; return; } errx(EXIT_FAILURE, _("group `%s' not found"), name); @@ -2225,9 +2147,7 @@ setgroup(flag, name) } static void -setuser(flag, name) - uid_t *flag; - const char *name; +setuser(uid_t *flag, const char *name) { struct passwd *pw; @@ -2241,7 +2161,7 @@ setuser(flag, name) ul = strtoul(name, &ep, 10); if (ul == (unsigned long)(gid_t)ul && *ep == '\0') { - *flag = ul; + *flag = (uid_t)ul; return; } errx(EXIT_FAILURE, _("user `%s' not found"), name); diff --git a/zprint.tproj/zprint.1 b/zprint.tproj/zprint.1 index 3acaae7..aa7c918 100644 --- a/zprint.tproj/zprint.1 +++ b/zprint.tproj/zprint.1 @@ -1,58 +1,90 @@ -.TH ZPRINT 1 02/12/09 -.CM 4 -.SH NAME -zprint \- show information about kernel zones -.SH SYNOPSIS -\fBzprint\fP [\fB-w\fP] [\fB-s\fP] [\fB-c\fP] [\fB-h\fP] [\fB-t\fP] [\fB-d\fP] [\fB-p \fP][name] -.SH DESCRIPTION -\fIzprint(1)\fR displays data about Mach zones. By default, -\fIzprint\fR will print out information about all Mach zones. If the -optional \fIname\fR is specified, \fIzprint\fR will print information -about each zone for which \fIname\fR is a substring of the zone's -name. -.PP -\fIzprint\fR interprets the following options: -.\" ========== -.TP 8 -.B \-c +.\" Copyright (c) 2016, Apple Inc. All rights reserved. +.\" +.Dd 2 May 2016 +.Dt ZPRINT 1 +.Os "Mac OS X" +.Sh NAME +.Nm zprint +.Nd show information about kernel zones +.Sh SYNOPSIS +.Nm +.Op Fl cdhlLstw +.Op Ar name +.Sh DESCRIPTION +.Nm +displays data about Mach zones (allocation buckets). By default, +.Nm +will print out information about all Mach zones. If the optional +.Ar name +is specified, +.Nm +will print information about each zone for which +.Ar name +is a substring of the zone's name. +.Pp +.Nm +interprets the following options: +.Pp +.Bl -tag -width "disable -" +.\" -c +.It Fl c (Default) -\fIzprint\fR prints zone info in columns. Long zone names are truncated -with '$', and spaces are replaced with '.', to allow for sorting by column. -Pageable and collectible zones are shown with 'P' and 'C' -on the far right. Zones with preposterously large maximum -sizes are shown with '----' in the max size and max num elts fields. -.\" ========== -.TP 8 -.B \-h -(Default) -Shows headings for the columns printed with the -c option. -It may be useful to override this option when sorting by column. -.\" ========== -.TP 8 -.B \-s -\fIzprint\fR sorts the zones, showing the zone wasting the most memory first. -.\" ========== -.TP 8 -.B \-w -For each zone, \fIzprint\fR calculates how much space is allocated but -not currently in use, the space wasted by the zone. -.TP 8 -.B \-t -For each zone, \fIzprint\fR calculates the total size of allocations from -the zone over the life of the zone. -.TP 8 -.B \-d +.Nm +prints zone info in columns. Long zone names are truncated with +.Ql \&$ , +and spaces are replaced with +.Ql \&. , +to allow for sorting by column. Pageable and collectible zones are shown with +.Ql \&P +and +.Ql \&C +on the far right, respectively. Zones with preposterously large maximum sizes +are shown with +.Ql ---- +in the max size and max num elts fields. +.\" -d +.It Fl d Display deltas over time, showing any zones that have achieved a new maximum current allocation size during the interval. If the total allocation sizes are -being displayed for the zones in question, it will also display the deltas if the -total allocations have doubled. -.B \-p -Display zone usage related to the specified process id. Each zone will display -standard columns and the amount of memory from that zone associated with a given -process. The letter "A" in the flags column indicates that this total is being -accounted to the process. Otherwise, the total is an indication of the influence -the process has on the kernel, but the memory is being accounted to the kernel proper. -.PP -Any option (including default options) can be overridden -by specifying the option in upper-case; for example, -C overrides -the (default) option -c. +being displayed for the zones in question, it will also display the deltas if +the total allocations have doubled. +.\" -h +.It Fl h +(Default) Shows headings for the columns printed with the +.Fl c +option. It may be useful to override this option when sorting by column. +.\" -l +.It Fl l +(Default) Show all wired memory information after the zone information. +.\" -L +.It Fl L +Do not show all wired memory information after the zone information. +.\" -s +.It Fl s +.Nm +sorts the zones, showing the zone wasting the most memory first. +.\" -t +.It Fl t +For each zone, +.Nm +calculates the total size of allocations from the zone over the life of the +zone. +.\" -w +.It Fl w +For each zone, +.Nm +calculates how much space is allocated but not currently in use, the space +wasted by the zone. +.El +.Pp +Any option (including default options) can be overridden by specifying the +option in upper-case; for example, +.Fl C +overrides the default option +.Fl c . +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr ioclasscount 1 , +.Xr lsmp 1 , +.Xr lskq 1 , diff --git a/zprint.tproj/zprint.c b/zprint.tproj/zprint.c index fed4172..104161c 100644 --- a/zprint.tproj/zprint.c +++ b/zprint.tproj/zprint.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2009 Apple Inc. All rights reserved. + * Copyright (c) 2009-2016 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_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 @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * 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, @@ -22,34 +22,34 @@ * 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_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ -/* +/* * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ @@ -65,8 +65,6 @@ * to zones but not currently in use. */ - - #include #include #include @@ -87,9 +85,6 @@ #include #include - - - #define streql(a, b) (strcmp((a), (b)) == 0) #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0) #define PRINTK(fmt, value) \ @@ -139,7 +134,7 @@ sigintr(__unused int signum) static void usage(void) { - fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-p ] [name]\n", program); + fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-l] [-L] [-p ] [name]\n", program); exit(1); } @@ -234,7 +229,7 @@ main(int argc, char **argv) if (ShowPid) { kr = task_for_pid(mach_task_self(), pid, &task); if (kr != KERN_SUCCESS) { - fprintf(stderr, "%s: task_for_pid(%d) failed: %s (try running as root)\n", + fprintf(stderr, "%s: task_for_pid(%d) failed: %s (try running as root)\n", program, pid, mach_error_string(kr)); exit(1); } @@ -335,11 +330,11 @@ main(int argc, char **argv) printzone(&name[i], &info[i]); } } + } - if (ShowLarge && first_time) { - PrintLarge(wiredInfo, wiredInfoCnt, - SortZones ? &SortSize : &SortName, ColFormat); - } + if (ShowLarge && first_time) { + PrintLarge(wiredInfo, wiredInfoCnt, + SortZones ? &SortSize : &SortName, ColFormat); } first_time = 0; @@ -396,6 +391,8 @@ substr(const char *a, size_t alen, const char *b, size_t blen) { int i; + if (alen > blen) return FALSE; + for (i = 0; i <= blen - alen; i++) if (strneql(a, b+i, alen)) return TRUE; @@ -611,6 +608,9 @@ kern_vm_tag_name(uint64_t tag) 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_REASON): name = "VM_KERN_MEMORY_REASON"; break; + case (VM_KERN_MEMORY_SKYWALK): name = "VM_KERN_MEMORY_SKYWALK"; break; + case (VM_KERN_MEMORY_LTABLE): name = "VM_KERN_MEMORY_LTABLE"; break; case (VM_KERN_MEMORY_ANY): name = "VM_KERN_MEMORY_ANY"; break; default: name = NULL; break; } @@ -619,7 +619,7 @@ kern_vm_tag_name(uint64_t tag) return (result); } -static char * +static char * kern_vm_counter_name(uint64_t tag) { char * result; @@ -656,11 +656,11 @@ MakeLoadTagKeys(const void * key, const void * value, void * context) CFDictionarySetValue(newDict, key, value); } -static CSSymbolicatorRef gSym; +static CSSymbolicatorRef gSym; static CFMutableDictionaryRef gTagDict; static mach_memory_info_t * gSites; -static char * +static char * GetSiteName(int siteIdx) { const char * name; @@ -693,7 +693,7 @@ GetSiteName(int siteIdx) case VM_KERN_SITE_KMOD: kextInfo = CFDictionaryGetValue(gTagDict, (const void *)(uintptr_t) addr); - if (kextInfo) + if (kextInfo) { bundleID = (CFStringRef)CFDictionaryGetValue(kextInfo, kCFBundleIdentifierKey); name = CFStringGetCStringPtr(bundleID, kCFStringEncodingUTF8); @@ -729,7 +729,7 @@ GetSiteName(int siteIdx) return (result); } -static int +static int SortName(const void * left, const void * right) { const int * idxL; @@ -750,7 +750,7 @@ SortName(const void * left, const void * right) return (result); } -static int +static int SortSize(const void * left, const void * right) { const mach_memory_info_t * siteL; @@ -781,15 +781,16 @@ PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, int sorted[wiredInfoCnt]; char totalstr[40]; char * name; + bool headerPrinted; zonetotal = totalsize; gSites = wiredInfo; gSym = CSSymbolicatorCreateWithMachKernel(); - + allKexts = OSKextCopyLoadedKextInfo(NULL, NULL); - gTagDict = CFDictionaryCreateMutable( + gTagDict = CFDictionaryCreateMutable( kCFAllocatorDefault, (CFIndex) 0, (CFDictionaryKeyCallBacks *) 0, &kCFTypeDictionaryValueCallBacks); @@ -802,16 +803,11 @@ PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, for (idx = 0; idx < wiredInfoCnt; idx++) sorted[idx] = idx; first = 0; // VM_KERN_MEMORY_FIRST_DYNAMIC qsort(&sorted[first], - wiredInfoCnt - first, - sizeof(sorted[0]), + 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++) + for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) { site = sorted[idx]; if (!gSites[site].size) continue; @@ -820,6 +816,15 @@ PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, if (!(VM_KERN_SITE_WIRED & gSites[site].flags)) continue; name = GetSiteName(site); + if (!substr(zname, znamelen, name, strlen(name))) continue; + if (!headerPrinted) + { + printf("-------------------------------------------------------------------------------------------------------------\n"); + printf(" kmod vm cur\n"); + printf("wired memory id tag size\n"); + printf("-------------------------------------------------------------------------------------------------------------\n"); + headerPrinted = true; + } printf("%-67s", name); free(name); printf("%12d", site); @@ -831,19 +836,20 @@ PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, 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++) + if (!znamelen) + { + printf("%-67s", "zones"); + printf("%12s", ""); + printf(" %11s", ""); + PRINTK(" %12llu", zonetotal); + printf("\n"); + } + if (headerPrinted) + { + snprintf(totalstr, sizeof(totalstr), "%6.2fM of %6.2fM", totalsize / 1024.0 / 1024.0, top_wired / 1024.0 / 1024.0); + printf("total%100s\n", totalstr); + } + for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) { site = sorted[idx]; if (!gSites[site].size) continue; @@ -851,6 +857,15 @@ PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, if (VM_KERN_SITE_WIRED & gSites[site].flags) continue; name = GetSiteName(site); + if (!substr(zname, znamelen, name, strlen(name))) continue; + if (!headerPrinted) + { + printf("-------------------------------------------------------------------------------------------------------------\n"); + printf(" largest\n"); + printf("maps free free size\n"); + printf("-------------------------------------------------------------------------------------------------------------\n"); + headerPrinted = true; + } printf("%-67s", name); free(name); -- 2.45.2