+++ /dev/null
-//
-// 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 <unistd.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <cstdlib>
-#include <string>
-#include <sstream>
-#include <exception>
-#include <vector>
-#include <asl.h>
-
-#include <math.h>
-
-#include <mach/mach_time.h>
-
-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
+++ /dev/null
-//
-// 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<AbsInterval>& 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<AbsInterval>& 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
+++ /dev/null
-//
-// 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<AbsTime> 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<AbsInterval>& 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<AbsInterval>& intervals, AbsInterval timespan);
-
-#endif /* defined(__CPPUtil__UtilAbsInterval__) */
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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 <typename... Args>
- FileDescriptor(Args&& ... args) :
- _fd(open(static_cast<Args &&>(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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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<typename T, typename ...Args>
-std::unique_ptr<T> make_unique( Args&& ...args )
-{
- return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
-}
-
-#endif
-
-#endif
+++ /dev/null
-//
-// UtilMappedFile.cpp
-// CPPUtil
-//
-// Created by James McIlree on 4/19/13.
-// Copyright (c) 2013 Apple. All rights reserved.
-//
-
-#include "CPPUtil.h"
-
-#include <sys/mman.h>
-
-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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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 <typename T>
-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<char>(1); // 1 byte
- // MemoryBuffer<uint32_t>(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 <typename T>
-MemoryBuffer<T>::MemoryBuffer(size_t capacity) :
- _capacity(capacity)
-{
- _data = capacity ? (T*)malloc(capacity * sizeof(T)) : (T*)NULL;
-}
-
-template <typename T>
-void MemoryBuffer<T>::set_capacity(size_t capacity) {
- MemoryBuffer<T> newbuf(capacity);
- memcpy(newbuf.data(), _data, std::min(_capacity * sizeof(T), newbuf.capacity() * sizeof(T)));
- *this = std::move(newbuf);
-}
-
-#endif /* defined(__CPPUtil__UtilMemoryBuffer__) */
+++ /dev/null
-//
-// 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<NanoTime> NanoInterval;
-
-#endif /* defined(__CPPUtil__UtilNanoInterval__) */
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// UtilPath.inline.hpp
-// CPPUtil
-//
-// Created by James McIlree on 4/8/13.
-// Copyright (c) 2013 Apple. All rights reserved.
-//
-
-#include "CPPUtil.h"
-
-#include <sys/stat.h>
-
-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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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<char*> hashes on the pointer,
- // not the contents of that pointer.
- //
- // The C++11 std::hash<std::string> 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
+++ /dev/null
-//
-// 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 <typename T>
-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 <typename TRANGE>
-bool is_trange_vector_sorted_and_non_overlapping(const std::vector<TRANGE>& 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 <typename TRANGE>
-bool is_trange_vector_sorted(const std::vector<TRANGE>& 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 <typename TRANGE>
-std::vector<TRANGE> trange_vector_union(std::vector<TRANGE>& input) {
- std::vector<TRANGE> 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 <typename TRANGE>
-std::vector<TRANGE> trange_vector_union(std::vector<TRANGE>& vec1, std::vector<TRANGE>& vec2) {
- std::vector<TRANGE> 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<TRANGE>();
- }
-
- 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 <typename TRANGE>
-std::vector<TRANGE> trange_vector_intersect(std::vector<TRANGE>& vec1, std::vector<TRANGE>& vec2) {
- std::vector<TRANGE> 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
+++ /dev/null
-//
-// 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 <typename T1, typename T2>
-class TRangeValue : public TRange<T1> {
- protected:
- T2 _value;
-
- public:
- TRangeValue(T1 location, T1 length, T2 value) : TRange<T1>(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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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 <typename SIZE>
-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<SIZE>* 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<SIZE>* 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<SIZE>* thread() const {
- ASSERT(is_run(), "Sanity");
- return (MachineThread<SIZE>* )((uintptr_t)_u.thread & ~kCPUActivityRunIsContextSwitch);
- }
-};
-
-#endif
+++ /dev/null
-//
-// 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 <typename SIZE>
-class MachineCPU;
-
-template <typename SIZE>
-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<SIZE>;
-
- public:
- typedef std::unordered_set<ProcessSummary<SIZE>, ProcessSummaryHash<SIZE>, ProcessSummaryEqualTo<SIZE>> ProcessSummarySet;
- typedef std::unordered_set<const MachineCPU<SIZE>*> 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<AbsInterval> _wallclock_run_intervals; // This is the actual wallclock run interval data.
- std::vector<AbsInterval> _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<AbsInterval> _all_cpus_idle_intervals;
- std::vector<AbsInterval> _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<SIZE>* cpu);
- void end_cpu_timeline_walk(const MachineCPU<SIZE>* cpu);
-
- // These bracket all cpu timeline walks
- void begin_cpu_timeline_walks(void);
- void end_cpu_timeline_walks(void);
-
- ProcessSummary<SIZE>* mutable_process_summary(const MachineProcess<SIZE>* 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<ProcessSummary<SIZE>*>(&*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<SIZE>* process_summary(const MachineProcess<SIZE>* process) const {
- auto it = _process_summaries.find(process);
- return (it == _process_summaries.end()) ? NULL : &*it;
- }
-
- DEBUG_ONLY(void validate() const;)
-};
-
-template <typename SIZE>
-void CPUSummary<SIZE>::begin_cpu_timeline_walks() {
- _should_merge_all_cpus_idle_intervals = true;
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::begin_cpu_timeline_walk(const MachineCPU<SIZE>* cpu) {
- ASSERT(cpu, "Sanity");
- _cpus.emplace(cpu);
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::end_cpu_timeline_walk(const MachineCPU<SIZE>* cpu) {
- ASSERT(cpu, "Sanity");
-
- accumulate_wallclock_run_intervals();
- accumulate_all_cpus_idle_intervals();
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::end_cpu_timeline_walks(void) {
- summarize_wallclock_run_intervals();
- summarize_all_cpus_idle_intervals();
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::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 <typename SIZE>
-void CPUSummary<SIZE>::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<ProcessSummary<SIZE>*>(&process_summary)->accumulate_wallclock_run_intervals();
- }
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::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<ProcessSummary<SIZE>*>(&process_summary)->summarize_wallclock_run_intervals();
- }
-}
-
-template <typename SIZE>
-void CPUSummary<SIZE>::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 <typename SIZE>
-void CPUSummary<SIZE>::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 <typename SIZE>
-void CPUSummary<SIZE>::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 <typename SIZE>
-void CPUSummary<SIZE>::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
+++ /dev/null
-//
-// 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 <typename SIZE>
-class IOActivity : public TRange<AbsTime> {
- private:
- MachineThread<SIZE>* _thread;
- typename SIZE::ptr_t _size;
-
- public:
- IOActivity(AbsTime start, AbsTime length, MachineThread<SIZE>* thread, typename SIZE::ptr_t size) :
- TRange(start, length),
- _thread(thread),
- _size(size)
- {
- ASSERT(_thread, "Sanity");
- ASSERT(_size, "Zero length IO");
- }
-
- MachineThread<SIZE>* thread() const { return _thread; }
- void set_thread(MachineThread<SIZE>* thread) { _thread = thread; }
-
- typename SIZE::ptr_t size() const { return _size; }
-};
-
-#endif
+++ /dev/null
-//
-// Kernel.cpp
-// KDBG
-//
-// Created by James McIlree on 10/24/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include <CPPUtil/CPPUtil.h>
-
-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<KDCPUMapEntry> KDBG::cpumap()
-{
- std::vector<KDCPUMapEntry> 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;
-}
+++ /dev/null
-//
-// 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 <typename KERNEL_SIZE>
- static std::vector<KDThreadMapEntry<KERNEL_SIZE>> 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 <typename SIZE>
- static std::vector<KDThreadMapEntry<SIZE>> 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<KDCPUMapEntry> 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 <typename SIZE>
- static int read(KDEvent<SIZE>* buf, size_t buf_size_in_bytes);
-};
-
-template <typename SIZE>
-int KDBG::read(KDEvent<SIZE>* 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 <typename SIZE>
-std::vector<KDThreadMapEntry<SIZE>> KDBG::threadmap(KDState& state)
-{
- std::vector<KDThreadMapEntry<SIZE>> maps(state.thread_map_capacity());
- size_t size = state.thread_map_capacity() * sizeof(KDThreadMapEntry<SIZE>);
-
- 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 <typename SIZE>
-std::vector<KDThreadMapEntry<SIZE>> KDBG::current_threadmap()
-{
- std::vector<KDThreadMapEntry<SIZE>> maps(2048);
-
-resize:
- size_t size_in = maps.size() * sizeof(KDThreadMapEntry<SIZE>);
- 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<SIZE>));
- }
-
- return maps;
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// KDEvent.hpp
-// KDBG
-//
-// Created by James McIlree on 10/25/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-template <typename SIZE> class KDEventFields {};
-
-template <>
-class KDEventFields<Kernel32> {
- 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<Kernel64> {
- 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 <typename SIZE>
-class KDEvent {
- private:
- KDEventFields<SIZE> _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 <typename SIZE>
-std::string KDEvent<SIZE>::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<char*>(buf));
-}
-
-template <typename SIZE>
-std::string KDEvent<SIZE>::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<char*>(buf));
-}
-
+++ /dev/null
-//
-// 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());
- }
-};
-
+++ /dev/null
-//
-// 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 <typename SIZE>
-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
+++ /dev/null
-//
-// 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 <sys/sysctl.h>
-#include <sys/buf.h>
-#include <mach/task_policy.h>
-
-#ifndef KERNEL_PRIVATE
- #define KERNEL_PRIVATE
- #include <sys/kdebug.h>
- #undef KERNEL_PRIVATE
-#else
- #error Something is really strage...
-#endif /*KERNEL_PRIVATE*/
-
-#include <vector>
-#include <unordered_map>
-#include <unordered_set>
-#include <algorithm>
-
-#include <libkern/OSAtomic.h>
-
-#include <CPPUtil/CPPUtil.h>
-
-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
+++ /dev/null
-//
-// 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;
-}
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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 <typename SIZE>
-class Machine {
- protected:
- std::vector<MachineCPU<SIZE>> _cpus;
-
- std::unordered_multimap<pid_t, MachineProcess<SIZE>> _processes_by_pid;
- std::unordered_multimap<const char*, MachineProcess<SIZE>*, ConstCharHash, ConstCharEqualTo> _processes_by_name;
- std::vector<MachineProcess<SIZE>*> _processes_by_time;
-
- std::unordered_multimap<typename SIZE::ptr_t, MachineThread<SIZE> > _threads_by_tid;
- std::vector<MachineThread<SIZE>*> _threads_by_time;
-
- std::vector<MachineMachMsg<SIZE>> _mach_msgs;
- std::unordered_map<uintptr_t, uintptr_t> _mach_msgs_by_event_index;
- std::unordered_map<typename SIZE::ptr_t, NurseryMachMsg<SIZE>> _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<typename SIZE::ptr_t, std::unique_ptr<MachineVoucher<SIZE>>> _voucher_nursery;
- std::unordered_map<typename SIZE::ptr_t, std::vector<std::unique_ptr<MachineVoucher<SIZE>>>> _vouchers_by_addr;
-
- std::unordered_map<typename SIZE::ptr_t, IOActivity<SIZE>> _io_by_uid; // uid == unique id, not user id
- std::vector<IOActivity<SIZE>> _all_io;
- std::vector<AbsInterval> _all_io_active_intervals;
-
- MachineProcess<SIZE>* _kernel_task;
- const KDEvent<SIZE>* _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<SIZE>* threadmaps,
- uint32_t threadmap_count,
- const KDEvent<SIZE>* events,
- uintptr_t event_count);
-
- void post_initialize();
-
- //
- // Mutable API, for use during construction
- //
-
- pid_t next_unknown_pid() { return --_unknown_process_pid; }
-
- MachineProcess<SIZE>* create_process(pid_t pid, const char* name, AbsTime create_timestamp, kMachineProcessFlag flags);
- MachineThread<SIZE>* create_thread(MachineProcess<SIZE>* process, typename SIZE::ptr_t tid, MachineVoucher<SIZE>* voucher, AbsTime create_timestamp, kMachineThreadFlag flags);
- MachineVoucher<SIZE>* 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<SIZE>* process, const char* name);
-
- MachineProcess<SIZE>* mutable_process(pid_t pid, AbsTime time) { return const_cast<MachineProcess<SIZE>*>(process(pid, time)); }
- MachineThread<SIZE>* mutable_thread(typename SIZE::ptr_t tid, AbsTime time) { return const_cast<MachineThread<SIZE>*>(thread(tid, time)); }
-
- MachineProcess<SIZE>* youngest_mutable_process(pid_t pid);
- MachineThread<SIZE>* youngest_mutable_thread(typename SIZE::ptr_t tid);
-
- MachineVoucher<SIZE>* process_event_voucher_lookup(typename SIZE::ptr_t address, uint32_t msgh_bits);
- MachineThread<SIZE>* process_event_tid_lookup(typename SIZE::ptr_t tid, AbsTime now);
-
- MachineVoucher<SIZE>* thread_forwarding_voucher_lookup(const MachineVoucher<SIZE>* original_thread_voucher);
-
- void begin_io(MachineThread<SIZE>* 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<SIZE>& 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<SIZE> UnsetVoucher;
- static MachineVoucher<SIZE> NullVoucher;
-
- Machine(KDCPUMapEntry* cpumaps, uint32_t cpumap_count, KDThreadMapEntry<SIZE>* threadmaps, uint32_t threadmap_count, KDEvent<SIZE>* events, uintptr_t event_count);
- // Destructive, mutates parent!
- Machine(Machine<SIZE>& parent, KDEvent<SIZE>* events, uintptr_t event_count);
- Machine(const TraceFile& file);
-
- bool lost_events() const { return (_flags & (uint32_t)kMachineFlag::LostEvents) > 0; }
-
- const MachineProcess<SIZE>* process(pid_t pid, AbsTime time) const;
- const MachineThread<SIZE>* thread(typename SIZE::ptr_t tid, AbsTime time) const;
- const MachineVoucher<SIZE>* voucher(typename SIZE::ptr_t address, AbsTime time) const;
- const MachineMachMsg<SIZE>* mach_msg(uintptr_t event_index) const;
-
- const std::vector<const MachineProcess<SIZE>*>& processes() const;
- const std::vector<const MachineThread<SIZE>*>& threads() const;
- const std::vector<const MachineCPU<SIZE>>& cpus() const;
-
- const KDEvent<SIZE>* 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<SIZE> summary_for_timespan(AbsInterval timespan, const MachineCPU<SIZE>* 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 <typename SIZE> MachineVoucher<SIZE> Machine<SIZE>::UnsetVoucher(SIZE::PTRMAX, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsUnsetVoucher, 0);
-template <typename SIZE> MachineVoucher<SIZE> Machine<SIZE>::NullVoucher(0, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsNullVoucher, 0);
-
+++ /dev/null
-//
-// Machine.impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "KDebug.h"
-
-template <typename SIZE>
-bool process_by_time_sort(const MachineProcess<SIZE>* left, const MachineProcess<SIZE>* right) {
- return left->timespan().location() < right->timespan().location();
-}
-
-template <typename SIZE>
-bool thread_by_time_sort(const MachineThread<SIZE>* left, const MachineThread<SIZE>* right) {
- return left->timespan().location() < right->timespan().location();
-}
-
-template <typename SIZE>
-void Machine<SIZE>::post_initialize() {
- //
- // Post initialization. Sort various by time vectors, etc.
- //
-
- std::sort(_processes_by_time.begin(), _processes_by_time.end(), process_by_time_sort<SIZE>);
- std::sort(_threads_by_time.begin(), _threads_by_time.end(), thread_by_time_sort<SIZE>);
-
- // 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<AbsTime> 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<AbsTime> 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<SIZE>::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<std::unique_ptr<MachineVoucher<SIZE>>> 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 <typename SIZE>
-void Machine<SIZE>::raw_initialize(const KDCPUMapEntry* cpumaps,
- uint32_t cpumap_count,
- const KDThreadMapEntry<SIZE>* threadmaps,
- uint32_t threadmap_count,
- const KDEvent<SIZE>* 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<SIZE>* 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 <typename SIZE>
-Machine<SIZE>::Machine(KDCPUMapEntry* cpumaps, uint32_t cpumap_count, KDThreadMapEntry<SIZE>* threadmaps, uint32_t threadmap_count, KDEvent<SIZE>* 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 <typename SIZE>
-Machine<SIZE>::Machine(const TraceFile& file) :
- _kernel_task(nullptr),
- _events(file.events<SIZE>()),
- _event_count(file.event_count()),
- _flags(0),
- _unknown_process_pid(-1)
-{
- raw_initialize(file.cpumap(),
- file.cpumap_count(),
- file.threadmap<SIZE>(),
- file.threadmap_count(),
- file.events<SIZE>(),
- file.event_count());
-}
-
-template <typename SIZE>
-Machine<SIZE>::Machine(Machine<SIZE>& parent, KDEvent<SIZE>* 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<const MachineThread<SIZE>*>& parent_threads = parent.threads();
- const std::vector<const MachineCPU<SIZE>>& parent_cpus = parent.cpus();
-
- for (const MachineCPU<SIZE>& 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<MachineVoucher<SIZE>>& 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<SIZE>* parent_thread : parent_threads) {
- if (!parent_thread->is_trace_terminated()) {
- const MachineProcess<SIZE>& parent_process = parent_thread->process();
- MachineProcess<SIZE>* 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<SIZE>& parent_cpu : parent_cpus) {
- if (!parent_cpu.is_iop()) {
- ap_count++;
- const std::vector<CPUActivity<SIZE>>& parent_cpu_timeline = parent_cpu.timeline();
-
- bool intr_initialized = false;
- bool idle_initialized = false;
- bool runq_initialized = false;
-
- MachineCPU<SIZE>& 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<SIZE>* 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<it, bool>, and the it is std::pair<key, value>...
-
- // 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 <typename SIZE>
-const MachineProcess<SIZE>* Machine<SIZE>::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<SIZE>& process = it->second;
- if (process.timespan().contains(time)) {
- return &process;
- }
- }
-
- return nullptr;
-}
-
-template <typename SIZE>
-const MachineThread<SIZE>* Machine<SIZE>::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<SIZE>& thread = it->second;
- if (thread.timespan().contains(time)) {
- return &thread;
- }
- }
-
- return nullptr;
-}
-
-template <typename SIZE>
-struct VoucherVsAbsTimeComparator {
- bool operator()(const std::unique_ptr<MachineVoucher<SIZE>>& voucher, const AbsTime time) const {
- return voucher->timespan().max() < time;
- }
-
- bool operator()(const AbsTime time, const std::unique_ptr<MachineVoucher<SIZE>>& voucher) const {
- return time < voucher->timespan().max();
- }
-};
-
-template <typename SIZE>
-const MachineVoucher<SIZE>* Machine<SIZE>::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<SIZE>());
- // 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 <typename SIZE>
-const MachineMachMsg<SIZE>* Machine<SIZE>::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 <typename SIZE>
-void Machine<SIZE>::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<SIZE>* 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<SIZE>* 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 <typename SIZE>
-const std::vector<const MachineProcess<SIZE>*>& Machine<SIZE>::processes() const {
- return *reinterpret_cast< const std::vector<const MachineProcess<SIZE>*>* >(&_processes_by_time);
-}
-
-template <typename SIZE>
-const std::vector<const MachineThread<SIZE>*>& Machine<SIZE>::threads() const {
- return *reinterpret_cast< const std::vector<const MachineThread<SIZE>*>* >(&_threads_by_time);
-}
-
-template <typename SIZE>
-const std::vector<const MachineCPU<SIZE>>& Machine<SIZE>::cpus() const {
- return *reinterpret_cast< const std::vector<const MachineCPU<SIZE>>* >(&_cpus);
-}
-
-template <typename SIZE>
-AbsInterval Machine<SIZE>::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 <typename SIZE>
-CPUSummary<SIZE> Machine<SIZE>::summary_for_timespan(AbsInterval summary_timespan, const MachineCPU<SIZE>* summary_cpu) const {
- ASSERT(summary_timespan.intersects(timespan()), "Sanity");
- CPUSummary<SIZE> 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<SIZE>* process_summary = NULL;
- ThreadSummary<SIZE>* thread_summary = NULL;
-
- if (start->is_run() && !start->is_context_switch()) {
- const MachineThread<SIZE>* thread_on_cpu = start->thread();
- const MachineProcess<SIZE>* 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<SIZE>* thread_on_cpu = start->thread();
- const MachineProcess<SIZE>* 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<SIZE>* process_summary = NULL;
- ThreadSummary<SIZE>* 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<SIZE>* thread_on_cpu = start->thread();
- const MachineProcess<SIZE>* 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<ProcessSummary<SIZE>*>(&*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<SIZE>* machine_thread : _threads_by_time) {
- const MachineProcess<SIZE>* process = &machine_thread->process();
-
- ProcessSummary<SIZE>* process_summary = NULL;
- ThreadSummary<SIZE>* 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<SIZE>* process_summary = summary.mutable_process_summary(&it->thread()->process());
- process_summary->add_io_time(t.length());
-
- ThreadSummary<SIZE>* 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<SIZE>* machine_thread : _threads_by_time) {
- const MachineProcess<SIZE>* process = &machine_thread->process();
-
- ProcessSummary<SIZE>* process_summary = NULL;
- ThreadSummary<SIZE>* 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<SIZE>* 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 <typename SIZE>
-uint32_t Machine<SIZE>::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 <typename SIZE>
-bool Machine<SIZE>::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;
-}
+++ /dev/null
-//
-// Machine.mutable-impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "KDebug.h"
-
-template <typename SIZE>
-MachineProcess<SIZE>* Machine<SIZE>::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<SIZE>& 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<SIZE>& 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<SIZE>* process : _processes_by_time) {
- if (process->pid() == pid) {
- ASSERT(!process->timespan().contains(create_timestamp), "Creating a process that overlaps an existing process");
- }
- }
- })
-
- if (MachineProcess<SIZE>* 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<SIZE>* process = &_processes_by_pid.emplace(pid, MachineProcess<SIZE>(pid, name, create_timestamp, flags))->second;
- _processes_by_name.emplace(process->name(), process);
- _processes_by_time.push_back(process);
-
- return process;
-}
-
-template <typename SIZE>
-MachineThread<SIZE>* Machine<SIZE>::create_thread(MachineProcess<SIZE>* process, typename SIZE::ptr_t tid, MachineVoucher<SIZE>* 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<SIZE>& 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<SIZE>* 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<SIZE>* 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<SIZE>* thread = &_threads_by_tid.emplace(tid, MachineThread<SIZE>(process, tid, voucher, create_timestamp, flags))->second;
- _threads_by_time.push_back(thread);
-
- return thread;
-}
-
-template <typename SIZE>
-MachineVoucher<SIZE>* Machine<SIZE>::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<SIZE>* voucher;
-
- ASSERT(_voucher_nursery.find(address) == _voucher_nursery.end(), "Attempt to create an already live voucher (<rdar://problem/16898190>)");
- //
- // 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 :-).
- //
- // <rdar://problem/16898190> 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<MachineVoucher<SIZE>>(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 <typename SIZE>
-void Machine<SIZE>::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<SIZE>* 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<std::unique_ptr<MachineVoucher<SIZE>>> row(std::move(nursery_it->second));
- std::vector<std::unique_ptr<MachineVoucher<SIZE>>> 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 <typename SIZE>
-MachineVoucher<SIZE>* Machine<SIZE>::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 <typename SIZE>
-MachineVoucher<SIZE>* Machine<SIZE>::thread_forwarding_voucher_lookup(const MachineVoucher<SIZE>* 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 <typename SIZE>
-void Machine<SIZE>::set_process_name(MachineProcess<SIZE>* 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 <typename SIZE>
-MachineProcess<SIZE>* Machine<SIZE>::youngest_mutable_process(pid_t pid) {
- MachineProcess<SIZE>* 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<SIZE>& 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 <typename SIZE>
-MachineThread<SIZE>* Machine<SIZE>::youngest_mutable_thread(typename SIZE::ptr_t tid) {
- MachineThread<SIZE>* 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<SIZE>& 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 <typename SIZE>
-MachineThread<SIZE>* Machine<SIZE>::process_event_tid_lookup(typename SIZE::ptr_t tid, AbsTime now) {
- MachineThread<SIZE>* 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<SIZE>* 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 <typename SIZE>
-void Machine<SIZE>::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<SIZE>* target = youngest_mutable_process(pid)) {
- target->set_apptype_from_trequested(apptype);
- }
- }
- }
-}
-
-template <typename SIZE>
-void Machine<SIZE>::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<SIZE>* 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 <typename SIZE>
-bool Machine<SIZE>::process_event(const KDEvent<SIZE>& 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<SIZE>& 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>& 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>::message_id(),
- kmsg_addr,
- flags,
- AbsTime(0),
- 0,
- 0,
- &Machine<SIZE>::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 <typename SIZE>
-void Machine<SIZE>::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<SIZE>& event = _events[index];
- ASSERT(event.cpu() > -1 && event.cpu() < _cpus.size(), "cpu_id out of range");
- MachineCPU<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void Machine<SIZE>::begin_io(MachineThread<SIZE>* 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<SIZE>(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<SIZE>(begin_time, AbsTime(0), thread, size);
- }
-}
-
-template <typename SIZE>
-void Machine<SIZE>::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<SIZE>* 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));
- })
- }
-}
+++ /dev/null
-//
-// 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 <typename SIZE>
-class MachineCPU {
- protected:
-
- class ThreadOnCPU {
- protected:
- MachineThread<SIZE>* _thread;
- AbsTime _timestamp;
- public:
- ThreadOnCPU(MachineThread<SIZE>* thread, bool is_event_zero_init_thread, AbsTime timestamp) :
- _thread(thread),
- _timestamp(timestamp)
- {
- if (is_event_zero_init_thread)
- _thread = (MachineThread<SIZE>*)((uintptr_t)_thread | 1);
- }
-
- MachineThread<SIZE>* thread() { return (MachineThread<SIZE>*)((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<CPUActivity<SIZE>> _timeline;
-
- // State used only during initialization
- MachineThread<SIZE>* _thread;
- AbsTime _begin_idle;
- AbsTime _begin_intr;
- std::vector<ThreadOnCPU> _cpu_runq;
- std::vector<AbsInterval> _cpu_intr;
- std::vector<AbsInterval> _cpu_idle;
-
- friend class Machine<SIZE>;
-
- 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<SIZE>* to_thread, MachineThread<SIZE>* from_thread, AbsTime timestamp);
-
- bool is_thread_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateThreadInitialized) > 0; }
- void initialize_thread_state(MachineThread<SIZE>* thread, AbsTime timestamp);
-
- MachineThread<SIZE>* 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<CPUActivity<SIZE>>& timeline() const { return _timeline; }
- const CPUActivity<SIZE>* activity_for_timestamp(AbsTime timestamp) const;
-};
+++ /dev/null
-//
-// 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 <typename SIZE>
-const CPUActivity<SIZE>* MachineCPU<SIZE>::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;
-}
+++ /dev/null
-//
-// MachineCPU.mutable-impl.hpp
-// KDBG
-//
-// Created by James McIlree on 11/7/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-template <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::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 <typename SIZE>
-void MachineCPU<SIZE>::initialize_thread_state(MachineThread<SIZE>* 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 <typename SIZE>
-void MachineCPU<SIZE>::context_switch(MachineThread<SIZE>* to_thread, MachineThread<SIZE>* 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 <typename SIZE>
-void MachineCPU<SIZE>::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<SIZE>* 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();
-}
+++ /dev/null
-//
-// 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 <typename SIZE>
-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<SIZE>* _send_voucher;
- MachineVoucher<SIZE>* _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<SIZE>* send_voucher,
- AbsTime recv_time,
- typename SIZE::ptr_t recv_tid,
- uint32_t recv_msgh_bits,
- MachineVoucher<SIZE>* 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<SIZE>::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<SIZE>* send_voucher() const { ASSERT(has_sender(), "No Sender"); return _send_voucher; }
- MachineVoucher<SIZE>* 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
+++ /dev/null
-//
-// 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 <typename SIZE> class Machine;
-
-template <typename SIZE>
-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<MachineThread<SIZE>*> _threads_by_time;
- uint32_t _flags;
- int32_t _exit_status;
- int32_t _apptype; // Unset == -1
-
- //
- // Mutable API
- //
-
- friend class Machine<SIZE>;
-
- 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<SIZE>* 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<const MachineThread<SIZE>*>& threads() const { return *reinterpret_cast<const std::vector<const MachineThread<SIZE>*>*>(&_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;)
-};
-
+++ /dev/null
-//
-// MachineProcess.impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-template <typename SIZE>
-MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::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
+++ /dev/null
-//
-// MachineProcess.mutable-impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "KDebug.h"
-
-template <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::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<SIZE>* thread : _threads_by_time) {
- if (!thread->is_trace_terminated()) {
- thread->set_trace_terminated(timestamp);
- }
- }
-
- set_trace_terminated(timestamp);
-}
-
-template <typename SIZE>
-void MachineProcess<SIZE>::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<SIZE>* 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 <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::set_name(const char* name) {
- ASSERT(name, "Sanity");
- ASSERT(strlen(name) < sizeof(_name) - 1, "Sanity");
-
- strlcpy(_name, name, sizeof(_name));
-}
-
-template <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::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 <typename SIZE>
-void MachineProcess<SIZE>::add_thread(MachineThread<SIZE>* 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<SIZE>* 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 <typename SIZE>
-void MachineProcess<SIZE>::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<SIZE>);
-}
+++ /dev/null
-//
-// MachineThread.hpp
-// KDBG
-//
-// Created by James McIlree on 10/26/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-template <typename SIZE> 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 <typename SIZE> class Machine;
-template <typename SIZE> class JetsamActivity;
-template <typename SIZE> class MachineVoucher;
-
-template <typename SIZE>
-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<SIZE>* _process;
- AbsInterval _timespan;
- AbsTime _begin_blocked;
- AbsTime _begin_vm_fault;
- AbsTime _begin_jetsam_activity;
- uint32_t _begin_jetsam_activity_type;
- std::vector<AbsInterval> _blocked;
- std::vector<AbsInterval> _vm_faults;
- std::vector<AbsInterval> _jetsam_activity;
- std::vector<VoucherInterval<SIZE>> _vouchers_by_time;
-
- //
- // Mutable API
- //
- friend class Machine<SIZE>;
- friend class MachineProcess<SIZE>;
-
- MachineProcess<SIZE>& 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<SIZE>* 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<SIZE>* process, typename SIZE::ptr_t tid, MachineVoucher<SIZE>* 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<SIZE>& process() const { return *_process; }
- uint32_t flags() const { return _flags; }
-
- const MachineVoucher<SIZE>* voucher(AbsTime timestamp) const;
- const MachineVoucher<SIZE>* last_voucher() const;
-
- const std::vector<AbsInterval>& vm_faults() const { return _vm_faults; }
- const std::vector<AbsInterval>& 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;)
-};
+++ /dev/null
-//
-// MachineThread.impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-template <typename SIZE>
-AbsTime MachineThread<SIZE>::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 <typename SIZE>
-AbsTime MachineThread<SIZE>::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 <typename SIZE>
-const MachineVoucher<SIZE>* MachineThread<SIZE>::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<SIZE>::UnsetVoucher;
-}
-
-template <typename SIZE>
-const MachineVoucher<SIZE>* MachineThread<SIZE>::last_voucher() const {
- ASSERT(!_vouchers_by_time.empty(), "Sanity");
- return _vouchers_by_time.back().voucher();
-}
-
-#if !defined(NDEBUG) && !defined(NS_BLOCK_ASSERTIONS)
-template <typename SIZE>
-void MachineThread<SIZE>::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
+++ /dev/null
-//
-// MachineThread.mutable-impl.hpp
-// KDBG
-//
-// Created by James McIlree on 10/30/12.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "KDebug.h"
-
-
-template <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::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 <typename SIZE>
-void MachineThread<SIZE>::set_voucher(MachineVoucher<SIZE>* 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<SIZE>& 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 <typename SIZE>
-void MachineThread<SIZE>::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);
- }
-}
+++ /dev/null
-//
-// 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 <typename SIZE> class Machine;
-
-enum class kMachineVoucherFlag : std::uint32_t {
- CreatedByVoucherCreate = 0x00000001,
- CreatedByFirstUse = 0x00000002,
- CreatedByPreviousMachineState = 0x00000004,
- IsNullVoucher = 0x00000008,
- IsUnsetVoucher = 0x00000010,
- IsDestroyed = 0x00000020
-};
-
-template <typename SIZE>
-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<SIZE>;
-
- 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 <typename SIZE>
-uint32_t MachineVoucher<SIZE>::voucher_id() {
- static uint32_t voucher_id = 1;
- return OSAtomicIncrement32Barrier((volatile int32_t*)&voucher_id);
-}
-
-template <typename SIZE>
-MachineVoucher<SIZE>::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 <typename SIZE>
-void MachineVoucher<SIZE>::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 <typename SIZE>
-void MachineVoucher<SIZE>::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 <typename SIZE>
-void MachineVoucher<SIZE>::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
+++ /dev/null
-//
-// 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 };
-};
+++ /dev/null
-//
-// 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 <typename SIZE>
-class NurseryMachMsg {
- protected:
- AbsTime _send_time;
- MachineVoucher<SIZE>* _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<SIZE>* 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<SIZE>* 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 <typename SIZE>
-uint32_t NurseryMachMsg<SIZE>::message_id() {
- static uint32_t message_id = 1;
- return OSAtomicIncrement32Barrier((volatile int32_t*)&message_id);
-}
-
-template <typename SIZE>
-void NurseryMachMsg<SIZE>::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<SIZE>* 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
+++ /dev/null
-//
-// 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 <typename SIZE>
-class MachineProcess;
-
-template <typename SIZE>
-class MachineThread;
-
-template <typename SIZE>
-class CPUSummary;
-
-template <typename SIZE>
-class ProcessSummary {
- public:
- typedef std::unordered_set<ThreadSummary<SIZE>, ThreadSummaryHash<SIZE>, ThreadSummaryEqualTo<SIZE>> ThreadSummarySet;
-
- protected:
- const MachineProcess<SIZE>* _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<AbsInterval> _wallclock_run_intervals; // This is the actual wallclock run interval data.
- std::vector<AbsInterval> _per_cpu_wallclock_run_intervals; // We need to accumulate intervals during summary generation, this is a temp buffer.
-
- friend class Machine<SIZE>;
- friend class CPUSummary<SIZE>;
-
- 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<SIZE>* mutable_thread_summary(const MachineThread<SIZE>* 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<ThreadSummary<SIZE>*>(&*it);
- }
-
- ThreadSummarySet& mutable_thread_summaries() { return _thread_summaries; }
-
- public:
- ProcessSummary(const MachineProcess<SIZE>* 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<SIZE>* 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<SIZE>* thread_summary(const MachineThread<SIZE>* thread) const {
- auto it = _thread_summaries.find(thread);
- return (it == _thread_summaries.end()) ? NULL : &*it;
- }
-
- DEBUG_ONLY(void validate() const;)
-};
-
-template <typename SIZE>
-void ProcessSummary<SIZE>::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 <typename SIZE>
-void ProcessSummary<SIZE>::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 <typename SIZE>
-void ProcessSummary<SIZE>::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 <typename SIZE>
-void ProcessSummary<SIZE>::validate() const {
- ASSERT(_total_wallclock_run_time <= _total_run_time, "Sanity");
-
- for (const auto& thread_summary : _thread_summaries) {
- thread_summary.validate();
- }
-}
-#endif
-
-template <typename SIZE>
-struct ProcessSummaryHash {
- size_t operator()(const ProcessSummary<SIZE>& summary) const {
- return std::hash<const MachineProcess<SIZE>*>()(summary.process());
- }
-};
-
-template <typename SIZE>
-struct ProcessSummaryEqualTo {
- bool operator()(const ProcessSummary<SIZE>& s1, const ProcessSummary<SIZE>& s2) const {
- return s1.process() == s2.process();
- }
-};
-
-#endif
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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 <typename SIZE>
-class MachineThread;
-
-template <typename SIZE>
-class ThreadSummary {
- protected:
- const MachineThread<SIZE>* _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<SIZE>;
-
- 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<SIZE>* 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<SIZE>* 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 <typename SIZE>
-void ThreadSummary<SIZE>::validate() const {
-}
-#endif
-
-template <typename SIZE>
-struct ThreadSummaryHash {
- size_t operator()(const ThreadSummary<SIZE>& summary) const {
- return std::hash<const MachineThread<SIZE>*>()(summary.thread());
- }
-};
-
-template <typename SIZE>
-struct ThreadSummaryEqualTo {
- bool operator()(const ThreadSummary<SIZE>& s1, const ThreadSummary<SIZE>& s2) const {
- return s1.thread() == s2.thread();
- }
-};
-
-#endif
+++ /dev/null
-//
-// TraceCodes.cpp
-// KDBG
-//
-// Created by James McIlree on 4/16/13.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "KDebug.h"
-
-std::vector<std::string> default_trace_code_paths() {
- // As of 4/17/2013, this is a single file.
- return { "/usr/share/misc/trace.codes" };
-}
-
-std::unordered_map<uint32_t, std::string> trace_codes_at_path(const char* path)
-{
- std::unordered_map<uint32_t, std::string> 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<uint32_t, std::string> resolve_trace_codes(bool should_read_default_codes, int output_fd, std::vector<std::string>& additional_paths) {
- std::unordered_map<uint32_t, std::string> codes;
-
- std::vector<std::string> paths;
-
- if (should_read_default_codes) {
- std::vector<std::string> 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<uint32_t, std::string> 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;
-}
+++ /dev/null
-//
-// 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<std::string> default_trace_code_paths();
-std::unordered_map<uint32_t, std::string> trace_codes_at_path(const char* path);
-
-//
-// Set output_fd to an open fd to print verbose output/warnings.
-//
-std::unordered_map<uint32_t, std::string> resolve_trace_codes(bool should_read_default_codes, int output_fd, std::vector<std::string>& additional_paths);
-
-#endif /* defined(__kdprof__TraceCodes__) */
+++ /dev/null
-//
-// 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 <typename KERNEL_SIZE> class TraceDataHeaderFields {};
-
-template <>
-class TraceDataHeaderFields<Kernel32> {
- 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<Kernel64> {
- 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 <typename KERNEL_SIZE>
-class TraceDataHeader {
- private:
- TraceDataHeaderFields<KERNEL_SIZE> _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; }
-};
-
+++ /dev/null
-//
-// 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<Kernel64>(sort_events, default_ap_count, default_iop_count);
- } catch (...) {
- parse<Kernel32>(sort_events, default_ap_count, default_iop_count);
- }
-}
+++ /dev/null
-//
-// 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<uint8_t> _time_sorted_events; // This is empty unless event sorting is requested.
- std::vector<KDCPUMapEntry> _default_cpumap; // If the file does not contain a cpumap, this will be used instead
-
- template <typename SIZE>
- void sanity_check_event_data();
-
- template <typename SIZE>
- 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 <typename SIZE>
- const KDThreadMapEntry<SIZE>* threadmap() const { return reinterpret_cast<KDThreadMapEntry<SIZE>*>(_threadmap); }
- uint32_t threadmap_count() const { return _threadmap_count; }
-
- template <typename SIZE>
- const KDEvent<SIZE>* events() const { return reinterpret_cast<KDEvent<SIZE>*>(_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 <typename SIZE>
-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_check_count; i++) {
- KDEvent<SIZE>& event = reinterpret_cast<KDEvent<SIZE>*>(_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 <typename SIZE>
-void TraceFile::parse(bool should_presort_events, uint32_t default_ap_count, uint32_t default_iop_count) {
- if (TraceDataHeader<SIZE>* header = reinterpret_cast<TraceDataHeader<SIZE>*>(_file.address())) {
- KDThreadMapEntry<SIZE>* threadmap = NULL;
- uint32_t threadmap_count = 0;
- KDCPUMapEntry* cpumap = NULL;
- uint32_t cpumap_count = 0;
- KDEvent<SIZE>* 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<KDThreadMapEntry<SIZE>*>(_file.address() + 4);
-
- // Event data starts immediately following the threadmap
- size_t offset = 4 + threadmap_count * sizeof(KDThreadMapEntry<SIZE>);
- events = reinterpret_cast<KDEvent<SIZE>*>(_file.address() + offset);
-
- version = kTraceFileVersion::V0;
- } else {
- //
- // RAW_VERSION1
- //
- threadmap_count = header->thread_count();
- threadmap = reinterpret_cast<KDThreadMapEntry<SIZE>*>(_file.address() + sizeof(TraceDataHeader<SIZE>));
-
- size_t threadmap_size_in_bytes = threadmap_count * sizeof(KDThreadMapEntry<SIZE>);
- size_t offset_to_event_data = (sizeof(TraceDataHeader<SIZE>) + threadmap_size_in_bytes + 4095) & ~4095;
- size_t offset_to_cpumap_data = sizeof(TraceDataHeader<SIZE>) + 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<kd_cpumap_header*>(_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<KDEvent<SIZE>*>(_file.address() + offset_to_event_data);
- }
-
- uintptr_t event_count = (uintptr_t)_file.size() - (reinterpret_cast<uintptr_t>(events) - reinterpret_cast<uintptr_t>(_file.address()));
- if (event_count % sizeof(KDEvent<SIZE>) != 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<SIZE>);
-
- 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<default_ap_count; ++i) {
- _default_cpumap.emplace_back(i, 0, "AP-???");
- }
- uint32_t iop_limit = default_ap_count + default_iop_count;
- for (uint32_t i=default_ap_count; i<iop_limit; ++i) {
- _default_cpumap.emplace_back(i, KDBG_CPUMAP_IS_IOP, "IOP-???");
- }
-
- cpumap = _default_cpumap.data();
- cpumap_count = (uint32_t)_default_cpumap.size();
-
- version = kTraceFileVersion::V1;
- } else {
- version = kTraceFileVersion::V1Plus;
- }
-
-
- // IOP's have been producing .trace files with out of order events.
- // This is a hack fix to work around that. It costs a full copy of the data!
- MemoryBuffer<KDEvent<SIZE>> presorted_events;
- if (should_presort_events && event_count) {
- _time_sorted_events.reserve(event_count * sizeof(KDEvent<SIZE>));
- memcpy(_time_sorted_events.data(), events, event_count * sizeof(KDEvent<SIZE>));
- events = reinterpret_cast<KDEvent<SIZE>*>(_time_sorted_events.data());
- std::sort(events, events + event_count, [](KDEvent<SIZE> const& p0, KDEvent<SIZE> 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<SIZE>();
-
- //
- // Okay, success if we made it this far.
- //
- _is_valid = true;
- }
-}
-
-#endif /* defined(__system_cmds__TraceFile__) */
+++ /dev/null
-//
-// 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 <typename SIZE>
-class VoucherInterval : public AbsInterval {
- MachineVoucher<SIZE>* _voucher;
-
- public:
- VoucherInterval(MachineVoucher<SIZE>* voucher, AbsInterval interval) :
- AbsInterval(interval),
- _voucher(voucher)
- {
- }
-
- const MachineVoucher<SIZE>* voucher() const { return _voucher; }
-};
-
-#endif
/*
- * 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
* 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,
* 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.
*/
* 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;
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 */
* 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 */
* is someone logged in on Console?
*/
int
-on_console(head)
- struct utmp_list *head;
+on_console(struct utmp_list *head)
{
struct utmp_list *up;
* 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;
*/
if (Flags & AC_U)
return head;
-
+
if ((up = NEW(struct user_list)) == NULL)
err(1, "malloc");
up->next = head;
}
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char **argv)
{
FILE *fp;
int c;
if (Flags & AC_D)
Flags &= ~AC_P;
ac();
-
+
return 0;
}
* 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;
* 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;
/* 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);
secs += up->secs;
up->secs = 0; /* for next day */
}
- if (secs)
+ if (secs)
(void)printf("%s %11.2f\n", date, ((double)secs / 3600));
}
* 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) {
* 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;
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;
/*
}
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)
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) {
}
void
-usage()
+usage(void)
{
(void)fprintf(stderr,
#ifdef CONSOLE_TTY
}
static void
-usage()
+usage(void)
{
(void)fprintf(stderr, "usage: accton [file]\n");
exit(1);
/*
- * 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,
* 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 <glob.h>
#include <CoreFoundation/CoreFoundation.h>
#include <NSSystemDirectories.h>
+#include <sysdir.h>
#ifndef ARCH_PROG
#define ARCH_PROG "arch"
arch(int archcmd)
{
const NXArchInfo *arch = NXGetLocalArchInfo();
-
+
if(!arch)
errx(-1, "Unknown architecture.");
if(archcmd) {
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");
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 */
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 */
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;
}
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;
}
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 */
} 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);
}
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, '/')) {
}
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");
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
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"))) {
}
/* 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.
*/
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");
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");
}
-/*
+/*
* at.c : Put file into atrun queue
* Copyright (C) 1993, 1994 Thomas Koenig
*
/* Macros */
-#ifndef ATJOB_DIR
+#ifndef ATJOB_DIR
#define ATJOB_DIR _PATH_ATJOBS
#endif
/* 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)
{
_exit(EXIT_FAILURE);
}
-static void alarmc(int signo __unused)
+static void
+alarmc(int signo __unused)
{
char buf[1024];
/* Local functions */
-static char *cwdname(void)
+static char *
+cwdname(void)
{
/* Read in the current directory; the name will be overwritten on
* subsequent calls.
if (getcwd(ptr, size-1) != NULL)
return ptr;
-
+
if (errno != ERANGE)
perr("cannot get directory");
-
+
free (ptr);
size += SIZE;
if ((ptr = malloc(size)) == NULL)
mode_t cmask;
struct flock lock;
char * oldpwd_str = NULL;
-
+
#ifdef __FreeBSD__
(void) setlocale(LC_TIME, "");
#endif
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 ++)
*/
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");
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;
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);
for (i=0; i<sizeof(no_export)/sizeof(no_export[0]); i++)
{
export = export
- && (strncmp(*atenv, no_export[i],
+ && (strncmp(*atenv, no_export[i],
(size_t) (eqp-*atenv)) != 0);
}
}
fputs("; export ", fp);
fwrite(*atenv, sizeof(char), eqp-*atenv -1, fp);
fputc('\n', fp);
-
+
}
- }
+ }
/* Cd to the directory at the time and write out all the
* commands the user supplies from stdin.
*/
{
if (*ap != '/' && !isalnum(*ap))
fputc('\\', fp);
-
+
fputc(*ap, fp);
}
}
fprintf(fp, "\n");
if (ferror(fp))
panic("output error");
-
+
if (ferror(stdin))
panic("input error");
fprintf(stderr, "Job %ld will be executed using /bin/sh\n", jobno);
}
-static int
+static int
in_job_list(long job, long *joblist, int len)
{
int i;
if (stat(name, &buf) != 0)
perr("cannot stat in " ATJOB_DIR);
-
+
/* See it's a regular file and has its x bit turned on and
* is the user's
*/
else {
struct passwd *pw = getpwuid(buf.st_uid);
- printf("%s\t%s\t%c%s\t%s\n",
- timestr,
- pw ? pw->pw_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);
}
}
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
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);
PRIV_END
- /* Loop over every file in the directory
+ /* Loop over every file in the directory
*/
while((dirent = readdir(spool)) != NULL) {
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)
*p++ = '\0';
t->tm_sec = ATOI2(p);
}
-
+
yearset = 0;
switch(strlen(arg)) {
case 12: /* CCYYMMDDhhmm */
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)
timer = -1;
RELINQUISH_PRIVS
- if (argv[0] == NULL)
+ if (argv[0] == NULL)
usage();
/* Eat any leading paths
*/
case 'f':
atinput = optarg;
break;
-
+
case 'q': /* specify queue */
if (strlen(optarg) > 1)
usage();
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)
timer = parsetime(argc, argv);
else
timer = time(NULL);
-
+
if (atverify)
{
struct tm *tm = localtime(&timer);
-/*
+/*
* at.h - header for at(1)
* Copyright (C) 1993 Thomas Koenig
*
-/*
+/*
* panic.c - terminate fast in case of error
* Copyright (C) 1993 Thomas Koenig
*
-/*
+/*
* panic.h - header for at(1)
* Copyright (C) 1993 Thomas Koenig
*
-/*
+/*
* parsetime.c - parse time for at(1)
* Copyright (C) 1993, 1994 Thomas Koenig
*
} /* plonk */
-/*
+/*
* expect() gets a token and dies most horribly if it's not the token we want
*/
static void
tm->tm_min += delay;
break;
default:
- plonk(sc_tokid);
+ plonk(sc_tokid);
break;
}
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");
}
{
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
*/
panic("garbled time");
hour = hour/100;
}
-
+
/* check if an AM or PM specifier was given
*/
switch (sc_tokid) {
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;
}
if (UTC != token())
break; /* else fallthrough */
-
+
case UTC:
hour += tm->tm_gmtoff/(60*60);
while (hour < 0)
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) {
} /* assign_date */
-/*
+/*
* month() picks apart a month specification
*
* /[<month> NUMBER [NUMBER]] \
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) {
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
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 */
-/*
+/*
* at.h - header for at(1)
* Copyright (C) 1993 Thomas Koenig
*
/*
- * 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
* 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,
* 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 _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/"
-/*
+/*
* perm.c - check user permission for at(1)
* Copyright (C) 1994 Thomas Koenig
*
-/*
+/*
* perm.h - header for at(1)
* Copyright (C) 1994 Thomas Koenig
*
-/*
- * 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
#endif
uid_t real_uid, effective_uid;
-#ifndef MAIN
+#ifndef MAIN
extern
#endif
gid_t real_gid, effective_gid;
-/*
+/*
* atrun.c - run jobs queued by at; run with root privileges.
* Copyright (C) 1993, 1994 Thomas Koenig
*
pid = fork();
if (pid == -1)
perr("cannot fork");
-
+
else if (pid != 0)
return;
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");
if (mailbuf[0] == '-')
perrx("Illegal mail name %s in %s", mailbuf, filename);
-
+
mailname = mailbuf;
if (nuid != uid)
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");
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
-
+
pid = fork();
if (pid < 0)
perr("error in fork");
PRIV_START
nice(tolower(queue) - 'a');
-
+
#ifdef LOGIN_CAP
/*
* For simplicity and safety, set all aspects of the user context
unlink(filename);
if ((buf.st_size != size) || send_mail)
- {
+ {
PRIV_START
#ifdef LOGIN_CAP
{
switch (c)
{
- case 'l':
+ case 'l':
if (sscanf(optarg, "%lf", &load_avg) != 1)
perr("garbled option -l");
if (load_avg <= 0.)
/* 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)
batch_uid = buf.st_uid;
batch_gid = buf.st_gid;
}
-
+
/* The file is executable and old enough
*/
if (islower(queue))
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);
}
-/*
+/*
* gloadavg.c - get load average for Linux
* Copyright (C) 1993 Thomas Koenig
*
double result;
#ifndef __FreeBSD__
FILE *fp;
-
+
if((fp=fopen(PROC_DIR "loadavg","r")) == NULL)
result = -1.0;
else
-/*
+/*
* gloadavg.h - header for atrun(8)
* Copyright (C) 1993 Thomas Koenig
*
/*
- * 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
* 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,
* 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 <stdio.h>
#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;
return s;
}
-struct passwd *
+static struct passwd *
parse_user(char *line)
{
static struct passwd pw = {0};
return &pw;
}
-struct passwd *
+static struct passwd *
find_user(char *uname, FILE *fp)
{
char *line;
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+");
fclose(tfp);
unlink(fname);
}
+#endif /* 0 */
int
file_check_passwd(char *uname, char *locn)
/*
- * 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
* 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,
* 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.
#include <string.h>
#include <pwd.h>
#include <netinet/in.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_clnt.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/yppasswd.h>
#include <sys/file.h>
#include <errno.h>
-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;
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)
(void)fprintf(stderr, "user %s not found\n", uname);
exit(1);
}
-
+
checkpasswd(uname, pwd->pw_passwd);
return(0);
}
-
+
static char *
pwskip(register char *p)
{
return (p);
}
-struct passwd *
+static struct passwd *
interpret(struct passwd *pwent, char *line)
{
register char *p = line;
return (pwent);
}
-
static struct passwd *
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:
-/*
- * 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.
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <OpenDirectory/OpenDirectory.h>
+#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;
}
}
}
-
+
if (!authenticated) {
fprintf(stderr, "Sorry\n");
exit(1);
return 0;
}
-
-
-
-
-
-
/*
- * 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,
* 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 <stdio.h>
#include <security/pam_appl.h>
#include <security/openpam.h> /* for openpam_ttyconv() */
+#include "passwd.h"
+
extern char* progname;
static pam_handle_t *pamh;
static struct pam_conv pamc;
// pam_check_passwd
//-------------------------------------------------------------------------------------
-int pam_check_passwd(char* uname)
+int
+pam_check_passwd(char* uname)
{
int retval = PAM_SUCCESS;
/* 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;
/*
- * 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
* 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,
* 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
#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)
{
return;
}
-void
-usage()
+static void
+usage(void)
{
fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n");
fprintf(stderr, " infosystem:\n");
}
argc -= optind;
argv += optind;
-
+
if (argc > 1) {
usage();
} else if (argc == 1) {
exit(1);
}
}
-
+
switch (infosystem)
{
case INFO_FILE:
exit(0);
}
-
--- /dev/null
+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 *);
/*
- * 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
* 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,
* 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 <string.h>
#import <stdarg.h>
#import "stringops.h"
-char *copyString(char *s)
+char *
+copyString(char *s)
{
- int len;
+ size_t len;
char *t;
if (s == NULL) return NULL;
return t;
}
-char *concatString(char *s, char *t)
+char *
+concatString(char *s, char *t)
{
- int len;
+ size_t len;
if (t == NULL) return s;
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);
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;
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;
return i;
}
-unsigned int listIndex(char *s,char **l)
+unsigned int
+listIndex(char *s,char **l)
{
int i;
return IndexNull;
}
-char *prefix(char *s, char c)
+char *
+prefix(char *s, char c)
{
int i;
char *t;
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;
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;
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;
return t;
}
-char *lowerCase(char *s)
+char *
+lowerCase(char *s)
{
int i;
char *t;
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];
return t;
}
-char **explode(char *s, char c)
+char **
+explode(char *s, char c)
{
char **l = NULL;
char *p, *t;
/*
- * 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
* 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,
* 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)
/*
- * 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,
* 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@
*/
/*-
CFStringRef username = NULL;
CFStringRef authname = NULL;
CFStringRef location = NULL;
-
+
progname = strrchr(argv[0], '/');
if (progname) progname++;
else progname = argv[0];
} 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.
CFDictionaryRef attrs_orig = NULL;
CFDictionaryRef attrs = NULL;
ODRecordRef rec = odGetUser(location, authname, username, &attrs_orig);
-
+
if (!rec || !attrs_orig) exit(1);
#endif /* OPEN_DIRECTORY */
#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) {
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 */
#ifdef OPEN_DIRECTORY
odUpdateUser(rec, attrs_orig, attrs);
-
+
if (rec) CFRelease(rec);
exit(0);
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
/*
- * 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,
* 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@
*/
/*
/*
- * 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,
* 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@
*/
/*-
(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) {
/*
- * 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,
* 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@
*/
/*
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);
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);
return (0);
}
-
#ifdef OPEN_DIRECTORY
#include <uuid/uuid.h>
/* ARGSUSED */
// 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;
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
}
desc = CFErrorCopyFailureReason(error);
if (desc) cfprintf(stderr, " %@", desc);
-
+
desc = CFErrorCopyRecoverySuggestion(error);
if (desc) cfprintf(stderr, " %@", desc);
-
+
fprintf(stderr, "\n");
}
}
*/
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);
CFErrorRef error = NULL;
int updated = 0;
ENTRY* ep;
-
+
for (ep = list; ep->prompt; ep++) {
-
+
// Nothing to update
if (!rec || !attrs_orig || !attrs) break;
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;
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.
/*
- * 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,
* 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@
*/
/*-
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;
/*
- * 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,
* 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@
*/
/*-
/*
- * 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,
* 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@
*/
/*-
/*
- * 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,
* 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@
*/
/*-
if (!*mp)
goto bad;
if (!strncasecmp(*mp, t, 3)) {
- month = mp - months + 1;
+ month = (int)(mp - months + 1);
break;
}
}
#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;
}
/*
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)
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 */
/*
- * 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
* 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,
* 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 <sys/sysctl.h>
#include <libproc.h>
-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);
free(msgbuf);
exit(0);
}
-
+++ /dev/null
-/*
- * 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 <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-
-simpleroutine backing_store_alert(
- alert_port : mach_port_t;
- in flags : int);
+++ /dev/null
-/*
- * 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 <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-
-simpleroutine backing_store_triggers(
- dynamic_pager : mach_port_t;
- in hi_wat : int;
- in flags : int;
- in trigger_port : mach_port_t);
+++ /dev/null
-#include <default_pager/default_pager_alerts.defs>
-
#define mig_external
#include <sys/mount.h>
* -- it could set the prefix for the swapfile name.
*/
-
static void
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);
}
}
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);
}
}
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
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
/*
- * 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
* 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,
* 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 <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <strings.h>
-#include <nlist.h>
#include <fcntl.h>
#include <aio.h>
#include <string.h>
#include <err.h>
#include <libutil.h>
+#include <ktrace.h>
+#include <assert.h>
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/mman.h>
-#include <sys/sysctl.h>
#include <sys/disk.h>
#include <sys/file.h>
-
-#ifndef KERNEL_PRIVATE
-#define KERNEL_PRIVATE
-#include <sys/kdebug.h>
-#undef KERNEL_PRIVATE
-#else
-#include <sys/kdebug.h>
-#endif /*KERNEL_PRIVATE*/
+#include <sys/fcntl.h>
#import <mach/clock_types.h>
#import <mach/mach_time.h>
-
-
-#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[] = {
- "<TEXT> ",
- "<DATA> ",
- "<OBJC> ",
- "<IMPORT> ",
- "<UNICODE> ",
- "<IMAGE> ",
- "<LINKEDIT>",
-};
-
-
-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
(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)
#define MSC_map_fd 0x010c00ac
#define BSC_BASE 0x040C0000
-#define MSC_BASE 0x010C0000
// Network related codes
#define BSC_recvmsg 0x040C006C
#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
#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
#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
#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
#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
#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
#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");
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);
+ }
+
+ /* <rdar://problem/19852325> 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);
- // <rdar://problem/19852325> 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(" <CMD=%d>", (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(" <CMD=0x%x>", (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(" <DKIOCSYNCHRONIZE> 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(" <DKIOCSYNCHRONIZECACHE> /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(" <DKIOCUNMAP> /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(" <CMD=%d>", 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(" <CMD=0x%x>", 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(" <DKIOCSYNCHRONIZE> B=%d /dev/%s", arg3, find_disk_name(arg1));
+ clen += printf(">");
+ }
- break;
- }
+ break;
- case FMT_IOCTL_SYNCCACHE:
- {
- /*
- * ioctl
- */
- clen += printf(" <DKIOCSYNCHRONIZECACHE> /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(" <DKIOCUNMAP> /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] <FLGS=0x%lx> ", (int)event->arg1, ti->arg3);
+ else
+ clen += printf(" <FLGS=0x%lx> ", 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 = "<FORCE>";
+ 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] <FLGS=0x%x> ", arg1, ti->arg3);
- else
- clen += printf(" <FLGS=0x%x> ", ti->arg3);
-
- nopadding = 1;
- break;
- }
-
- case FMT_UNMOUNT:
- {
- char *mountflag;
-
- if (ti->arg2 & MNT_FORCE)
- mountflag = "<FORCE>";
- 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;
+ }
}
}
* 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;
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;
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];
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 "/" */
while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
substring++;
+
*substring = 0;
- }
- else
- {
+ } else {
/*
* No ".": take segment after last "/"
*/
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
*/
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
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
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[] = {
+ "<TEXT> ",
+ "<DATA> ",
+ "<OBJC> ",
+ "<IMPORT> ",
+ "<UNICODE> ",
+ "<IMAGE> ",
+ "<LINKEDIT>",
+ };
+
+ *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;
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];
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
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)
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;
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)
}
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);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "corefile.h"
+#include "sparse.h"
+#include "utils.h"
+#include "vm.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <compression.h>
+#include <sys/param.h>
+#include <libgen.h>
+
+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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include "loader_additions.h"
+#include "dyld_shared_cache.h"
+#include "region.h"
+
+#include <mach-o/loader.h>
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <sys/types.h>
+
+#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 */
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "dyld.h"
+#include "utils.h"
+#include "corefile.h"
+#include "vm.h"
+
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach-o/dyld_process_info.h>
+
+#include <mach/mach.h>
+#include <mach/task.h>
+#include <mach/mach_vm.h>
+#include <mach/shared_region.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <libgen.h>
+#include <sys/stat.h>
+
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "corefile.h"
+
+#include <mach-o/dyld_images.h>
+#include <mach-o/dyld_process_info.h>
+#include <uuid/uuid.h>
+
+#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 */
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "dyld_shared_cache.h"
+#include "utils.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fts.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <uuid/uuid.h>
+#include <sys/types.h>
+
+#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 */
--- /dev/null
+.Dd 2/10/16\r
+.Dt gcore 1\r
+.Os Darwin\r
+.Sh NAME\r
+.Nm gcore\r
+.Nd get core images of running processes\r
+.Sh SYNOPSIS\r
+.Nm\r
+.Op Fl s\r
+.Op Fl v\r
+.Op Fl b Ar size\r
+.Op Fl o Ar path | Fl c Ar pathformat\r
+.Ar pid\r
+.Sh DESCRIPTION\r
+The\r
+.Nm gcore\r
+program creates a core file image of the process specified by\r
+.Ar pid .\r
+The resulting core file can be used with a debugger, e.g.\r
+.Xr lldb(1) ,\r
+to examine the state of the process.\r
+.Pp\r
+The following options are available:\r
+.Bl -tag -width Fl\r
+.It Fl s\r
+Suspend the process while the core file is captured.\r
+.It Fl v\r
+Report progress on the dump as it proceeds.\r
+.It Fl b Ar size\r
+Limit the size of the core file to\r
+.Ar size\r
+MiBytes.\r
+.El\r
+.Pp\r
+The following options control the name of the core file:\r
+.Bl -tag -width flag\r
+.It Fl o Ar path\r
+Write the core file to\r
+.Ar path .\r
+.It Fl c Ar pathformat\r
+Write the core file to\r
+.Ar pathformat .\r
+The\r
+.Ar pathformat\r
+string is treated as a pathname that may contain various special\r
+characters which cause the interpolation of strings representing\r
+specific attributes of the process into the name.\r
+.Pp\r
+Each special character is introduced by the\r
+.Cm %\r
+character. The format characters and their meanings are:\r
+.Bl -tag -width Fl\r
+.It Cm N\r
+The name of the program being dumped, as reported by\r
+.Xr ps 1 .\r
+.It Cm U\r
+The uid of the process being dumped, converted to a string.\r
+.It Cm P\r
+The pid of the process being dumped, converted to a string.\r
+.It Cm T\r
+The time when the core file was taken, converted to ISO 8601 format.\r
+.It Cm %\r
+Output a percent character.\r
+.El\r
+.El\r
+.Pp\r
+The default file name used by\r
+.Nm gcore\r
+is\r
+.Ar %N-%P-%T .\r
+By default, the core file will be written to a directory whose\r
+name is determined from the\r
+.Ar kern.corefile\r
+MIB. This can be printed or modified using\r
+.Xr sysctl 8 .\r
+.Pp\r
+The directory where the core file is to be written must be\r
+accessible to the owner of the target process.\r
+.Pp\r
+.Nm gcore\r
+will not overwrite an existing file,\r
+nor will it create missing directories in the path.\r
+.Sh EXIT_STATUS\r
+.Ex -std\r
+.Pp\r
+.Sh FILES\r
+.Bl -tag -width "/cores/%N-%P-%T plus" -compact\r
+.It Pa /cores/%N-%P-%T\r
+default pathname for the corefile.\r
+.El\r
+.Sh BUGS\r
+With the\r
+.Fl b\r
+flag,\r
+.Nm gcore\r
+writes out as much data as it can up to the specified limit,\r
+even if that results in an incomplete core image.\r
+Such a partial core dump may confuse subsequent\r
+programs that attempt to parse the contents of such files.\r
+.Sh SEE ALSO \r
+.Xr lldb 1 ,\r
+.Xr core 5 ,\r
+.Xr Mach-O 5 ,\r
+.Xr sysctl 8 ,\r
+.Xr sudo 8 .\r
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include <mach-o/loader.h>
+
+#ifndef _LOADER_ADDITIONS_H
+#define _LOADER_ADDITIONS_H
+
+/*
+ * Something like this should end up in <mach-o/loader.h>
+ */
+#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 */
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "utils.h"
+#include "corefile.h"
+#include "vanilla.h"
+#include "sparse.h"
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libproc.h>
+
+#include <sys/kauth.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <libutil.h>
+
+#include <mach/mach.h>
+
+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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <compression.h>
+
+#include <assert.h>
+
+#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 */
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <mach/mach.h>
+#include <uuid/uuid.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libproc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include <mach/mach.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "utils.h"
+#include "threads.h"
+#include "corefile.h"
+
+#include <sys/types.h>
+#include <mach/mach.h>
+#include <mach/task.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include "corefile.h"
+#include <mach/task.h>
+
+#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 */
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "utils.h"
+#include "region.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <libutil.h>
+
+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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <uuid/uuid.h>
+#include <mach/mach_types.h>
+#include <sysexits.h>
+#include <err.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libproc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sysexits.h>
+
+#include <mach/mach.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include "options.h"
+#include "vm.h"
+#include "utils.h"
+#include "region.h"
+#include "sparse.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include <sys/queue.h>
+
+/*
+ * There should be better APIs to describe the shared region
+ * For now, some hackery.
+ */
+
+#include <mach/shared_region.h>
+
+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 <System/machine/cpu_capabilities.h>
+
+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
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ */
+
+#include <mach/mach.h>
+#include <mach/mach_port.h>
+#include <mach/task.h>
+#include <mach/mach_vm.h>
+#include <stdbool.h>
+
+#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 */
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);
else
printf("%ld\n", value);
}
-
* For semi-intelligent modem handling.
*/
+#include <sys/cdefs.h>
+
#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 */
}
}
alarm(0);
- chat_unalarm();
- alarmed = 0;
- free(got);
+ chat_unalarm();
+ alarmed = 0;
+ free(got);
}
}
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);
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+
#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 */
{ "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 */
#include <sys/cdefs.h>
#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 */
#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 */
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);
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) {
}
sleep(60);
}
- if (login_tty(i) < 0) {
+ if (login_tty(i) < 0) {
#ifndef __APPLE__
if (daemon(0,0) < 0) {
syslog(LOG_ERR,"daemon: %m");
}
static void
-defttymode()
+defttymode(void)
{
/* Start with default tty settings. */
static void
dogettytab()
{
-
/* Read the database entry. */
gettable(tname);
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+
#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 */
#include "pathnames.h"
#include "extern.h"
-
-
/*
* Get a table entry.
*/
/*
- * 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
* 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,
* 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
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;
exit(EXIT_FAILURE);
}
-
if (hi.max_cpus > 1)
printf("Kernel configured for up to %d processors.\n",
hi.max_cpus);
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");
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",
exit(0);
}
-
#include <limits.h>
#include <errno.h>
-#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;
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");
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);
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;
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)
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;
void *sync_routine(void *arg)
{
- while(1) {
+ while(1) {
usleep(sync_frequency_ms * 1000);
sync();
}
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)
{
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);
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);
memset(data, '\0', io_size);
while(1) {
-
burst_elapsed = 0;
for(i = 0; i < burst_count; i++) {
exit(1);
}
}
-
gettimeofday(&start_tv, NULL);
perform_io(fd, data, io_size, workload_type);
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);
}
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;
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);
}
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);
/* 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);
-
}
/*
- * 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
* 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,
* 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@
*/
/*
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
maxshowdevs = 4;
} else {
if ((dflag > 0) && (Cflag == 0))
- maxshowdevs = 4;
+ maxshowdevs = 4;
else
maxshowdevs = 3;
}
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++;
headercount = 20;
do_phdr();
}
-
+
last_time = cur_time;
gettimeofday(&cur_time, NULL);
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);
phdr(int signo)
{
- phdr_flag = 1;
+ phdr_flag = 1;
}
static void
-do_phdr()
+do_phdr(void)
{
register int i;
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");
(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 ");
}
* 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;
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;
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) {
transfers_per_second,
msdig,
ms_per_transaction);
- else
+ else
printf("%4.1qu%4.1qu%5.*Lf ",
interval_blocks,
interval_transfers,
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);
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);
last.load.cpu_ticks[CPU_STATE_IDLE]
+= cur.load.cpu_ticks[CPU_STATE_IDLE];
time += cur.load.cpu_ticks[CPU_STATE_IDLE];
-
+
/*
* Print times.
*/
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;
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))) {
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))) {
CFStringRef name;
CFNumberRef number;
kern_return_t status;
-
+
/* get drive's parent */
status = IORegistryEntryGetParentEntry(drive,
kIOServicePlane, &parent);
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");
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// CollectAction.cpp
-// kdprof
-//
-// Created by James McIlree on 4/17/13.
-// Copyright (c) 2013 Apple. All rights reserved.
-//
-
-#include "global.h"
-
-template <typename SIZE>
-static void execute_arch_specific(Globals& globals, KDState& state) {
- // Collect all data first, printing takes time...
- auto threadmap = KDBG::threadmap<SIZE>(state);
- auto cpumap = KDBG::cpumap();
-
- MemoryBuffer<KDEvent<SIZE>> events(state.capacity());
- int count = KDBG::read(events.data(), events.capacity() * sizeof(KDEvent<SIZE>));
-
- // 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<SIZE> const& p0, KDEvent<SIZE> const& p1) -> bool {
- return p0.timestamp() < p1.timestamp();
- });
- }
- Machine<SIZE> machine((KDCPUMapEntry*)cpumap.data(), (uint32_t)cpumap.size(), (KDThreadMapEntry<SIZE>*)threadmap.data(), (uint32_t)threadmap.size(), (KDEvent<SIZE>*)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<Kernel64>(globals, state);
- } else {
- execute_arch_specific<Kernel32>(globals, state);
- }
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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");
- }
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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");
- }
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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");
-}
+++ /dev/null
-//
-// 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 <typename SIZE>
-char* print_event(char* buf, char* buf_end, const Globals& globals, const Machine<SIZE>& machine, const KDEvent<SIZE>& 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<SIZE>& 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<SIZE>* 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 <typename SIZE>
-char* print_event_range_to_buffer(const Globals& globals, const Machine<SIZE>& machine, TRange<uintptr_t> range, MemoryBuffer<char>& buffer ) {
- char* cursor = buffer.data();
- char* cursor_end = cursor + buffer.capacity();
-
- if (const KDEvent<SIZE>* events = machine.events()) {
- ASSERT(TRange<uintptr_t>(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<char> _buffer;
- TRange<uintptr_t> _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<char>&& buffer, TRange<uintptr_t> 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<char>& buffer() { return _buffer; }
-
- TRange<uintptr_t> event_range() { return _event_range; }
- void set_event_range(TRange<uintptr_t> range) { _event_range = range; }
-
- char* buffer_end() const { return _buffer_end; }
- void set_buffer_end(char* buffer_end) { _buffer_end = buffer_end; }
-};
-
-template <typename SIZE>
-class PrintProducer {
- protected:
- const Globals& _globals;
- const Machine<SIZE>& _machine;
- uintptr_t _start_index;
- uintptr_t _end_index;
- uintptr_t _chunk_size;
-
- public:
- PrintProducer(const Globals& globals, const Machine<SIZE>& 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<SIZE> 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<SIZE> 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<uintptr_t> 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 <typename SIZE>
-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<SIZE>& machine, uintptr_t start_index) :
- _globals(globals),
- _write_index(start_index)
- {
- }
-
- void consume(PrintWorkUnit& work_unit) {
- std::unique_lock<std::mutex> 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 <typename SIZE>
-uintptr_t print_machine_events(const Globals& globals, const Machine<SIZE>& machine) {
- print_event_header(globals, SIZE::is_64_bit);
-
- if (const KDEvent<SIZE>* 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<SIZE> producer(globals, machine, chunk_size);
- PrintConsumer<SIZE> consumer(globals, machine, producer.start_index());
-
- std::vector<std::thread> threads;
- for (uint32_t i=0; i<active_cpus; ++i) {
- threads.push_back(std::thread([&]() {
- PrintWorkUnit work_unit(MemoryBuffer<char>(160 * chunk_size), TRange<uintptr_t>(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
+++ /dev/null
-//
-// 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();
-}
+++ /dev/null
-//
-// 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<std::string> _additional_trace_code_paths;
- std::unordered_map<uint32_t, std::string> _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<uint32_t, std::string>& trace_codes() const { return _trace_codes; }
- void set_trace_codes(std::unordered_map<uint32_t, std::string>&& 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<SIZE>'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
+++ /dev/null
-//
-// 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");
- }
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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);
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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");
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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();
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// SaveTraceAction.cpp
-// kdprof
-//
-// Created by James McIlree on 5/2/13.
-// Copyright (c) 2013 Apple. All rights reserved.
-//
-
-#include "global.h"
-
-template <typename SIZE>
-static void execute_arch_specific(Globals& globals, KDState& state, FileDescriptor& save_fd) {
- // Collect all data first, printing takes time...
- auto threadmap = KDBG::threadmap<SIZE>(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<SIZE>) + (threadmap.size() * sizeof(KDThreadMapEntry<SIZE>))) & 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<SIZE> header(RAW_VERSION1, (uint32_t)threadmap.size(), time(NULL), 0);
- write(save_fd, &header, sizeof(TraceDataHeader<SIZE>));
-
- // Write the threadmaps
- write(save_fd, threadmap.data(), threadmap.size() * sizeof(KDThreadMapEntry<SIZE>));
-
- if (extra_thread_count) {
- pad_size = extra_thread_count * sizeof(KDThreadMapEntry<SIZE>);
- 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<SIZE>) + (threadmap.size() + extra_thread_count) * sizeof(KDThreadMapEntry<SIZE>);
- 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<SIZE>);
- MemoryBuffer<KDEvent<SIZE>> 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<SIZE>));
-
- 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<Kernel64>(globals, state, _save_fd);
- } else {
- execute_arch_specific<Kernel32>(globals, state, _save_fd);
- }
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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);
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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");
-}
+++ /dev/null
-//
-// 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 <typename SIZE>
-void print_summary_line(const Globals& globals, const Machine<SIZE>& 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 <typename SIZE>
-void print_cpu_summary_with_name_and_indent(const Globals& globals, const Machine<SIZE>& machine, AbsInterval summary_interval, const CPUSummary<SIZE>& master_summary, const CPUSummary<SIZE>& 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 <typename SIZE>
-void print_process_summary_with_name_and_indent(const Globals& globals, const Machine<SIZE>& machine, AbsInterval summary_interval, const CPUSummary<SIZE>& master_summary, const ProcessSummary<SIZE>& 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 <typename SIZE>
-void print_thread_summary_with_name_and_indent(const Globals& globals, const Machine<SIZE>& machine, AbsInterval summary_interval, const CPUSummary<SIZE>& master_summary, const ThreadSummary<SIZE>& 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 <typename SIZE>
-static void sort_processes(const Globals& globals, const CPUSummary<SIZE>& summary, std::vector<const MachineProcess<SIZE>*>& processes) {
- switch (globals.sort_key()) {
- case kSortKey::CPU:
- // Sort by Actual CPU, Future CPU, pid
- std::sort(processes.begin(), processes.end(), [&summary](const MachineProcess<SIZE>* p0, const MachineProcess<SIZE>* 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<SIZE>* p0, const MachineProcess<SIZE>* 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<SIZE>* p0, const MachineProcess<SIZE>* 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<SIZE>* p0, const MachineProcess<SIZE>* 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<SIZE>* p0, const MachineProcess<SIZE>* 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<SIZE>* p0, const MachineProcess<SIZE>* p1) -> bool {
- return p0->pid() < p1->pid();
- });
- break;
- }
-}
-
-template <typename SIZE>
-static void sort_threads(const Globals& globals, const ProcessSummary<SIZE>& summary, std::vector<const MachineThread<SIZE>*>& threads) {
- switch (globals.sort_key()) {
- case kSortKey::CPU:
- std::sort(threads.begin(), threads.end(), [&summary](const MachineThread<SIZE>* t0, const MachineThread<SIZE>* 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<SIZE>* t0, const MachineThread<SIZE>* 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<SIZE>* t0, const MachineThread<SIZE>* 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<SIZE>* t0, const MachineThread<SIZE>* 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<SIZE>* t0, const MachineThread<SIZE>* 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<SIZE>* t0, const MachineThread<SIZE>* t1) -> bool {
- return t0->tid() < t1->tid();
- });
- break;
- }
-}
-
-template <typename SIZE>
-void print_machine_summary(const Globals& globals, const Machine<SIZE>& 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<SIZE> 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<CPUSummary<SIZE>> 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<const MachineCPU<SIZE>*> sorted_cpus;
-
- for (auto& cpu : summary.cpus()) {
- sorted_cpus.emplace_back(cpu);
- }
-
- std::sort(sorted_cpus.begin(), sorted_cpus.end(), [](MachineCPU<SIZE> const* cpu0, MachineCPU<SIZE> 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<const MachineProcess<SIZE>*> 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<SIZE>* 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<SIZE>* 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<const MachineThread<SIZE>*> 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<SIZE>* 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<SIZE>* per_cpu_process_summary = cpu_summary.process_summary(process)) {
- if (const ThreadSummary<SIZE>* 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 <typename SIZE>
-void print_machine_csv_summary_header(const Globals& globals,
- const Machine<SIZE>& machine,
- std::vector<const MachineCPU<SIZE>*>& all_cpus,
- std::vector<const MachineProcess<SIZE>*>& all_processes,
- std::unordered_map<const MachineProcess<SIZE>*, std::vector<const MachineThread<SIZE>*>>& 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 <typename SIZE>
-void print_machine_csv_summary_actual_cpu_ms_line(const Globals& globals,
- const Machine<SIZE>& machine,
- AbsInterval summary_interval,
- std::vector<const MachineCPU<SIZE>*>& all_cpus,
- std::vector<const MachineProcess<SIZE>*>& all_processes,
- std::unordered_map<const MachineProcess<SIZE>*, std::vector<const MachineThread<SIZE>*>>& all_threads,
- CPUSummary<SIZE>& master_summary,
- std::vector<CPUSummary<SIZE>>& 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<SIZE>* 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 <typename SIZE>
-void print_machine_csv_summary_wanted_cpu_ms_line(const Globals& globals,
- const Machine<SIZE>& machine,
- AbsInterval summary_interval,
- std::vector<const MachineCPU<SIZE>*>& all_cpus,
- std::vector<const MachineProcess<SIZE>*>& all_processes,
- std::unordered_map<const MachineProcess<SIZE>*, std::vector<const MachineThread<SIZE>*>>& all_threads,
- CPUSummary<SIZE>& master_summary,
- std::vector<CPUSummary<SIZE>>& 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<SIZE>* 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 <typename SIZE>
-void print_machine_csv_summary(const Globals& globals, const Machine<SIZE>& 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<SIZE> start_stop_summary = machine.summary_for_timespan(clipped_start_stop_timespan, NULL);
-
- std::vector<const MachineProcess<SIZE>*> all_processes;
- std::vector<const MachineCPU<SIZE>*> all_cpus;
- std::unordered_map<const MachineProcess<SIZE>*, std::vector<const MachineThread<SIZE>*>> 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<SIZE> const* cpu0, MachineCPU<SIZE> 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<SIZE>* 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<SIZE> summary = machine.summary_for_timespan(summary_interval, NULL);
-
- //
- // Per CPU summaries...
- //
- std::vector<CPUSummary<SIZE>> 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<SIZE> summary = machine.summary_for_timespan(summary_interval, NULL);
-
- //
- // Per CPU summaries...
- //
- std::vector<CPUSummary<SIZE>> 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 <typename SIZE>
-void print_process_start_stop_timestamps(const Globals& globals, const Machine<SIZE>& 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 <typename SIZE>
-void print_verbose_machine_info(const Globals& globals, const Machine<SIZE>& 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
+++ /dev/null
-//
-// TraceFileAction.cpp
-// kdprof
-//
-// Created by James McIlree on 4/15/13.
-// Copyright (c) 2013 Apple. All rights reserved.
-//
-
-#include "global.h"
-
-#if 0
-template <typename SIZE>
-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<SIZE>* header = reinterpret_cast<TraceDataHeader<SIZE>*>(trace_data.address())) {
-
- KDThreadMapEntry<SIZE>* threadmap = NULL;
- uint32_t threadmap_count = 0;
- KDCPUMapEntry* cpumap = NULL;
- uint32_t cpumap_count = 0;
- KDEvent<SIZE>* 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<KDThreadMapEntry<SIZE>*>(trace_data.address() + 4);
-
- // Event data starts immediately following the threadmap
- size_t offset = 4 + threadmap_count * sizeof(KDThreadMapEntry<SIZE>);
- events = reinterpret_cast<KDEvent<SIZE>*>(trace_data.address() + offset);
- } else {
- //
- // RAW_VERSION1
- //
- threadmap_count = header->thread_count();
- threadmap = reinterpret_cast<KDThreadMapEntry<SIZE>*>(trace_data.address() + sizeof(TraceDataHeader<SIZE>));
-
- size_t threadmap_size_in_bytes = threadmap_count * sizeof(KDThreadMapEntry<SIZE>);
- size_t offset_to_event_data = (sizeof(TraceDataHeader<SIZE>) + threadmap_size_in_bytes + 4095) & ~4095;
- size_t offset_to_cpumap_data = sizeof(TraceDataHeader<SIZE>) + 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<kd_cpumap_header*>(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<KDEvent<SIZE>*>(trace_data.address() + offset_to_event_data);
- }
-
- uintptr_t event_count = (uintptr_t)trace_data.size() - (reinterpret_cast<uintptr_t>(events) - reinterpret_cast<uintptr_t>(trace_data.address()));
- if (event_count % sizeof(KDEvent<SIZE>) != 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<SIZE>);
-
- std::vector<KDCPUMapEntry> 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<globals.cpu_count(); ++i) {
- default_cpumap.emplace_back(i, 0, "AP-???");
- }
- uint32_t iop_limit = globals.cpu_count() + globals.iop_count();
- for (uint32_t i=globals.cpu_count(); i<iop_limit; ++i) {
- default_cpumap.emplace_back(i, KDBG_CPUMAP_IS_IOP, "IOP-???");
- }
-
- cpumap = default_cpumap.data();
- cpumap_count = (uint32_t)default_cpumap.size();
- }
-
- // IOP's have been producing .trace files with out of order events.
- // This is a hack fix to work around that. It costs a full copy of the data!
- MemoryBuffer<KDEvent<SIZE>> presorted_events;
- if (globals.should_presort_events() && event_count) {
- presorted_events.set_capacity(event_count);
- memcpy(presorted_events.data(), events, event_count * sizeof(KDEvent<SIZE>));
- events = presorted_events.data();
- std::sort(events, events + event_count, [](KDEvent<SIZE> const& p0, KDEvent<SIZE> const& p1) -> bool {
- return p0.timestamp() < p1.timestamp();
- });
- }
-
- Machine<SIZE> 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<Kernel32>(globals, _path);
- else
- execute_arch_specific<Kernel64>(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<Kernel64>(globals, _path);
- } catch (Exception& e) {
- execute_arch_specific<Kernel32>(globals, _path);
- }
- }
-}
-
-#endif
-
-template <typename SIZE>
-static void execute_arch_specific(Globals& globals, TraceFile& file, std::string& path)
-{
- Machine<SIZE> 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<Kernel32>(globals, file, _path);
- else
- execute_arch_specific<Kernel64>(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<Kernel64>(globals, file, _path);
- } else {
- execute_arch_specific<Kernel32>(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());
- }
- }
- }
-}
-
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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 <CPPUtil/CPPUtil.h>
-
-using namespace util;
-
-#include "KDebug.h"
-
-#include <dispatch/dispatch.h>
-#include <libkern/OSAtomic.h>
-
-#include <vector>
-#include <unordered_map>
-#include <thread>
-
-#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
+++ /dev/null
-.Dd 3/8/14\r
-.Dt kdprof 1\r
-.Os Darwin\r
-.Sh NAME\r
-.Nm kdprof\r
-.Nd kdebug profiler and event printer\r
-.Sh SYNOPSIS\r
-.Nm\r
-.Op Fl h, -help\r
-.Sh DESCRIPTION\r
-The help output for kdprof is more recent than this man page. Please run\r
-.Nm\r
---help\r
-.Sh SEE ALSO\r
-.Xr lsmp 1 ,\r
-.Xr msa 1 ,\r
-.Xr trace 1\r
+++ /dev/null
-//
-// 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<Action> 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<TraceFileAction>(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<std::unique_ptr<Action>> parse_arguments(int argc, const char* argv[], Globals& globals) {
- int i = 1;
- bool cpus_set = false;
- bool iops_set = false;
-
- std::vector<std::unique_ptr<Action>> 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<InitializeAction>(buffers_default));
- } else if ((strcmp(arg, "-r") == 0) || strcasecmp(arg, "--remove") == 0) {
- actions.push_back(std::make_unique<RemoveAction>());
- } else if ((strcmp(arg, "-n") == 0) || strcasecmp(arg, "--no-wrap") == 0) {
- actions.push_back(std::make_unique<NoWrapAction>());
- } else if ((strcmp(arg, "-g") == 0) || strcasecmp(arg, "--print-kdbg-state") == 0) {
- actions.push_back(std::make_unique<PrintStateAction>());
- } else if ((strcmp(arg, "-e") == 0) || strcasecmp(arg, "--enable") == 0) {
- actions.push_back(std::make_unique<EnableAction>());
- } else if ((strcmp(arg, "-d") == 0) || strcasecmp(arg, "--disable") == 0) {
- actions.push_back(std::make_unique<DisableAction>());
- } else if ((strcmp(arg, "-t") == 0) || strcasecmp(arg, "--collect") == 0) {
- actions.push_back(std::make_unique<CollectAction>());
- } 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<SaveTraceAction>(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<SleepAction>(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;
-}
/*
- * 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
* 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,
* 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@
*/
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);
}
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;
}
}
+ 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)
}
return 0;
-
}
/*
- * 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,
* 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
*/
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;
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;
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 */
struct lookup {
lookup_t lk_next;
-
+
uintptr_t lk_thread;
uintptr_t lk_dvp;
long *lk_pathptr;
struct threadmap {
threadmap_t tm_next;
-
+
uintptr_t tm_thread;
uintptr_t tm_pthread;
char tm_command[MAXCOMLEN + 1];
struct threadrun {
threadrun_t tr_next;
-
+
uintptr_t tr_thread;
kd_buf *tr_entry;
uint64_t tr_timestamp;
uintptr_t te_thread;
};
-
#define HASH_SIZE 1024
#define HASH_MASK 1023
#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)
#define EMPTYSTRING ""
-
const char *fault_name[] = {
"",
"ZeroFill",
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);
if (trace_enabled) {
set_enable(0);
}
- /*
+ /*
* This flag is turned off when calling
* quit() due to a set_remove() failure.
*/
}
void
-set_enable(int val)
+set_enable(int val)
{
int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDENABLE, val };
size_t needed;
}
}
-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 };
}
}
-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);
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");
}
}
-void
+static void
write_high_res_latencies(void)
{
int i;
}
}
-void
+static void
sigintr(int signo __attribute__((unused)))
{
write_high_res_latencies();
}
/* exit under normal conditions -- signal handler */
-void
+static void
leave(int signo __attribute__((unused)))
{
write_high_res_latencies();
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;
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;
/*
* Display the current time.
* "ctime" always returns a string that looks like this:
- *
+ *
* Sun Sep 16 01:03:52 1973
* 012345678901234567890123
* 1 2
* 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;
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]);
}
}
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);
}
}
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) {
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) {
} else {
printw(tbuf);
}
-
+
if (s_total_samples) {
average_s_latency = (unsigned int)(s_total_latency/s_total_samples);
} else {
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;
}
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 {
} 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);
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);
}
}
fprintf(fp, "%s", tbuf);
} else {
printw(tbuf);
- }
+ }
if (fp == NULL) {
refresh();
}
}
-int
+static int
exit_usage(void)
{
fprintf(stderr, "Usage: latency [-p <priority>] [-h] [-m] [-st <threshold>] [-it <threshold>]\n");
fprintf(stderr, " [-c <codefile>] [-l <logfile>] [-R <rawfile>] [-n <kernel>]\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[])
{
} else if (strcmp(argv[1], "-it") == 0) {
argc--;
argv++;
-
+
if (argc > 1) {
i_thresh_hold = atoi(argv[1]);
} else {
} else if (strcmp(argv[1], "-c") == 0) {
argc--;
argv++;
-
+
if (argc > 1) {
code_file = argv[1];
} else {
} else if (strcmp(argv[1], "-l") == 0) {
argc--;
argv++;
-
+
if (argc > 1) {
open_logfile(argv[1]);
} else {
}
}
-
-
void
read_command_map(void)
{
}
}
total_threads = header.thread_count;
-
+
sample_TOD_secs = header.TOD_secs;
sample_TOD_usecs = header.TOD_usecs;
} 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
*/
threadmap_hash[hashid] = tme;
}
-void
+static void
delete_thread_entry(uintptr_t thread)
{
threadmap_t tme;
}
}
-void
+static void
find_and_insert_tmp_map_entry(uintptr_t pthread, char *command)
{
threadmap_t tme;
}
}
-void
+static void
create_tmp_map_entry(uintptr_t thread, uintptr_t pthread)
{
threadmap_t tme;
threadmap_temp = tme;
}
-threadmap_t
+static threadmap_t
find_thread_entry(uintptr_t thread)
{
threadmap_t tme;
return 0;
}
-void
+static void
find_thread_name(uintptr_t thread, char **command)
{
threadmap_t tme;
}
}
-void
+static void
add_thread_entry_to_list(thread_entry_t *list, uintptr_t thread)
{
thread_entry_t te;
*list = te;
}
-void
+static void
exec_thread_entry(uintptr_t thread, char *command)
{
threadmap_t tme;
}
}
-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;
thread_delete_list = 0;
}
-void
+static void
gc_reset_entries(void)
{
thread_entry_t te;
thread_reset_list = 0;
}
-void
+static void
reset_thread_names(void)
{
thread_entry_t te;
thread_reset_list = 0;
}
-void
+static void
delete_all_thread_entries(void)
{
threadmap_t tme = 0;
}
}
-
-
-
static void
insert_run_event(uintptr_t thread, int priority, kd_buf *kd, uint64_t now)
{
}
static void
-gc_run_events(void) {
+gc_run_events(void)
+{
thread_entry_t te;
thread_entry_t te_next;
threadrun_t trp;
thread_event_list = 0;
}
-int
+static int
thread_in_user_mode(uintptr_t thread, char *command)
{
event_t evp;
return 1;
}
-
-
static lookup_t
handle_lookup_event(uintptr_t thread, int debugid, kd_buf *kdp)
{
}
static void
-gc_lookup_events(void) {
+gc_lookup_events(void)
+{
thread_entry_t te;
thread_entry_t te_next;
lookup_t lkp;
{
kd_buf *kd, *end_of_sample;
int keep_going = 1;
- int count, i;
+ int i;
+ ssize_t count;
if (!RAW_flag) {
/*
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));
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);
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);
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;
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);
}
}
}
}
-
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;
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;
} 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)
{
}
}
-
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;
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;
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;
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;
case MACH_stkhandoff:
find_thread_name(kd->arg2, &command1);
-
+
if (command1 == EMPTYSTRING) {
command1 = command_buf;
sprintf(command1, "%-8lx", kd->arg2);
}
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;
* 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);
}
}
-
-
-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;
uint64_t start_bias = 0;
uint64_t now;
kd_buf *kd;
- int clen;
+ size_t clen;
char buf2[128];
clen = strlen(buf1);
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) {
gc_lookup_events();
}
-
kd_buf *
log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency)
{
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++) {
if (CPU_NUMBER(kd_start) != cpunum) {
continue;
}
-
+
if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP) {
break;
}
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 {
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;
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 {
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)
{
if (s_thresh_hold && s_latency > s_thresh_hold) {
s_exceeded_threshold++;
-
+
if (log_fp) {
*kd_start = trp->tr_entry;
*priority = trp->tr_priority;
return found_latency;
}
-
double
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) {
return latency;
}
-
-
char *
find_code(int type)
{
return NULL;
}
-
void
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];
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
*/
*/
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");
}
}
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);
binary_search(kern_sym_t *list, int low, int high, uintptr_t addr)
{
int mid;
-
+
if (kern_sym_count == 0) {
return -1;
}
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
* Failed
*/
return -1;
- }
+ }
mid = (low + high) / 2;
if (addr < (uintptr_t)list[mid].k_sym_addr) {
return binary_search(list, mid, high, addr);
}
-
void
open_logfile(const char *path)
{
}
}
-
void
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;
/*
- * 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
* 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,
* 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@
*/
/*-
* 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;
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);
}
#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
(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) {
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;
int rval;
rval = 0;
-
+
if (skip_auth == 0)
{
pam_err = pam_authenticate(pamh, pam_silent);
* Export any environment variables PAM modules may have set
*/
static void
-export_pam_environment()
+export_pam_environment(void)
{
char **pam_env;
char **pp;
#endif /* USE_PAM */
static void
-usage()
+usage(void)
{
#ifdef __APPLE__
(void)fprintf(stderr, "usage: login [-pq] [-h hostname] [username]\n");
* Prompt user and read login name from stdin.
*/
static char *
-getloginname()
+getloginname(void)
{
char *nbuf, *p;
int ch;
#ifdef __APPLE__
#ifndef USE_PAM
void
-checknologin()
+checknologin(void)
{
int fd, nchars;
char tbuf[8192];
#endif /* !USE_PAM */
void
-dolastlog(quiet)
- int quiet;
+dolastlog(int quiet)
{
#ifdef USE_PAM
if (quiet)
static void
badlogin(char *name)
{
-
if (failures == 0)
return;
if (hflag) {
* Shut down PAM
*/
static void
-pam_cleanup()
+pam_cleanup(void)
{
-
if (pamh != NULL) {
if (pam_session_established) {
pam_err = pam_close_session(pamh, 0);
void
bail(int sec, int eval)
{
-
#ifdef USE_PAM
pam_cleanup();
#endif /* USE_PAM */
/*
- * Copyright (c) 2005 Apple Computer, Inc.
- * All rights reserved.
+ * Copyright (c) 2005-2016 Apple Inc. All rights reserved.
*
* @APPLE_BSD_LICENSE_HEADER_START@
*
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");
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) {
}
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;
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");
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");
#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
/*
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
NOTE_EXIT
.It Sy t
NOTE_EXITSTATUS
+.It Sy d
+NOTE_EXIT_DETAIL
.It Sy f
NOTE_FORK
.It Sy e
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.
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
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.
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 ,
/*
- * Copyright (c) 2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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 "<inval>";
+ 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 "<unknown>";
+ snprintf(unkn_fdtype, sizeof(unkn_fdtype), "%i (?)", type);
+ return unkn_fdtype;
}
}
/* 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' : '-',
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;
static void
print_ident(uint64_t ident, int16_t filter, int width)
{
+ if (raw) {
+ printf("%#*llx ", width, ident);
+ return;
+ }
+
switch (filter) {
case EVFILT_SIGNAL:
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)) {
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);
}
break;
}
+ case EVFILT_MACHPORT:
+ case EVFILT_TIMER:
+ /* hex, to match lsmp */
+ printf("%#*llx ", width, ident);
+ break;
+
default:
printf("%*llu ", width, ident);
break;
}
}
+#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
/*
* 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 */
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 = "<UNKN>";
- 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 = "<unkn>";
+ 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);
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));
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 */
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;
/* 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 <pid>]\n", self);
+ fprintf(stderr, "usage: %s [-vher] [-a | -p <pid>]\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;
break;
case 'h':
usage();
+ cheatsheet();
return 0;
+ case 'r':
+ raw = 1;
+ break;
case '?':
default:
usage();
return 1;
}
- printf("command pid kq kqst ident filter fdtype fflags flags evst data");
- if (verbose) {
- printf(" udata ext0 ext1 ext2 ext3 xflags");
- }
- printf("\n");
- printf("---------- ----- ----- ---- -------------------- --------- -------- ------- --------- ---- ------------------");
- if (verbose) {
- printf(" ------------------ ------------------ ------------------ ------------------ ------------------ ----------");
- }
- printf("\n");
+ print_header();
if (all_pids) {
return process_all_pids();
return 0;
}
-
/*
- * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
boolean_t verbose;
int voucher_detail_length;
pid_t pid; /* if user focusing only one pid */
-
};
extern struct prog_configs lsmp_config;
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;
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 */
(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 */
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
/*
- * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <TargetConditionals.h>
#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,
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':
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) {
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));
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) {
}
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) {
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++) {
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);
printf("\n");
print_task_threads_special_ports(taskinfo);
-
} else {
for (i=0; i < taskCount; i++) {
if (psettaskinfo[i].valid != TRUE)
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);
}
/*
- * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <unistd.h>
#include <stdlib.h>
#include <libproc.h>
+#include <assert.h>
#include <mach/mach.h>
#include <mach/mach_voucher.h>
#include "common.h"
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));
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;
}
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;
}
if (context == NULL) {
return;
}
-
+
kern_return_t ret;
ret = mach_port_get_context(taskp, portname, context);
if (ret != KERN_SUCCESS) {
mach_error_string(ret));
return -1;
}
-
+
return 0;
}
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++) {
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);
}
}
}
-
+
ret = vm_deallocate(mach_task_self(), (vm_address_t)members,
membersCnt * sizeof(mach_port_name_t));
if (ret != KERN_SUCCESS) {
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 */
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;
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,
"-",
"-",
(send) ? sendrights : 0);
-
+
/* converting to kobjects is not always supported */
ret = mach_port_kernel_object(taskinfo->task,
taskinfo->table[i].iin_name,
printf(" (%d) %s", _found_task->pid, _found_task->processName);
}
}
-
+
printf("\n");
if (kotype == IKOT_VOUCHER) {
vouchercount++;
}
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;
} else
printf(" 0x00000000 (-) Unknown Process\n");
-
+
}
printf("total = %d\n", taskinfo->tableCount + taskinfo->treeCount - emptycount);
printf("SEND = %d\n", sendcount);
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;
}
/*
- * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <stdio.h>
#include <stdlib.h>
#include <libproc.h>
+#include <assert.h>
#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,
.tree = NULL,
.treeCount = 0,
.valid = FALSE,
+ .k2ntable = {0},
.processName = "Unknown",
.exceptionInfo = {0},
.threadInfos = NULL,
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);
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) {
void get_exc_mask_string(exception_mask_t m, char *out_string, size_t len)
{
out_string[0]='\0';
-
+
if (m & (1<<EXC_BAD_ACCESS))
strncat(out_string, " BAD_ACCESS", len);
if (m & (1<<EXC_BAD_INSTRUCTION))
strncat(out_string," RESOURCE", len);
if (m & (1<<EXC_GUARD))
strncat(out_string," GUARD", len);
-
}
kern_return_t print_task_exception_info(my_per_task_info_t *taskinfo)
get_exc_mask_string(taskinfo->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;
}
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);
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){
return retval;
}
-
-
struct proc_list {
int pid;
int seen;
- char command[32];
+ char name[2 * MAXCOMLEN];
struct ledger *ledger;
struct proc_list *next;
};
struct ledger *ledgers = NULL;
static void
-get_template_info()
+get_template_info(void)
{
void *buf;
* 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))
}
static void
-validate_group()
+validate_group(void)
{
int i;
}
static void
-validate_resource()
+validate_resource(void)
{
int i;
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)
{
l->info = NULL;
l->old_info = NULL;
ledgers = l;
- }
+ }
return (l);
-
}
static void
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;
struct ledger_info li;
struct ledger *ledgerp;
struct proc_list *proc;
- struct kinfo_proc kinfo;
void *arg;
if (pid == 0)
ledgerp = ledger_find(&li);
ledger_update(pid, ledgerp);
ledgerp->seen = 1;
-
+
for (proc = procs; proc; proc = proc->next)
if (proc->pid == pid)
break;
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;
}
static void
-get_all_info()
+get_all_info(void)
{
pid_t *pids;
int sz, cnt, i;
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;
}
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;
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);
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);
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;
plast->next = pnext;
else
procs = pnext;
-
+
free(p);
} else {
p->seen = 0;
free(l->info);
if (l->old_info)
free(l->old_info);
- free(l);
+ free(l);
} else {
l->seen = 0;
free(l->old_info);
const char *pname;
static void
-usage()
+usage(void)
{
printf("%s [-hdL] [-g group] [-p pid] [-r resource] [interval]\n", pname);
}
{
int c;
int interval = 0;
-
+
pname = argv[0];
while ((c = getopt(argc, argv, "g:hdLp:r:")) != -1) {
case 'h':
usage();
exit(0);
-
+
case 'L':
get_template_info();
dump_template_info();
exit(0);
-
+
case 'p':
pid = atoi(optarg);
break;
+++ /dev/null
-.\" 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.
+++ /dev/null
-/*
- * 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 <sys/cdefs.h>
-#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 <sys/types.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-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");
-}
* 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.
*
*/
void usage(void);
-
-void
+void
usage(void)
{
fprintf(stderr, "Usage: mean -[r|s|u] <pid>\n");
exit(0);
}
-int
+int
main(int argc, char **argv)
{
int pid, err, i, ch;
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':
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);
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);
}
}
- 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) {
} else {
printf("Process %d suspended.\n", pid);
}
-
}
-
+
if (do_resume) {
err = task_resume(task);
if (err) {
return 0;
}
-
/*
- * 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,
* 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@
*/
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] [<pages>]\n"
" Allocate memory and wait forever.\n"
" Options include:\n"
- " -l <level> - allocate memory until a low memory notification is received (warn OR critical)\n"
+ " -l <level> - allocate memory until a low memory notification is received (warn OR critical)\n"
" -p <percent-free> - allocate memory until percent free is this (or less)\n"
" -s <seconds> - how long to sleep between checking for a set percent level\n"
" -w <percent-free> - don't allocate, just wait until percent free is this then exit\n"
" -v <print VM stats> - print VM statistics every sampling interval\n"
- " -Q <quiet mode> - reduces the tool's output\n"
+ " -Q <quiet mode> - reduces the tool's output\n"
" -S - simulate the system's memory pressure level without applying any real pressure\n"
" \n"
);
}
static unsigned int
-read_sysctl_int(const char* name)
+read_sysctl_int(const char* name)
{
unsigned int var;
size_t var_size;
}
static int
-get_percent_free(unsigned int* level)
+get_percent_free(unsigned int* level)
{
int error;
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));
}
}
-
static int
reached_or_bypassed_desired_result(void)
{
}
if (tool_mode == TOOL_MODE_FOR_PERCENT) {
-
+
unsigned int current_percent = 0;
get_percent_free(¤t_percent);
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;
p = *(char*) addr;
addr += PAGE_SIZE;
num_pages++;
-
+
}
-
+
//if (num_pages) {
// printf("Referenced %d\n", num_pages);
//}
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) {
if (error == -1) {
perror("Failed to lock memory!");
exit(-1);
- }
+ }
memset(range_current_addr, 0xFF, size);
range_current_addr += size;
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;
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!");
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!");
}
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;
}
get_percent_free(¤t_percent);
-
+
if (print_vm_stats) {
print_vm_stats_on_page_processing = TRUE;
}
} else {
desired_percent = 1;
}
-
+
pages_to_process = (desired_percent * phys_pages) / 100;
page_op = PAGE_OP_ALLOC;
printf(".");
fflush(stdout);
}
-
+
if (print_vm_stats_on_page_processing == TRUE) {
print_vm_statistics();
}
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;
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;
}
} /* 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;
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.
*/
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);
}
}
}
-
+
//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;
}
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;
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 {
break;
case 'v':
print_vm_stats = 1;
- break;
+ break;
case 'Q':
quiet_mode_on = TRUE;
break;
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
*/
#define TEST_LOW_MEMORY_PURGEABLE_TRIGGER_ALL 6
-
+
unsigned int var = 0;
size_t var_size = 0;
int error = 0;
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);
} 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 {
/*
- * 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
* 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,
* 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 <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
-#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 */
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;
case 'K':
case 'k':
multiplier = 1024;
- break;
+ break;
case 'M':
case 'm':
multiplier = 1024 * 1024;
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])) {
}
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;
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");
}
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);
-
}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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 <typename SIZE>
-bool is_mach_msg_interesting(const Machine<SIZE>& machine, const MachineMachMsg<SIZE>* 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<SIZE>* sender_thread = machine.thread(mach_msg->send_tid(), mach_msg->send_time())) {
- const MachineVoucher<SIZE>* sender_voucher = sender_thread->voucher(mach_msg->send_time());
- if (!sender_voucher->is_unset() && !sender_voucher->is_null()) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-template <typename SIZE>
-void reset_task_data_on_exec_or_exit(const MachineProcess<SIZE>& process,
- std::unordered_map<pid_t, bool>& task_appnap_state,
- std::unordered_map<pid_t, TaskRequestedPolicy>& task_requested_state,
- std::unordered_map<pid_t, std::pair<TaskEffectivePolicy, uint32_t>>& task_effective_state,
- std::unordered_map<pid_t, std::pair<uint32_t, uint32_t>>& 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 <typename SIZE>
-void process_events(Globals& globals,
- const Machine<SIZE>& machine,
- std::unordered_map<pid_t, bool>& task_appnap_state,
- std::unordered_map<pid_t, TaskRequestedPolicy>& task_requested_state,
- std::unordered_map<typename SIZE::ptr_t, TaskRequestedPolicy>& thread_requested_state,
- std::unordered_map<pid_t, std::pair<TaskEffectivePolicy, uint32_t>>& task_effective_state,
- std::unordered_map<typename SIZE::ptr_t, std::pair<TaskEffectivePolicy, uint32_t>>& thread_effective_state,
- std::unordered_map<pid_t, std::pair<uint32_t, uint32_t>>& task_boosts)
-{
- const KDEvent<SIZE>* 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<SIZE>& 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>* 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<SIZE>* 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
+++ /dev/null
-//
-// 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 <typename SIZE>
-class EventRingBuffer {
- protected:
- const Globals& _globals; // Used for printing the ringbuffer
- std::vector<KDEvent<SIZE>> _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<KDEvent<SIZE>*, 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 <typename SIZE>
-EventRingBuffer<SIZE>::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<SIZE>));
-}
-
-template <typename SIZE>
-std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> EventRingBuffer<SIZE>::read() {
- std::size_t modulo_index = _tail % _events.size();
- std::size_t count, capacity = _events.size() - modulo_index;
- KDEvent<SIZE>* events = &_events.data()[modulo_index];
-
- if ((count = KDBG::read(events, capacity * sizeof(KDEvent<SIZE>)))) {
- // 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 <typename SIZE>
-void EventRingBuffer<SIZE>::print() const {
- printf("%zu events in buffer [%zu -> %zu)\n", _tail - _head, _head, _tail);
-}
-
-template <typename SIZE>
-void EventRingBuffer<SIZE>::print_event_index(std::size_t index) const {
- const KDEvent<SIZE>& 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 <typename SIZE>
-void EventRingBuffer<SIZE>::print_all_events() const {
- std::size_t begin = _head;
- while (begin < _tail) {
- print_event_index(begin++);
- }
-}
-
-template <typename SIZE>
-void EventRingBuffer<SIZE>::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 <typename SIZE>
-void EventRingBuffer<SIZE>::print_from_timestamp(uint64_t t) const {
- std::size_t begin = _head;
- while (begin < _tail) {
- const KDEvent<SIZE>& 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<Kernel64>* events = (const KDEvent<Kernel64>*)g_rb;
- for (std::size_t i=ring_buffer_head_index; i<ring_buffer_tail_index; i++) {
- const KDEvent<Kernel64>& 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__) */
+++ /dev/null
-//
-// 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);
-}
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// 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<Kernel32>;
-template class EventRingBuffer<Kernel64>;
-
-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 <typename SIZE>
-static void live_trace_event_loop(Globals& globals)
-{
- // Handle ctrl-C
- shouldProcessEvents = true;
- sigintCount = 0;
-
- while (shouldProcessEvents) {
- signal(SIGINT, signal_handler_ctrl_C);
-
- EventRingBuffer<SIZE> 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<SIZE>> machine, last_machine;
-
- std::unordered_map<pid_t, bool> task_appnap_state;
- std::unordered_map<pid_t, TaskRequestedPolicy> task_requested_state;
- std::unordered_map<typename SIZE::ptr_t, TaskRequestedPolicy> thread_requested_state;
- std::unordered_map<pid_t, std::pair<TaskEffectivePolicy, uint32_t>> task_effective_state;
- std::unordered_map<typename SIZE::ptr_t, std::pair<TaskEffectivePolicy, uint32_t>> thread_effective_state;
- std::unordered_map<pid_t, std::pair<uint32_t, uint32_t>> task_boosts;
-
- while (shouldProcessEvents) {
- now = AbsTime::now();
- if (now >= next_trace_update) {
- std::size_t count, capacity;
- KDEvent<SIZE>* events;
-
- std::tie(events, count, capacity) = ring_buffer.read();
- if (count) {
- if (last_machine) {
- machine = std::make_unique<Machine<SIZE>>(*last_machine, events, count);
- } else {
- auto state = KDBG::state();
- auto threadmap = KDBG::threadmap<SIZE>(state);
- auto cpumap = KDBG::cpumap();
- machine = std::make_unique<Machine<SIZE>>(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<Kernel64>(globals);
- } else {
- live_trace_event_loop<Kernel32>(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());
- }
- }
-}
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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;
-}
+++ /dev/null
-//
-// 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 <typename SIZE>
-void print_base(PrintBuffer& buffer,
- const Globals& globals,
- AbsTime timestamp,
- const MachineThread<SIZE>* thread,
- const KDEvent<SIZE>& 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<SIZE>::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<SIZE>& 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 <typename SIZE>
-void print_mach_msg(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- bool is_send,
- const MachineMachMsg<SIZE>* 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<SIZE>* 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<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void print_boost(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void print_impdelv(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void print_generic(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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 <typename SIZE>
-void print_importance_assert(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const char* type,
- std::unordered_map<pid_t, std::pair<uint32_t, uint32_t>>& 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<uint32_t, uint32_t>(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, uint32_t>((uint32_t)event.arg3(), (uint32_t)event.arg4());
- if (must_print || old_importance != new_importance) {
- const MachineThread<SIZE>* event_thread = machine.thread(event.tid(), event.timestamp());
- print_base(buffer, globals, event.timestamp(), event_thread, event, event_index, type, false);
-
- const MachineProcess<SIZE>* 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 <typename SIZE>
-void print_watchport_importance_transfer(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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<SIZE>* 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<SIZE>* 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 <typename SIZE>
-void print_importance_send_failed(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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 <typename SIZE>
-void print_trequested_task(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void print_appnap(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- bool is_appnap_active,
- std::unordered_map<pid_t, bool>& task_appnap_state,
- std::unordered_map<pid_t, TaskRequestedPolicy>& 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 <typename SIZE>
-void print_trequested_task(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- pid_t pid,
- TaskRequestedPolicy task_requested)
-{
-
- ASSERT(pid != -1, "Sanity");
- const char* target_name;
- if (const MachineProcess<SIZE>* 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 <typename SIZE>
-void print_trequested_thread(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const MachineThread<SIZE>* 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 <typename SIZE>
-void print_teffective_task(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- pid_t pid,
- TaskEffectivePolicy task_effective)
-{
- ASSERT(pid != -1, "Sanity");
- const char* target_name;
- if (const MachineProcess<SIZE>* 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 <typename SIZE>
-void print_teffective_thread(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const MachineThread<SIZE>* 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 <typename SIZE>
-void print_importance_apptype(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& 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<SIZE>* 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 <typename SIZE>
-void print_importance_update_task(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const char* type,
- std::unordered_map<pid_t, std::pair<TaskEffectivePolicy, uint32_t>>& 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<TaskEffectivePolicy, uint32_t>(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 <typename SIZE>
-void print_importance_update_thread(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const char* type,
- std::unordered_map<typename SIZE::ptr_t, std::pair<TaskEffectivePolicy, uint32_t>>& thread_effective_state)
-{
- //
- // event args are:
- //
- // targettid, teffective_0(task, thread), teffective_1(task, thread), tpriority(task, thread)
- //
-
- if (const MachineThread<SIZE>* 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<TaskEffectivePolicy, uint32_t>(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 <typename SIZE>
-void print_fork(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const MachineProcess<SIZE>& 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 <typename SIZE>
-void print_exit(PrintBuffer& buffer,
- const Globals& globals,
- const KDEvent<SIZE>& event,
- const MachineThread<SIZE>* 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 <typename SIZE>
-void print_voucher(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const char* type,
- const MachineVoucher<SIZE>* 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 <typename SIZE>
-void print_voucher_contents(PrintBuffer& buffer,
- const Globals& globals,
- const Machine<SIZE>& machine,
- const KDEvent<SIZE>& event,
- uintptr_t event_index,
- const MachineVoucher<SIZE>* 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; offset<recipe->content_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; cursor<data_remaining; cursor++) {
- char* hex_buffer_tmp = &hex_buffer[cursor * 3];
- size_t hex_buffer_tmp_size = sizeof(hex_buffer) - cursor * 3;
- snprintf(hex_buffer_tmp, hex_buffer_tmp_size, "%02x ", data[cursor]);
- }
-
- char ascii_buffer[24];
- for (uint32_t cursor = 0; cursor<data_remaining; cursor++) {
- if (isprint(data[cursor]))
- ascii_buffer[cursor] = data[cursor];
- else
- ascii_buffer[cursor] = '.';
- }
- ascii_buffer[data_remaining] = 0;
-
- buffer.printf("%-48s %-16s\n", hex_buffer, ascii_buffer);
- }
- break;
-
- default:
- print_base_empty(buffer, globals, event_index, "voucher_create", false);
- buffer.printf(" voucher-%u | UNKNOWN key-%u command-%u size-%u\n", voucher->id(), recipe->key, recipe->command, recipe->content_size);
- break;
- }
-
- used_size += sizeof(mach_voucher_attr_recipe_data_t) + recipe->content_size;
- }
-}
-
-#endif /* defined(__msa__MessagePrinting__) */
+++ /dev/null
-//
-// ReadTraceFileAction.cpp
-// msa
-//
-// Created by James McIlree on 4/15/13.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include "global.h"
-
-template <typename SIZE>
-static void execute_arch_specific(Globals& globals, TraceFile& file)
-{
- Machine<SIZE> 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<pid_t, bool> task_appnap_state;
- std::unordered_map<pid_t, TaskRequestedPolicy> task_requested_state;
- std::unordered_map<typename SIZE::ptr_t, TaskRequestedPolicy> thread_requested_state;
- std::unordered_map<pid_t, std::pair<TaskEffectivePolicy, uint32_t>> task_effective_state;
- std::unordered_map<typename SIZE::ptr_t, std::pair<TaskEffectivePolicy, uint32_t>> thread_effective_state;
- std::unordered_map<pid_t, std::pair<uint32_t, uint32_t>> 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<Kernel32>(globals, file);
- else
- execute_arch_specific<Kernel64>(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<Kernel64>(globals, file);
- } else {
- execute_arch_specific<Kernel32>(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());
- }
- }
- }
-}
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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");
- }
- }
-}
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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();
-}
+++ /dev/null
-//
-// 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__) */
+++ /dev/null
-//
-// 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 <CPPUtil/CPPUtil.h>
-
-using namespace util;
-
-#include <KDBG/KDebug.h>
-
-#include <signal.h>
-
-#include <libkern/OSAtomic.h>
-
-#include <vector>
-#include <unordered_map>
-#include <thread>
-#include <tuple>
-
-__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
+++ /dev/null
-//
-// main.cpp
-// msa
-//
-// Created by James McIlree on 1/30/14.
-// Copyright (c) 2014 Apple. All rights reserved.
-//
-
-#include <CPPUtil/CPPUtil.h>
-
-#include "global.h"
-
-bool isVerbose = true;
-bool shouldPrintVersion = true;
-std::vector<std::string> 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 <typename SIZE>
-static bool check_interest_name(const MachineProcess<SIZE>& 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<Action> 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<ReadTraceFileAction>(resolved_path);
- }
- }
- char* errmsg = NULL;
- asprintf(&errmsg, "%s does not exist or is not a file", trace_file_path);
- usage(errmsg);
-}
-
-static std::vector<std::unique_ptr<Action>> parse_arguments(int argc, const char* argv[], Globals& globals) {
- int i = 1;
-
- std::vector<std::unique_ptr<Action>> 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<WriteTraceFileAction>(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<LiveTraceAction>());
- }
-
- 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;
-}
-
+++ /dev/null
-.Dd 3/7/14\r
-.Dt msa 1\r
-.Os Darwin\r
-.Sh NAME\r
-.Nm msa\r
-.Nd Mach spy agency. Shows mach ipc, vouchers, importance boosts, etc.\r
-.Sh SYNOPSIS \" Section Header - required - don't modify\r
-.Nm\r
-.Op Fl ho\r
-.Op Fl -help\r
-.Op Fl -verbose\r
-.Op Fl -version\r
-.Op Fl -lifecycle Ar all | user | none\r
-.Op Fl -mach-msg Ar all | user | voucher | none\r
-.Op Fl -ouput Ar file\r
-.Op Fl -raw-timestamps\r
-.Op Fl -mach-absolute-time\r
-.Op Fl -event-index\r
-.Op Ar\r
-.Sh DESCRIPTION\r
-The\r
-.Nm\r
-command is used to observe voucher and importance propagation.\r
-.Nm\r
-displays mach message senders and receivers, message state (voucher, importance, reply expected, etc.) and receiver behavior such as refusing a voucher.\r
-.Nm\r
-shows process & thread lifecycle events, adoption & clearing of vouchers by threads, process importance count changes, and process DarwinBG state.\r
-.Nm\r
-uses the kernel trace facility and can be run live or against saved trace files.\r
-.Pp\r
-Options are as follows:\r
-.Pp\r
-\r
-.Bl -tag -width -indent\r
-.It Fl h, -help\r
-Print help.\r
-.It Fl -verbose\r
-Print additional details and output.\r
-.It Fl -version\r
-Print version info.\r
-.It Fl -lifecycle Ar all | user | none\r
-Set the process and thread lifecycle filter level. The default is "user".\r
-.Bl -tag -width -indent\r
-.It all\r
-Show kernel & userspace process and thread events\r
-.It user\r
-Show userspace process and thread events\r
-.It none\r
-Show no process and thread events\r
-.El\r
-.It Fl -mach-msg Ar all | user | voucher | none\r
-Set the mach message sender/receiver filter level. The default is "voucher".\r
-.Bl -tag -width -indent\r
-.It all\r
-Show all mach message senders/receivers\r
-.It user\r
-Show mach message senders/receivers where both the sender and receiver are in userspace\r
-.It voucher\r
-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.\r
-.It none\r
-Show no mach message senders/receivers\r
-.El\r
-.It Fl o, -output Ar file\r
-Write output to \r
-.Ar file\r
-.It Fl -raw-timestamps\r
-Do not show time as a delta from the first trace event, print the actual time offsets.\r
-.It Fl -mach-absolute-time\r
-Do not translate time from mach absolute units to nanoseconds.\r
-.It Fl -event-index\r
-Print the index of each event.\r
-.El\r
-.Sh OUTPUT\r
-.Nm\r
-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):\r
-\r
- Time(uS) Type Thread ThreadVoucher Process ;; Message-From/To MsgID MsgVoucher DeliveryTime FLAGS\r
- 9304.56 send 8C2 - coreaudiod (236) ;; -> coreaudiod (236) 2 - - ONEWAY \r
- 9346.52 impdelv 8A6 - coreaudiod (236) ;; linked to coreaudiod (236)'s live importance chain\r
- 9349.02 recv 8A6 - coreaudiod (236) ;; <- coreaudiod (236) 2 5EBD6CB68FF6401F 44.46 \r
- 9361.50 adopt 8A6 5EBD6CB68FF6401F coreaudiod (236) ;;\r
-\r
-.Bl -tag -width -indent\r
-.It The column headers have the following meanings:\r
-.Bl -tag -width -indent\r
-.It Time\r
-The Time column displays the number of microseconds elapsed since\r
-.Nm\r
-started, or since the first event in the trace file. This value may be modified by\r
-.Fl -raw-timestamps\r
-or\r
-.Fl -mach-absolute-time.\r
-You might set these flags in order to correlate timestamps with output from another process that was printing mach_absolute_time() based timestamps.\r
-.It Type\r
-This describes the type of event being reported. Information to the right of the ';;' will vary based on this type.\r
-.It Thread\r
-The Thread column shows the thread id of the thread that generated the event. This is the thread id as displayed by\r
-.Xr trace 1\r
-and\r
-.Xr kdprof 1\r
-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.\r
-.It ThreadVoucher\r
-The ThreadVoucher column shows the id of any voucher currently adopted by the thread. This voucher id is the same identifier as shown by\r
-.Xr lsmp 1 .\r
-A '-' means that\r
-.Nm\r
-has not yet seen a voucher adopt for the thread. A NULL voucher is displayed as '0'.\r
-.It Process\r
-The Process column shows the name and pid of the process executing. The name is limited to 16 characters and may appear truncated.\r
-.El\r
-.It Mach message send/recv have the following additional column headers:\r
-.Bl -tag -width -indent\r
-.It Message-From/To\r
-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\r
-.Nm\r
-was unable to determine the source or destination of the message.\r
-.It MsgID\r
-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.\r
-.It MsgVoucher\r
-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.\r
-.It DeliveryTime\r
-This is the time it took to deliver the message, in uS. If the time cannot be calculated, it will show as '-'.\r
-.It FLAGS\r
-The FLAGS field will indicate various mach message behaviors:\r
-.Bl -tag -width -indent\r
-.It ONEWAY\r
-This message cannot be replied to\r
-.It MSGH_BITS_RAISED_IMPORTANCE\r
-This message carries "old style" importance\r
-.It VOUCHER-REFUSED\r
-The message carried a voucher, and the receiver refused to accept it\r
-.El\r
-.El\r
-.El\r
-.Sh EXAMPLES\r
-.Bl -tag -width -indent\r
-.It Here are several examples of usage:\r
-.Bl -tag -width -indent\r
-.It msa | grep BOOST\r
-This will show live boost/unboost behavior. Useful for watching what UI interactions will cause boosting.\r
-.It msa | grep -e APP-NAME -e DAEMON-NAME -e OTHER-DAEMON-NAME\r
-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.\r
-.It trace -L /tmp/temp.trace; msa /tmp/temp.trace\r
-This uses trace to capture a trace file for later analysis by msa.\r
-.El\r
-.El\r
-.Sh SEE ALSO \r
-.\" List links in ascending order by section, alphabetically within a section.\r
-.\" Please do not reference files that do not exist without filing a bug report\r
-.Xr kdprof 1 ,\r
-.Xr lsmp 1,\r
-.Xr trace 1\r
-.\" .Sh BUGS \" Document known, unremedied bugs\r
-.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file
gid_t egid;
struct group *grp;
char *ep, *pass;
+#ifndef __APPLE__
char **p;
+#endif
char *grp_passwd;
#ifdef __APPLE__
uuid_t user_uuid;
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;
}
/*
- * Copyright (c) 2000-2012 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <CoreFoundation/CoreFoundation.h>
#include <err.h>
#include <mach/mach_error.h>
+#include <sys/stat.h>
// Prototypes
static void UsageMessage(char *message);
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) {
UsageMessage("missing filename");
}
break;
-
+
case 'd':
cnt++;
if (cnt < argc && *argv[cnt] != '-') {
UsageMessage("missing name");
}
break;
-
+
case 'c':
ClearOFVariables();
break;
}
} else {
// Other arguments will be firmware variable requests.
+ argcount++;
SetOrGetOFVariable(str);
}
}
-
+
+ // radar:25206371
+ if (argcount == 0 && gUseForceSync == true) {
+ NVRamSyncNow("");
+ }
+
IOObjectRelease(gOptionsRef);
-
+
return 0;
}
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");
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);
}
kCollectValue,
kContinueValue,
kSetenv,
-
+
kMaxStringSize = 0x800,
kMaxNameSize = 0x100
};
//
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;
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);
name[ni++] = tc;
}
break;
-
+
case kScanComment :
if (tc == '\n') {
state = kFirstColumn;
// state stays kScanComment.
}
break;
-
+
case kFindName :
if (tc == '\n') {
state = kFirstColumn;
name[ni++] = tc;
}
break;
-
+
case kCollectName :
if (tc == '\n') {
name[ni] = 0;
// state staus kCollectName.
}
break;
-
+
case kFindValue :
case kContinueValue :
if (tc == '\n') {
value[vi++] = tc;
}
break;
-
+
case kCollectValue :
if (tc == '\n') {
if (value[vi-1] == '\\') {
}
break;
}
-
+
if (state == kSetenv) {
name[ni] = 0;
value[vi] = 0;
state = kFirstColumn;
}
}
-
+
if (state != kFirstColumn) {
errx(1, "Last line ended abruptly");
}
}
-
// ParseXMLFile(fileName)
//
// Open and parse the specified file in XML format,
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);
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 == '=') {
}
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) {
errx(1, "Error getting variable - '%s': %s", name,
mach_error_string(result));
}
-
+
PrintOFVariable(nameRef, valueRef, 0);
CFRelease(nameRef);
CFRelease(valueRef);
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;
}
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;
}
// DeleteOFVariable(name)
//
// Delete the named firmware variable.
-//
+//
//
static void DeleteOFVariable(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));
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");
}
CFDictionaryApplyFunction(dict, &PrintOFVariable, 0);
}
-
+
CFRelease(dict);
}
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);
warnx("Unable to convert property name to C string");
nameString = "<UNPRINTABLE>";
}
-
+
// Get the OF variable's type.
typeID = CFGetTypeID(value);
-
+
if (typeID == CFBooleanGetTypeID()) {
if (CFBooleanGetValue(value)) valueString = "true";
else valueString = "false";
} else {
valueString="<INVALID>";
}
-
+
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);
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;
valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value,
cnt2, kCFAllocatorDefault);
} else return 0;
-
+
return valueRef;
}
result = IORegistryEntrySetCFProperty(gOptionsRef, key, value);
if ( result != KERN_SUCCESS ) {
- int nameLen;
+ long nameLen;
char *nameBuffer;
char *nameString;
/*
- * 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,
* 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 <ctype.h>
char *tempname = NULL; // temporary master.passwd file
asprintf(&tempname, "%s.XXXXXX", path);
-
+
fd = mkstemp(tempname);
if (fd == -1) {
err(EXIT_FAILURE, "%s", tempname);
errno = save;
err(EXIT_FAILURE, "%s", tempname);
}
-
+
while ((line = fgetln(fp, &len)) != NULL) {
struct passwd *pw = parse_user(line, len);
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);
/*
- * 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
* 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,
* 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.
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 */
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)
(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;
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)
{
/*
- * 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,
* 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 <stdio.h>
}
desc = CFErrorCopyFailureReason(error);
if (desc) cfprintf(stderr, " %@", desc);
-
+
desc = CFErrorCopyRecoverySuggestion(error);
if (desc) cfprintf(stderr, " %@", desc);
-
+
fprintf(stderr, "\n");
}
}
ODRecordRef rec = NULL;
CFStringRef oldpass = NULL;
CFStringRef newpass = NULL;
-
+
if (uname == NULL)
return -1;
CFArrayRef values = NULL;
values = ODRecordCopyValues(rec, kODAttributeTypeMetaNodeLocation, &error);
location = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : location;
-
+
printf("Changing password for %s.\n", uname);
/*
printf("Password unchanged.\n");
exit(0);
}
-
+
p = getpass("Retype new password:");
if (p) {
CFStringRef verify = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
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";
}
/*
- * 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,
* 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 <stdio.h>
/* 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. */
/* 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;
/*
- * 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,
* 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 <TargetConditionals.h>
}
//strcpy(obuf, p);
snprintf( obuf, sizeof(obuf), "%s", p );
-
+
tries = 0;
nbuf[0] = '\0';
for (;;)
* 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)
//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");
char* auth = NULL;
int infosystem, ch;
int free_user = 0;
-
+
#ifdef INFO_PAM
infosystem = INFO_PAM;
#else
* 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:
break;
#endif
}
-
+
if (free_user == 1)
free(user);
-
+
exit(0);
}
-
/*
- * 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
* 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,
* 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@
*/
--- /dev/null
+.\" 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
--- /dev/null
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <libkern/OSByteOrder.h>
+#include <libproc.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+#include <System/sys/proc_uuid_policy.h>
+
+/* 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 <verb> <policy> <uuid>\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;
+}
* @APPLE_LICENSE_HEADER_END@
*/
-#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
+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");
#include <limits.h>
#include "util.h"
+#include "pw_scan.h"
int
pw_scan(char *bp, struct passwd *pw, int *flags)
/*
- * 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
* 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,
* 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 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 */
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)];
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);
/* 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) {
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);
}
void
-mv(from, to)
- char *from, *to;
+mv(char *from, char *to)
{
char buf[MAXPATHLEN * 2];
}
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];
void
usage(void)
{
-
(void)fprintf(stderr,
"usage: pwd_mkdb [-c] [-p | -s] [-d basedir] [-u username] file\n");
exit(1);
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+
#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 */
#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 */
#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 */
}
void
-usage()
+usage(void)
{
#ifndef __APPLE__
(void)fprintf(stderr, "usage: %s [-dnpq] [-k kernel]\n",
}
u_int
-get_pageins()
+get_pageins(void)
{
u_int pageins;
size_t len;
* contact kextd to lock for reboot
*/
int
-reserve_reboot()
+reserve_reboot(void)
{
int rval = ELAST + 1;
kern_return_t macherr = KERN_FAILURE;
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);
}
static void
-usage()
+usage(void)
{
(void)fprintf(stderr,
"usage: sa [-abcdDfijkKlmnqrstu] [-P file] [-U file] [-v cutoff] [file ...]\n");
/* 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");
}
/* 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;
printf(" %s\n", cip->ci_comm);
}
-#endif
\ No newline at end of file
+#endif
/* Copy usrdb_file to in-memory usracct_db. */
int
-usracct_init()
+usracct_init(void)
{
BTREEINFO bti;
}
void
-usracct_destroy()
+usracct_destroy(void)
{
db_destroy(usracct_db, "user accounting");
}
/* Copy in-memory usracct_db to usrdb_file. */
int
-usracct_update()
+usracct_update(void)
{
BTREEINFO bti;
}
void
-usracct_print()
+usracct_print(void)
{
DBT key, data;
struct userinfo uistore, *ui = &uistore;
+++ /dev/null
-.\"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
+++ /dev/null
-#!/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
+++ /dev/null
-.\"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
+++ /dev/null
-#!/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 {} \;
+++ /dev/null
-.\"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
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <time.h>
-#include <err.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <sys/param.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/IOBSD.h>
-
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_var.h>
-#include <ifaddrs.h>
-
-#include <sadc.h>
-
-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;
-}
+++ /dev/null
-/*
- * 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 <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/IOBSD.h>
-
-/* 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;
-};
+++ /dev/null
-.\"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
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <time.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <mach/mach.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-
-#include <sadc.h>
-#include <sar.h>
-
-
-#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<datacount; i++)
- {
- int found;
- char *name;
- int nr_index;
- int n;
-
- name = databuf[i].tname_unit;
- found = 0;
-
- if (!(network_mode & NET_PPP_MODE))
- {
- if (!strncmp(name, "ppp", 3))
- continue; /* skip ppp interfaces */
- }
-
- /* Find the matching entry using the interface name */
- for (j=0; j < nr_count && !found; j++)
- {
- if (nr_table[j].valid)
- {
- if(!strcmp(nr_table[j].tname_unit, name))
- {
- found = 1;
- nr_table[j].present = 1;
- set_cur_netstats(&nr_table[j], &databuf[i]);
- }
- }
- } /* end for */
-
- if (!found) /* this is a new entry */
- {
- /* Find an invalid entry in the table and init it */
- for (j=0; j < nr_count; j++)
- {
- if (!nr_table[j].valid)
- {
- nr_index = j;
- goto NEW_ENTRY;
- }
- }
-
- /* we ran out of entries... grow the table */
- n = nr_count * 2;
- nr_table = (struct netstats_report *)realloc(nr_table, n * sizeof(struct netstats_report));
- bzero(&nr_table[nr_count], nr_count * sizeof (struct netstats_report));
- nr_index = nr_count;
- nr_count = n;
-
- NEW_ENTRY:
- strncpy(nr_table[nr_index].tname_unit, databuf[i].tname_unit, MAX_TNAME_UNIT_SIZE);
- nr_table[nr_index].tname_unit[MAX_TNAME_UNIT_SIZE] = '\0';
- set_cur_netstats(&nr_table[nr_index], &databuf[i]);
- init_prev_netstats(&nr_table[nr_index]);
- }
-
- } /* end for */
-
- /*
- * Traverse the internal table. Any valid entry that wasn't
- * present in this sample is cleared for reuse.
- */
- for (i = 0; i < nr_count; i++)
- {
- if (nr_table[i].valid)
- {
- if (nr_table[i].present == 0)
- bzero(&nr_table[i], sizeof(struct netstats_report));
- }
- }
- return (1);
-}
-
-static void
-print_netstats_sample(char *timebufptr)
-{
- int i;
-
- for (i=0; i < nr_count; i++)
- {
- if (!nr_table[i].valid)
- continue;
-
- /*
- * This is where we attempt to handle counters that
- * might wrap ... the kernel netstats are only 32 bits.
- *
- * Interfaces may go away and then return within the
- * sampling period. This can't be detected and it
- * may look like a counter wrap. An interface generation
- * counter will help... but isn't implemented at this time.
- */
-
- /*
- * The ppp interfaces are very likely to come and go during
- * a sampling period. During the normal life of a ppp interface,
- * it's less likely that the packet counter will wrap, so if
- * it appears to have done so, is probably because the
- * interface unit number has been reused.
- * We reinitialize that interface in that case.
- */
- if (network_mode & NET_PPP_MODE)
- {
- /*
- * ppp interfaces won't even make it into this table
- * when NET_PPP_MODE isn't set
- */
- if (!strncmp(nr_table[i].tname_unit, "ppp", 3))
- {
- /*
- * Both ipackets and opackets have to be less
- * than the previous counter to cause us to reinit.
- */
-
- if ((nr_table[i].cur_ipackets < nr_table[i].prev_ipackets)
- && (nr_table[i].cur_opackets < nr_table[i].prev_opackets))
- {
- init_prev_netstats(&nr_table[i]);
- continue;
- }
- }
- }
-
- nr_table[i].avg_count ++;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_ipackets < nr_table[i].prev_ipackets)
- nr_table[i].cur_ipackets += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_ipackets -= nr_table[i].prev_ipackets;
- nr_table[i].prev_ipackets += nr_table[i].cur_ipackets;
- nr_table[i].avg_ipackets += nr_table[i].cur_ipackets;
-
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_ibytes < nr_table[i].prev_ibytes)
- nr_table[i].cur_ibytes += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_ibytes -= nr_table[i].prev_ibytes;
- nr_table[i].prev_ibytes += nr_table[i].cur_ibytes;
- nr_table[i].avg_ibytes += nr_table[i].cur_ibytes;
-
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_opackets < nr_table[i].prev_opackets)
- nr_table[i].cur_opackets += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_opackets -= nr_table[i].prev_opackets;
- nr_table[i].prev_opackets += nr_table[i].cur_opackets;
- nr_table[i].avg_opackets += nr_table[i].cur_opackets;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_obytes < nr_table[i].prev_obytes)
- nr_table[i].cur_obytes += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_obytes -= nr_table[i].prev_obytes;
- nr_table[i].prev_obytes += nr_table[i].cur_obytes;
- nr_table[i].avg_obytes += nr_table[i].cur_obytes;
-
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_ierrors < nr_table[i].prev_ierrors)
- nr_table[i].cur_ierrors += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_ierrors -= nr_table[i].prev_ierrors;
- nr_table[i].prev_ierrors += nr_table[i].cur_ierrors;
- nr_table[i].avg_ierrors += nr_table[i].cur_ierrors;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_oerrors < nr_table[i].prev_oerrors)
- nr_table[i].cur_oerrors += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_oerrors -= nr_table[i].prev_oerrors;
- nr_table[i].prev_oerrors += nr_table[i].cur_oerrors;
- nr_table[i].avg_oerrors += nr_table[i].cur_oerrors;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_collisions < nr_table[i].prev_collisions)
- nr_table[i].cur_collisions += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_collisions -= nr_table[i].prev_collisions;
- nr_table[i].prev_collisions += nr_table[i].cur_collisions;
- nr_table[i].avg_collisions += nr_table[i].cur_collisions;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_drops < nr_table[i].prev_drops)
- nr_table[i].cur_drops += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_drops -= nr_table[i].prev_drops;
- nr_table[i].prev_drops += nr_table[i].cur_drops;
- nr_table[i].avg_drops += nr_table[i].cur_drops;
-
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_imcasts < nr_table[i].prev_imcasts)
- nr_table[i].cur_imcasts += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_imcasts -= nr_table[i].prev_imcasts;
- nr_table[i].prev_imcasts += nr_table[i].cur_imcasts;
- nr_table[i].avg_imcasts += nr_table[i].cur_imcasts;
-
-#ifdef IFNET_32_BIT_COUNTERS
- while (nr_table[i].cur_omcasts < nr_table[i].prev_omcasts)
- nr_table[i].cur_omcasts += 0x100000000LL;
-#endif /* IFNET_32_BIT_COUNTERS */
- nr_table[i].cur_omcasts -= nr_table[i].prev_omcasts;
- nr_table[i].prev_omcasts += nr_table[i].cur_omcasts;
- nr_table[i].avg_omcasts += nr_table[i].cur_omcasts;
- }
-
-
- if (!(flag_count > 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;
- }
-}
-
+++ /dev/null
-/*
- * 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 <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/IOBSD.h>
-
-#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;
-};
/*
- * 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
* 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,
* 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@
*/
};
struct th_info {
- int thread;
+ uintptr_t thread;
int depth;
int vfslookup;
int curpri;
};
struct sc_entry {
- char name[32];
+ char name[64];
int delta_count;
int total_count;
int waiting;
#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};
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();
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");
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;
}
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");
fprintf(stderr, "Could not re-execute: %d\n", errno);
exit(1);
}
-
+
/* get our name */
if (argc > 0) {
if ((myname = rindex(argv[0], '/')) == 0) {
uid_t uid, euid;
gid_t gid, egid;
-
+
ptr = strrchr(argv[optind], '/');
if (ptr)
ptr++;
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();
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)
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
}
}
-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);
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) {
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]);
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();
sprintf(tbuf, "%-14.14s", proc_name);
clen = strlen(tbuf);
-
+
if (preempted == 1)
p1 = "preemption ";
else
/*
* Display the current time.
* "ctime" always returns a string that looks like this:
- *
+ *
* Sun Sep 16 01:03:52 1973
* 012345678901234567890123
* 1 2
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
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) {
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], ")");
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], ")");
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);
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
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;
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;
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;
delta_otime_usecs = 0;
}
-void
-reset_counters() {
+static void
+reset_counters(void)
+{
int i;
for (i = 0; i < (MAX_SC + msgcode_cnt) ; i++) {
total_faults = 0;
scalls = 0;
called = 0;
-
+
utime_secs = 0;
utime_usecs = 0;
itime_secs = 0;
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;
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]);
rewind(fp);
-
+
for (;;) {
n = fscanf(fp, "%x%55s\n", &code, &name[0]);
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;
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");
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++) {
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)
return 1;
}
-
-void
-sort_scalls() {
+static void
+sort_scalls(void)
+{
int i, n, k, cnt, secs;
struct th_info *ti;
struct sc_entry *se;
called++;
}
-void
-set_enable(int val)
+static void
+set_enable(int val)
{
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
trace_enabled = 0;
}
-void
-set_numbufs(int nbufs)
+static void
+set_numbufs(int nbufs)
{
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
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 */
}
-void
-set_pidcheck(int pid, int on_off)
+static void
+set_pidcheck(int pid, int on_off)
{
kd_regtype kr;
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);
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 */
}
-void
-set_remove()
+static void
+set_remove(void)
{
extern int errno;
}
}
-void
-set_init()
-{ kd_regtype kr;
+static void
+set_init(void)
+{
+ kd_regtype kr;
kr.type = KDBG_RANGETYPE;
kr.value1 = 0;
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 */
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);
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;
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;
switched_in = (struct th_info *)0;
now = kd[i].timestamp & KDBG_TIMESTAMP_MASK;
-
+
baseid = debugid & 0xffff0000;
if (type == vfs_lookup) {
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;
}
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];
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) {
ti->depth--;
if (ti->depth == 0) {
- /*
+ /*
* headed back to user mode
* start the time accumulation
*/
ti->depth--;
if (ti->depth == 0) {
- /*
+ /*
* headed back to user mode
* start the time accumulation
*/
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);
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;
errx(EINVAL, "-%c flag requires a %s", flag, req);
return (ret);
}
-
/*
- * 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
* 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,
* 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 <paths.h>
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
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);
{
char *p, *endp;
struct passwd *pw;
- int arglen, ch, len, readstdin;
+ size_t arglen;
+ int ch, len, readstdin;
#ifndef DEBUG
if (geteuid())
if (!(dohalt || doreboot || dosleep || killflg))
usage("-h, -r, -s, or -k is required");
-
+
if (doups && !dohalt)
usage("-u requires -h");
#endif /* !__APPLE__ */
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) {
}
void
-loop()
+loop(void)
{
struct interval *tp;
u_int sltime;
* 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);
}
};
void
-timewarn(int timeleft)
+timewarn(time_t timeleft)
{
static int first;
static char hostname[MAXHOSTNAMELEN + 1];
(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");
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
} else {
int howto = 0;
-#if defined(__APPLE__)
+#if defined(__APPLE__)
{
struct utmpx utx;
bzero(&utx, sizeof(utx));
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.");
}
}
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);
#define NOMSG "\n\nNO LOGINS: System going down at "
void
-nolog()
+nolog(void)
{
int logfd;
char *ct;
}
void
-badtime()
+badtime(void)
{
errx(1, "bad time format");
}
* header
* subject
* return
- */
-int audit_shutdown(int exitstatus)
+ */
+int
+audit_shutdown(int exitstatus)
{
int aufd;
token_t *tok;
if((aufd = au_open()) == -1) {
fprintf(stderr, "shutdown: Audit Error: au_open() failed\n");
- exit(1);
+ exit(1);
}
/* The subject that performed the operation */
* contact kextd to lock for reboot
*/
int
-reserve_reboot()
+reserve_reboot(void)
{
int rval = ELAST + 1;
kern_return_t macherr = KERN_FAILURE;
return rval;
}
#endif /* __APPLE__ */
-
#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 */
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);
}
}
#endif
-
+
return (0);
}
return (1);
}
#endif
-
+
switch (ctltype) {
case CTLTYPE_STRING:
if (!nflag)
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" */;
C9D64CD21B91066B00CFA43B /* CopyFiles */,
);
dependencies = (
+ C21481471C1A1447003BCA63 /* PBXTargetDependency */,
+ 78DE9DED1B5048D400FE6DF5 /* PBXTargetDependency */,
97999D351AE84D3A00E8B10F /* PBXTargetDependency */,
08DC48921A12C6FA008AAF38 /* PBXTargetDependency */,
- 18597F1A18CBC3B000531A50 /* PBXTargetDependency */,
- 1865518B18CA7151003B92A7 /* PBXTargetDependency */,
550C19F11804D2B7001DA380 /* PBXTargetDependency */,
ADA9007E1767A31300161ADF /* PBXTargetDependency */,
C625B29116D6F38700168EF7 /* PBXTargetDependency */,
BA9BF4B7139682710018C7BB /* PBXTargetDependency */,
BA91CE6A137F43A500AE5160 /* PBXTargetDependency */,
BAE58A54137D69FB0049DD3B /* PBXTargetDependency */,
- BAE58A42137A59300049DD3B /* PBXTargetDependency */,
BAE58A2E1379A1260049DD3B /* PBXTargetDependency */,
- BAE58A301379A1260049DD3B /* PBXTargetDependency */,
BAE589FE137905740049DD3B /* PBXTargetDependency */,
BAE58A00137905740049DD3B /* PBXTargetDependency */,
BAE58A02137905740049DD3B /* PBXTargetDependency */,
BACC1D681377B8DC007728F4 /* PBXTargetDependency */,
BACC1D6A1377B8DC007728F4 /* PBXTargetDependency */,
BACC1D6C1377B8DC007728F4 /* PBXTargetDependency */,
- BACC1D3C1377B5D9007728F4 /* PBXTargetDependency */,
BACC1D001377B3A4007728F4 /* PBXTargetDependency */,
BA4B7A981376600200003422 /* PBXTargetDependency */,
BA4B7A7C13765DC600003422 /* PBXTargetDependency */,
BA4B7A0C1373BA8D00003422 /* PBXTargetDependency */,
BA4B79F81373B06B00003422 /* PBXTargetDependency */,
BA4B79DB1373A9CE00003422 /* PBXTargetDependency */,
- BA4B79DD1373A9CE00003422 /* PBXTargetDependency */,
BA9B76A81373A2CF001BB39F /* PBXTargetDependency */,
BA9B76AA1373A2CF001BB39F /* PBXTargetDependency */,
BA9B76AC1373A2CF001BB39F /* PBXTargetDependency */,
BA4FD3121373001C0025925C /* PBXTargetDependency */,
BA4FD329137301370025925C /* PBXTargetDependency */,
BA4FD337137306260025925C /* PBXTargetDependency */,
+ 8EC3916E1C973440001E28E6 /* PBXTargetDependency */,
);
name = All_MacOSX;
productName = All_MacOSX;
C9D64CD01B91064700CFA43B /* CopyFiles */,
);
dependencies = (
+ C21481491C1A14AD003BCA63 /* PBXTargetDependency */,
+ 78DE9DFA1B504D1200FE6DF5 /* PBXTargetDependency */,
97999D371AE84D4100E8B10F /* PBXTargetDependency */,
08DC48901A12C6F0008AAF38 /* PBXTargetDependency */,
- 18597F1C18CBC3B900531A50 /* PBXTargetDependency */,
- 186551D018CA8154003B92A7 /* PBXTargetDependency */,
550C19EF1804D2AD001DA380 /* PBXTargetDependency */,
ADA900801767A31900161ADF /* PBXTargetDependency */,
C625B29316D6F39000168EF7 /* PBXTargetDependency */,
BA9BF4BB139682880018C7BB /* PBXTargetDependency */,
BA9BF4BD139682880018C7BB /* PBXTargetDependency */,
BAE58A56137D6A050049DD3B /* PBXTargetDependency */,
- BAE58A44137A59390049DD3B /* PBXTargetDependency */,
BAE58A321379A1300049DD3B /* PBXTargetDependency */,
- BAE58A341379A1300049DD3B /* PBXTargetDependency */,
BAE58A041379057F0049DD3B /* PBXTargetDependency */,
BAE58A061379057F0049DD3B /* PBXTargetDependency */,
BAE58A081379057F0049DD3B /* PBXTargetDependency */,
BACC1D201377B58A007728F4 /* PBXTargetDependency */,
BACC1D221377B58A007728F4 /* PBXTargetDependency */,
BACC1D241377B58A007728F4 /* PBXTargetDependency */,
- BACC1D261377B58A007728F4 /* PBXTargetDependency */,
BACC1D281377B58A007728F4 /* PBXTargetDependency */,
BACC1D2A1377B58A007728F4 /* PBXTargetDependency */,
BACC1D2C1377B58A007728F4 /* PBXTargetDependency */,
BACC1D321377B58A007728F4 /* PBXTargetDependency */,
BACC1D341377B58A007728F4 /* PBXTargetDependency */,
BACC1D361377B58A007728F4 /* PBXTargetDependency */,
- BACC1D381377B58A007728F4 /* PBXTargetDependency */,
BACC1D3A1377B58A007728F4 /* PBXTargetDependency */,
);
name = All_iOS;
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 */; };
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 */; };
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 */; };
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 */; };
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;
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;
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 */;
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 */;
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;
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 */;
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 */;
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 */;
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;
);
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;
};
);
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;
);
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;
};
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;
};
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 = "<group>"; };
1523FE6B1595056C00661E82 /* ltop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ltop.c; sourceTree = "<group>"; };
+ 1821B00B1C88BEE2000BAA0C /* usage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = usage.cpp; sourceTree = "<group>"; };
+ 1821B00C1C88BEE2000BAA0C /* usage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = usage.hpp; sourceTree = "<group>"; };
+ 18380CDC1C596E8900DC6B89 /* eostrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = eostrace.c; sourceTree = "<group>"; };
+ 18410FED1CC881FD00385C96 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = "<group>"; };
1845E41418EB95810010F451 /* TraceFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TraceFile.cpp; sourceTree = "<group>"; };
1845E41518EB95810010F451 /* TraceFile.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TraceFile.hpp; sourceTree = "<group>"; };
- 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 = "<group>"; };
18597ECC18CBC35700531A50 /* Action.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Action.hpp; sourceTree = "<group>"; };
18597ECD18CBC35700531A50 /* CollectAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CollectAction.hpp; sourceTree = "<group>"; };
185B9771191022B200FCB84C /* VoucherContentSysctl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VoucherContentSysctl.cpp; sourceTree = "<group>"; };
185B97731910475500FCB84C /* WriteTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteTraceFileAction.cpp; sourceTree = "<group>"; };
185B97741910475500FCB84C /* WriteTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WriteTraceFileAction.hpp; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 185F75151CC2EFC600B0EA9E /* TypeFilterAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TypeFilterAction.hpp; sourceTree = "<group>"; };
+ 185F75171CC337D400B0EA9E /* Machine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Machine.cpp; sourceTree = "<group>"; };
+ 185F75191CC34EBE00B0EA9E /* WriteTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteTraceFileAction.cpp; sourceTree = "<group>"; };
+ 185F751A1CC34EBE00B0EA9E /* WriteTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WriteTraceFileAction.hpp; sourceTree = "<group>"; };
+ 18624C851BF6400200FA0575 /* TypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TypeSummary.hpp; sourceTree = "<group>"; };
+ 18624C861BF64ED700FA0575 /* CPUTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CPUTypeSummary.hpp; sourceTree = "<group>"; };
+ 18624C871BF6503600FA0575 /* ProcessTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ProcessTypeSummary.hpp; sourceTree = "<group>"; };
+ 18624C881BF651EC00FA0575 /* ThreadTypeSummary.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ThreadTypeSummary.hpp; sourceTree = "<group>"; };
+ 186288CF1CC5DA71002950E0 /* UUIDMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UUIDMap.cpp; sourceTree = "<group>"; };
+ 186288D01CC5DA71002950E0 /* UUIDMap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UUIDMap.hpp; sourceTree = "<group>"; };
1865513A18CA70B5003B92A7 /* CPPUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPPUtil.h; sourceTree = "<group>"; };
1865513B18CA70B5003B92A7 /* UtilAbsInterval.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UtilAbsInterval.cpp; sourceTree = "<group>"; };
1865513C18CA70B5003B92A7 /* UtilAbsInterval.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilAbsInterval.hpp; sourceTree = "<group>"; };
1865515618CA70B5003B92A7 /* UtilTimer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTimer.hpp; sourceTree = "<group>"; };
1865515718CA70B5003B92A7 /* UtilTRange.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTRange.hpp; sourceTree = "<group>"; };
1865515818CA70B5003B92A7 /* UtilTRangeValue.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = UtilTRangeValue.hpp; sourceTree = "<group>"; };
- 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 = "<group>"; };
1865518C18CA72F7003B92A7 /* Action.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Action.hpp; sourceTree = "<group>"; };
1865518E18CA72F7003B92A7 /* EventProcessing.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EventProcessing.hpp; sourceTree = "<group>"; };
1865519818CA72F7003B92A7 /* Printing.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Printing.hpp; sourceTree = "<group>"; };
1865519918CA72F7003B92A7 /* ReadTraceFileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadTraceFileAction.cpp; sourceTree = "<group>"; };
1865519A18CA72F7003B92A7 /* ReadTraceFileAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ReadTraceFileAction.hpp; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 1873F1211CC551DD008950A8 /* DeviceMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceMap.cpp; sourceTree = "<group>"; };
+ 1873F1221CC551DD008950A8 /* DeviceMap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DeviceMap.hpp; sourceTree = "<group>"; };
+ 1873F1261CC587E2008950A8 /* BinaryDataTraceDecoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = BinaryDataTraceDecoder.hpp; sourceTree = "<group>"; };
+ 1875DF421C443513004AC849 /* KDState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KDState.cpp; sourceTree = "<group>"; };
1888DB65191A8A4400A0541E /* PrintBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PrintBuffer.hpp; sourceTree = "<group>"; };
188959FC1958D287004576E8 /* TaskRequestedPolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TaskRequestedPolicy.hpp; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 189632961C5FD38E00FA9646 /* eostrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eostrace.h; sourceTree = "<group>"; };
+ 18C65BAD1CC1868D005194F4 /* TypeFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeFilter.cpp; sourceTree = "<group>"; };
+ 18C65BAE1CC1868D005194F4 /* TypeFilter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TypeFilter.hpp; sourceTree = "<group>"; };
18C8728718EA128B00F86DD9 /* CPUActivity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CPUActivity.hpp; sourceTree = "<group>"; };
18C8728818EA128B00F86DD9 /* CPUSummary.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CPUSummary.hpp; sourceTree = "<group>"; };
18C8728918EA128B00F86DD9 /* IOActivity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOActivity.hpp; sourceTree = "<group>"; };
18C872A718EA128B00F86DD9 /* TraceDataHeader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TraceDataHeader.hpp; sourceTree = "<group>"; };
18C872A818EA128B00F86DD9 /* VoucherInterval.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VoucherInterval.hpp; sourceTree = "<group>"; };
18D0E13119101CD200F93974 /* VoucherContentSysctl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VoucherContentSysctl.hpp; sourceTree = "<group>"; };
+ 18D6F9AF1C5A8EF000F472A7 /* eostraced.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eostraced.c; sourceTree = "<group>"; };
+ 18D6F9B11C5A8EFB00F472A7 /* com.apple.eostraced.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.eostraced.plist; sourceTree = "<group>"; };
18D8B66519535B92008847DF /* TaskEffectivePolicy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TaskEffectivePolicy.hpp; sourceTree = "<group>"; };
+ 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 = "<group>"; };
550C19E11804C55E001DA380 /* iosim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iosim.c; sourceTree = "<group>"; };
550C19EB1804D226001DA380 /* iosim */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = iosim; sourceTree = BUILT_PRODUCTS_DIR; };
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 = "<group>"; };
+ 78DE9DFD1B504D7F00FE6DF5 /* wait4path.version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wait4path.version; path = wait4path/wait4path.version; sourceTree = "<group>"; };
+ 78DE9EE51B505EBF00FE6DF5 /* wait4path.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = wait4path.1; path = wait4path/wait4path.1; sourceTree = "<group>"; };
+ 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 = "<group>"; };
97999D301AE84C7600E8B10F /* lskq.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; name = lskq.1; path = lskq.tproj/lskq.1; sourceTree = "<group>"; };
97999D311AE84C7600E8B10F /* lskq.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = lskq.c; path = lskq.tproj/lskq.c; sourceTree = "<group>"; };
- A624DA851AF6F3CF00F56A5C /* CoreSymbolication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSymbolication.framework; path = ../../../../System/Library/PrivateFrameworks/CoreSymbolication.framework; sourceTree = "<group>"; };
- A6738D021AF6FF9F001EF064 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../System/Library/Frameworks/IOKit.framework; sourceTree = "<group>"; };
- A6738D041AF6FFB5001EF064 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = ../../../../System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<group>"; };
+ 9FAAF8741C158C0B00E6856D /* ThreadRequestedPolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ThreadRequestedPolicy.hpp; sourceTree = "<group>"; };
+ 9FAAF8761C158C2300E6856D /* ThreadEffectivePolicy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ThreadEffectivePolicy.hpp; sourceTree = "<group>"; };
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 = "<group>"; };
ADA9007A1767A02700161ADF /* purge.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = purge.c; sourceTree = "<group>"; };
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 = "<absolute>"; };
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 = "<absolute>"; };
BA4B79FA1373B7C300003422 /* com.apple.dynamic_pager.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = com.apple.dynamic_pager.plist; sourceTree = BUILT_PRODUCTS_DIR; };
BA4FD2171372FAFA0025925C /* util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = "<group>"; };
BA4FD2201372FAFA0025925C /* dmesg.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dmesg.8; sourceTree = "<group>"; };
BA4FD2211372FAFA0025925C /* dmesg.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dmesg.c; sourceTree = "<group>"; };
- BA4FD2281372FAFA0025925C /* backing_store_alerts.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = backing_store_alerts.defs; sourceTree = "<group>"; };
- BA4FD2291372FAFA0025925C /* backing_store_triggers.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = backing_store_triggers.defs; sourceTree = "<group>"; };
BA4FD22A1372FAFA0025925C /* com.apple.dynamic_pager.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.dynamic_pager.plist; sourceTree = "<group>"; };
- BA4FD22B1372FAFA0025925C /* default_pager_alerts.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = default_pager_alerts.defs; sourceTree = "<group>"; };
BA4FD22C1372FAFA0025925C /* dynamic_pager.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dynamic_pager.8; sourceTree = "<group>"; };
BA4FD22D1372FAFA0025925C /* dynamic_pager.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dynamic_pager.c; sourceTree = "<group>"; };
BA4FD2301372FAFA0025925C /* fs_usage.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = fs_usage.1; sourceTree = "<group>"; };
BA4FD2611372FAFA0025925C /* login */ = {isa = PBXFileReference; lastKnownFileType = text; path = login; sourceTree = "<group>"; };
BA4FD2621372FAFA0025925C /* login.term */ = {isa = PBXFileReference; lastKnownFileType = text; path = login.term; sourceTree = "<group>"; };
BA4FD2631372FAFA0025925C /* pathnames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pathnames.h; sourceTree = "<group>"; };
- BA4FD2671372FAFA0025925C /* makekey.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = makekey.8; sourceTree = "<group>"; };
- BA4FD2681372FAFA0025925C /* makekey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = makekey.c; sourceTree = "<group>"; };
BA4FD26B1372FAFA0025925C /* mean.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mean.c; sourceTree = "<group>"; };
BA4FD26E1372FAFA0025925C /* mkfile.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = mkfile.8; sourceTree = "<group>"; };
BA4FD26F1372FAFA0025925C /* mkfile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mkfile.c; sourceTree = "<group>"; };
BA4FD29B1372FAFA0025925C /* pdb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pdb.c; sourceTree = "<group>"; };
BA4FD29C1372FAFA0025925C /* sa.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa.8; sourceTree = "<group>"; };
BA4FD29D1372FAFA0025925C /* usrdb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = usrdb.c; sourceTree = "<group>"; };
- BA4FD2A01372FAFA0025925C /* sa1.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa1.8; sourceTree = "<group>"; };
- BA4FD2A11372FAFA0025925C /* sa1.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sa1.sh; sourceTree = "<group>"; };
- BA4FD2A21372FAFA0025925C /* sa2.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sa2.8; sourceTree = "<group>"; };
- BA4FD2A31372FAFA0025925C /* sa2.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sa2.sh; sourceTree = "<group>"; };
- BA4FD2A41372FAFA0025925C /* sadc.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sadc.8; sourceTree = "<group>"; };
- BA4FD2A51372FAFA0025925C /* sadc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sadc.c; sourceTree = "<group>"; };
- BA4FD2A61372FAFA0025925C /* sadc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sadc.h; sourceTree = "<group>"; };
- BA4FD2A91372FAFA0025925C /* sar.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sar.1; sourceTree = "<group>"; };
- BA4FD2AA1372FAFA0025925C /* sar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sar.c; sourceTree = "<group>"; };
- BA4FD2AB1372FAFA0025925C /* sar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sar.h; sourceTree = "<group>"; };
BA4FD2AE1372FAFA0025925C /* sc_usage.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sc_usage.1; sourceTree = "<group>"; };
BA4FD2AF1372FAFA0025925C /* sc_usage.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sc_usage.c; sourceTree = "<group>"; };
BA4FD2B21372FAFA0025925C /* kextmanager.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = kextmanager.defs; sourceTree = "<group>"; };
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; };
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 = "<group>"; };
+ C214810E1C1A11E6003BCA63 /* corefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = corefile.h; path = gcore.tproj/corefile.h; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 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 = "<group>"; };
+ C21481111C1A11E6003BCA63 /* dyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dyld.c; path = gcore.tproj/dyld.c; sourceTree = "<group>"; };
+ C21481121C1A11E6003BCA63 /* dyld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dyld.h; path = gcore.tproj/dyld.h; sourceTree = "<group>"; };
+ C21481131C1A11E6003BCA63 /* gcore.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = gcore.1; path = gcore.tproj/gcore.1; sourceTree = "<group>"; };
+ C21481141C1A11E6003BCA63 /* loader_additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = loader_additions.h; path = gcore.tproj/loader_additions.h; sourceTree = "<group>"; };
+ C21481151C1A11E6003BCA63 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = gcore.tproj/main.c; sourceTree = "<group>"; };
+ C21481161C1A11E6003BCA63 /* options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = options.h; path = gcore.tproj/options.h; sourceTree = "<group>"; };
+ C21481171C1A11E6003BCA63 /* region.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = region.h; path = gcore.tproj/region.h; sourceTree = "<group>"; };
+ C21481181C1A11E6003BCA63 /* sparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sparse.c; path = gcore.tproj/sparse.c; sourceTree = "<group>"; };
+ C21481191C1A11E6003BCA63 /* sparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sparse.h; path = gcore.tproj/sparse.h; sourceTree = "<group>"; };
+ C214811A1C1A11E7003BCA63 /* threads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = threads.c; path = gcore.tproj/threads.c; sourceTree = "<group>"; };
+ C214811B1C1A11E7003BCA63 /* threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = threads.h; path = gcore.tproj/threads.h; sourceTree = "<group>"; };
+ C214811C1C1A11E7003BCA63 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utils.c; path = gcore.tproj/utils.c; sourceTree = "<group>"; };
+ C214811D1C1A11E7003BCA63 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = gcore.tproj/utils.h; sourceTree = "<group>"; };
+ C214811E1C1A11E7003BCA63 /* vanilla.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vanilla.c; path = gcore.tproj/vanilla.c; sourceTree = "<group>"; };
+ C214811F1C1A11E7003BCA63 /* vanilla.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vanilla.h; path = gcore.tproj/vanilla.h; sourceTree = "<group>"; };
+ C21481201C1A11E7003BCA63 /* vm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vm.c; path = gcore.tproj/vm.c; sourceTree = "<group>"; };
+ C21481211C1A11E7003BCA63 /* vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vm.h; path = gcore.tproj/vm.h; sourceTree = "<group>"; };
+ C248DBAF1C1A1D0500F6E9AF /* libcompression.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcompression.dylib; path = /usr/lib/libcompression.dylib; sourceTree = "<absolute>"; };
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 = "<group>"; };
C625B28C16D6F27E00168EF7 /* taskpolicy.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = taskpolicy.8; sourceTree = "<group>"; };
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 = "<group>"; };
+ 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 = "<group>"; };
/* End PBXFileReference section */
);
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;
};
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;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
- BA4B79D21373A97000003422 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
BA4B79E41373AF7A00003422 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ C97199F21C5206DE006D9758 /* libktrace.dylib in Frameworks */,
BA4B7A0A1373BA4600003422 /* libutil.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
);
runOnlyForDeploymentPostprocessing = 0;
};
- BACC1D041377B3E6007728F4 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
BACC1D101377B481007728F4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
);
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;
};
path = ltop.tproj;
sourceTree = "<group>";
};
+ 18380CDB1C596E8900DC6B89 /* eostrace */ = {
+ isa = PBXGroup;
+ children = (
+ 189632961C5FD38E00FA9646 /* eostrace.h */,
+ 18380CDC1C596E8900DC6B89 /* eostrace.c */,
+ 18EA07131C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.h */,
+ 18EA07121C99E4E3006D3005 /* copy_of_AppleEmbeddedOSSupport.c */,
+ );
+ path = eostrace;
+ sourceTree = "<group>";
+ };
18597EC518CBC2A300531A50 /* kdprof */ = {
isa = PBXGroup;
children = (
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;
1865513E18CA70B5003B92A7 /* UtilAbsTime.hpp */,
1865513F18CA70B5003B92A7 /* UtilAssert.hpp */,
1865514018CA70B5003B92A7 /* UtilBase.hpp */,
+ 189337C41CC7DA8700B2A6A4 /* UtilCoreSymbolication.hpp */,
1865514118CA70B5003B92A7 /* UtilException.hpp */,
1865514218CA70B5003B92A7 /* UtilFileDescriptor.hpp */,
1865514318CA70B5003B92A7 /* UtilLog.cpp */,
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 = "<group>";
};
+ 189337C11CC7CB4800B2A6A4 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 189337C21CC7CB4800B2A6A4 /* CoreFoundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
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 */,
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 = "<group>";
};
+ 18D6F9A91C5A8EDB00F472A7 /* eostraced */ = {
+ isa = PBXGroup;
+ children = (
+ 18D6F9AF1C5A8EF000F472A7 /* eostraced.c */,
+ 18D6F9B11C5A8EFB00F472A7 /* com.apple.eostraced.plist */,
+ );
+ path = eostraced;
+ sourceTree = "<group>";
+ };
550C19DF1804C55E001DA380 /* iosim.tproj */ = {
isa = PBXGroup;
children = (
path = vm_purgeable_stat.tproj;
sourceTree = "<group>";
};
+ 78DE9DFB1B504D3300FE6DF5 /* wait4path */ = {
+ isa = PBXGroup;
+ children = (
+ 78DE9EE51B505EBF00FE6DF5 /* wait4path.1 */,
+ 78DE9DFC1B504D7F00FE6DF5 /* wait4path.c */,
+ 78DE9DFD1B504D7F00FE6DF5 /* wait4path.version */,
+ );
+ name = wait4path;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
97999D2E1AE84C5700E8B10F /* lskq.tproj */ = {
isa = PBXGroup;
children = (
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 */,
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 = "<group>";
};
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 */,
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 */,
path = pam.d;
sourceTree = "<group>";
};
- BA4FD2651372FAFA0025925C /* makekey.tproj */ = {
- isa = PBXGroup;
- children = (
- BA4FD2671372FAFA0025925C /* makekey.8 */,
- BA4FD2681372FAFA0025925C /* makekey.c */,
- );
- path = makekey.tproj;
- sourceTree = "<group>";
- };
BA4FD2691372FAFA0025925C /* mean.tproj */ = {
isa = PBXGroup;
children = (
path = sa.tproj;
sourceTree = "<group>";
};
- 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 = "<group>";
- };
- BA4FD2A71372FAFA0025925C /* sar.tproj */ = {
- isa = PBXGroup;
- children = (
- BA4FD2A91372FAFA0025925C /* sar.1 */,
- BA4FD2AA1372FAFA0025925C /* sar.c */,
- BA4FD2AB1372FAFA0025925C /* sar.h */,
- );
- path = sar.tproj;
- sourceTree = "<group>";
- };
BA4FD2AC1372FAFA0025925C /* sc_usage.tproj */ = {
isa = PBXGroup;
children = (
BA9B766313739C20001BB39F /* chkpasswd */,
BA9B768C1373A0D8001BB39F /* chpass */,
BA4B79CD1373A72800003422 /* dmesg */,
- BA4B79D51373A97000003422 /* libdp_notify_lib.a */,
BA4B79EC1373AF7A00003422 /* dynamic_pager */,
BA4B7A051373B9E900003422 /* fs_usage */,
BA4B7A161373BE9D00003422 /* getconf */,
BA4B7A7113765D3E00003422 /* iostat */,
BA4B7A9013765F3C00003422 /* latency */,
BA473DB31377B2230005CC19 /* login */,
- BACC1D091377B3E6007728F4 /* makekey */,
BACC1D151377B481007728F4 /* mean */,
BACC1D451377B6E2007728F4 /* mkfile */,
BACC1D551377B7A7007728F4 /* newgrp */,
BAE589E3137902F50049DD3B /* pwd_mkdb */,
BAE589F01379044E0049DD3B /* reboot */,
BAE58A1113799F610049DD3B /* sa */,
- BAE58A2513799FFA0049DD3B /* sadc */,
- BAE58A3D1379A3F60049DD3B /* sar */,
BAE58A4E137D69A60049DD3B /* sc_usage */,
BA91CE62137F42ED00AE5160 /* shutdown */,
BA9BF492139680CF0018C7BB /* sync */,
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 = "<group>";
};
+ 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 = "<group>";
+ };
C625B28916D6F27E00168EF7 /* taskpolicy.tproj */ = {
isa = PBXGroup;
children = (
/* 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;
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 = (
);
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" */;
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" */;
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 */ = {
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;
};
};
};
targets = (
BA4FD2FE1372FE4E0025925C /* All_MacOSX */,
BACC1D181377B4C9007728F4 /* All_iOS */,
+ 1812F18C1C8F923900F3DC9E /* All_Bridge */,
BA4FD2EE1372FB3D0025925C /* ac */,
BA4FD3041372FFD80025925C /* accton */,
BA4FD31A137300ED0025925C /* arch */,
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;
);
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;
);
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 */ = {
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = ". ${SRCROOT}/getty.tproj/generate_plist.sh";
+ shellScript = ". \"${SRCROOT}/getty.tproj/generate_plist.sh\"";
};
BA4FD335137306050025925C /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
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;
);
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;
};
);
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;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
- BACC1D021377B3E6007728F4 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- BACC1D0B1377B413007728F4 /* makekey.c in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
BACC1D0E1377B481007728F4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
);
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;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
};
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;
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",
};
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 = {
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;
};
};
name = Debug;
};
- 18732FFD18CBD4A700275344 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INSTALL_PATH = /usr/libexec;
- PRODUCT_NAME = makekey;
- };
- name = Debug;
- };
18732FFE18CBD4A700275344 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
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 = {
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",
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 = {
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",
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",
};
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 = {
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;
};
};
name = Release;
};
- BACC1D081377B3E6007728F4 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INSTALL_PATH = /usr/libexec;
- PRODUCT_NAME = makekey;
- };
- name = Release;
- };
BACC1D141377B481007728F4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
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;
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;
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 = (
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 = (
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;
</BuildActionEntries>
</BuildAction>
<TestAction
+ buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Release">
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
+ <AdditionalOptions>
+ </AdditionalOptions>
</TestAction>
<LaunchAction
+ buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
- allowLocationSimulation = "YES"
- showNonLocalizedStrings = "NO">
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "BA4FD2FE1372FE4E0025925C"
+ BuildableName = "All_MacOSX"
+ BlueprintName = "All_MacOSX"
+ ReferencedContainer = "container:system_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
+ buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
revealArchiveInOrganizer = "YES">
</ArchiveAction>
<InstallAction
- buildConfiguration = "Release">
+ buildConfiguration = "Release"
+ includeDebugSupportFiles = "YES">
</InstallAction>
</Scheme>
</BuildActionEntries>
</BuildAction>
<TestAction
+ buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Release">
+ shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
+ <AdditionalOptions>
+ </AdditionalOptions>
</TestAction>
<LaunchAction
+ buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
- allowLocationSimulation = "YES"
- showNonLocalizedStrings = "NO">
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "BACC1D181377B4C9007728F4"
+ BuildableName = "All_iOS"
+ BlueprintName = "All_iOS"
+ ReferencedContainer = "container:system_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
+ buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
revealArchiveInOrganizer = "YES">
</ArchiveAction>
<InstallAction
- buildConfiguration = "Release">
+ buildConfiguration = "Release"
+ includeDebugSupportFiles = "YES">
</InstallAction>
</Scheme>
Run the program after calling\r
.Xr setiopolicy_np 3\r
with an iotype of IOPOL_TYPE_DISK, a scope of IOPOL_SCOPE_DARWIN_BG, and the\r
-specified policy. The argument is interpreted in the same manor as\r
+specified policy. The argument is interpreted in the same manner as\r
.Fl d .\r
.It Fl c Ar clamp\r
Run the program using the specified QoS clamp. The argument can be either\r
.It Fl l \r
Set latency tier of the process to \r
.Ar latency_tier .\r
-\r
-\r
.El\r
.Pp\r
.Sh SEE ALSO \r
/*
- * Copyright (c) 2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2013-2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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':
warnx("Incompatible option(s) used with -p");
usage();
}
-
+
if (flagx && flagX){
warnx("Incompatible options -x, -X");
usage();
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;
}
{
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")) {
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')) {
}
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")) {
.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 ##
.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
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 <sys/param.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
-
int nbufs = 0;
int enable_flag=0;
int execute_flag=0;
#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
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
#define US_TO_SLEEP 50000
#define BASE_EVENTS 500000
-
+mach_timebase_info_data_t mach_timebase;
double divisor;
typedef struct {
struct lookup {
lookup_t lk_next;
-
+
uintptr_t lk_thread;
uintptr_t lk_dvp;
long *lk_pathptr;
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
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 *);
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);
}
}
-void set_remove()
+void set_remove(void)
{
extern int errno;
-
+
errno = 0;
-
+
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDREMOVE;
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;
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;
void set_pidcheck(int pid, int on_off_flag)
{
kd_regtype kr;
-
+
kr.type = KDBG_TYPENONE;
kr.value1 = pid;
kr.value2 = 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;
}
}
-void set_freerun()
+void set_freerun(void)
{
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
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);
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;
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;
quit_args("trace facility failure, KERN_KDSETUP: %s\n", strerror(errno));
}
-
static void
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;
{
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;
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;
}
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;
}
if (evp) {
elapsed = now - evp->ev_timestamp;
-
+
evp->ev_next = event_freelist;
event_freelist = evp;
}
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);
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);
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);
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;
}
}
-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;
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);
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);
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;
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;
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");
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)
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,
" 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);
if ( !lkp || !(debugid & DBG_FUNC_END))
continue;
}
+
x = (double)now;
x /= divisor;
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) {
}
} 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;
/*
* print the tail end of the pathname
*/
- len = strlen(strptr);
+ len = (int)strlen(strptr);
if (len > 51)
len -= 51;
else
-void signal_handler(int sig)
+void signal_handler(int sig)
{
ptrace(PT_KILL, pid, (caddr_t)0, 0);
/*
}
-
-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++) {
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);
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)
set_remove();
exit(0);
}
-
+
if (bufset_flag )
{
if (!init_flag && !LogRAW_flag)
}
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' ? "<unknown>" : execname);
+
+ /* get kdebug info */
+
get_bufinfo(&bufinfo);
printf("The kernel buffer settings are:\n");
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
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)
usage(SHORT_HELP);
}
setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE);
-
+
if (fcntl(output_fd, F_NOCACHE, 1) < 0)
{
/* Not fatal */
}
static void
-quit_args(const char *fmt, ...)
+quit_args(const char *fmt, ...)
{
char buffer[1024];
printf("trace: ");
if (s)
- printf("%s ", s);
+ printf("%s", s);
exit(1);
}
(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,
(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");
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;
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;
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:
*
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))
*/
static void
-parse_filter_file(char *filename) {
+parse_filter_file(char *filename)
+{
FILE* file;
uint32_t current_line = 0;
uint32_t parsed_arg = 0;
while( fgets(line, sizeof(line), file) != NULL ) {
current_line++;
-
+
switch (line[0]) {
case 'C':
rval = sscanf(line, "C 0x%x\n", &parsed_arg);
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;
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)
* 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);
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;
}
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'))
}
/* 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)
}
}
-
-int match_debugid(unsigned int xx, char * debugstr, int * yy)
+int
+match_debugid(unsigned int xx, char * debugstr, int * yy)
{
int indx;
* cpumap size is one page.
*/
cpumap_header = malloc(PAGE_SIZE);
-
+
if (readRAW_flag) {
/*
* cpu maps exist in a RAW_VERSION1+ header only
}
} 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) {
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");
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;
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;
}
}
-
-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;
}
}
-
-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;
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;
*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;
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;
/*
- * 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,
* 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) 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
* 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,
* 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@
*/
/*-
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;
}
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.
}
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;
}
int
-pw_mkdb()
+pw_mkdb(void)
{
int pstat;
pid_t pid;
}
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())) {
}
void
-pw_prompt()
+pw_prompt(void)
{
int c;
}
void
-pw_error(name, err, eval)
- char *name;
- int err, eval;
+pw_error(char *name, int err, int eval)
{
if (err)
warn("%s", name);
/*
- * 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
* 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,
* 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) 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
* 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,
* 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@
*/
/*
void usage __P((void));
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
int pfd, tfd;
struct stat begin, end;
default:
usage();
}
-
+
argc -= optind;
argv += optind;
}
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)
}
void
-usage()
+usage(void)
{
-
(void)fprintf(stderr, "usage: vipw\n");
exit(1);
}
+/*
+ * 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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
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));
int main(int argc, char *argv[])
{
-
+
char ch;
int pid;
int sleep_duration;
case '?':
case 'h':
default:
- printf("%s", USAGE);
+ printf("%s", USAGE);
}
break;
}
printf("%s", USAGE);
return 0;
}
-
-
/*
- * 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
* 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,
* 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@
*/
/*
*
* 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
************************************************************************
*/
int
main(int argc, char *argv[])
{
-
double delay = 0.0;
int count = 0;
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);
--- /dev/null
+."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.
--- /dev/null
+/*
+ * 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/event.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int
+main(int argc, char *argv[])
+{
+ int kq = kqueue();
+ struct kevent kev;
+ struct stat sb;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <object on mount point>\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);
+}
--- /dev/null
+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."
/*
- * 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,
* 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@
*/
--- /dev/null
+#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
+#include "<DEVELOPER_DIR>/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.
+//
+// <rdar://problem/11075809>
+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
--- /dev/null
+// 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
+// <rdar://problem/16129315>
+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
--- /dev/null
+// 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.
+//
+// <rdar://problem/15995721>
+// <rdar://problem/16477165>
+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))
--- /dev/null
+#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
--- /dev/null
+#!/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`:<objects>
+#
+# <objects> 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.
+#
+# <rdar://problem/15459303>
+#/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"
static const char elsieid[] = "@(#)zdump.c 7.31";
#ifndef lint
-static const char rcsid[] =
+#include <sys/cdefs.h>
+__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 */
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;
continue;
#endif
{
- register int from;
- register int to;
+ int from;
+ int to;
for (i = 0; environ[i] != NULL; ++i)
continue;
}
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;
*/
static long
-delta(newp, oldp)
-struct tm * newp;
-struct tm * oldp;
+delta(struct tm *newp, struct tm *oldp)
{
long result;
int tmy;
}
static void
-show(zone, t, v)
-char * zone;
-time_t t;
-int v;
+show(char *zone, time_t t, int v)
{
struct tm * tmp;
}
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)
#!/bin/sh
+set -e
+set -x
# we need to know where the data files are...
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
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
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"
# 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
+#include <sys/cdefs.h>
#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 */
#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)
}
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);
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
/*
** 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));
#ifndef lint
#ifndef NOID
-static const char elsieid[] = "@(#)scheck.c 8.15";
+#include <sys/cdefs.h>
+__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 */
#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)
static const char elsieid[] = "@(#)zic.c 7.116";
+#include <sys/cdefs.h>
#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 */
*/
static char *
-memcheck(ptr)
-char * const ptr;
+memcheck(char * const ptr)
{
if (ptr == NULL)
errx(EXIT_FAILURE, _("memory exhausted"));
#if !(HAVE_STRERROR - 0)
static char *
-strerror(errnum)
-int errnum;
+strerror(int errnum)
{
extern char * sys_errlist[];
extern int sys_nerr;
#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;
}
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
}
static void
-warning(string)
-const char * const string;
+warning(const char * const string)
{
char * cp;
| 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));
}
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);
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);
}
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, "/.");
*/
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);
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,
}
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");
*/
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;
}
static void
-inrule(fields, nfields)
-register char ** const fields;
-const int nfields;
+inrule(char ** const fields, const int nfields)
{
static struct rule r;
}
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) {
}
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"));
}
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;
}
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"));
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;
}
static void
-inlink(fields, nfields)
-register char ** const fields;
-const int nfields;
+inlink(char ** const fields, const int nfields)
{
struct link l;
}
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"));
}
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];
}
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];
}
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)
}
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);
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) {
}
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)) {
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;
}
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"));
}
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"));
static void
adjleap P((void))
{
- register int i;
- register long last = 0;
+ int i;
+ long last = 0;
/*
** propagate leap seconds forward
}
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;
}
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')
}
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;
}
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;
}
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;
}
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)) {
}
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;
*/
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;
--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);
}
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);
}
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;
}
static long
-eitol(i)
-const int i;
+eitol(const int i)
{
long l;
#include <pwd.h>
static void
-setgroup(flag, name)
- gid_t *flag;
- const char *name;
+setgroup(gid_t *flag, const char *name)
{
struct group *gr;
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);
}
static void
-setuser(flag, name)
- uid_t *flag;
- const char *name;
+setuser(uid_t *flag, const char *name)
{
struct passwd *pw;
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);
-.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 <pid>\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 <pid>
-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 ,
/*
- * 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
* 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,
* 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.
*/
* to zones but not currently in use.
*/
-
-
#include <vm_statistics.h>
#include <stdio.h>
#include <stdlib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreSymbolication/CoreSymbolication.h>
-
-
-
#define streql(a, b) (strcmp((a), (b)) == 0)
#define strneql(a, b, n) (strncmp((a), (b), (n)) == 0)
#define PRINTK(fmt, value) \
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-p <pid>] [name]\n", program);
+ fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-l] [-L] [-p <pid>] [name]\n", program);
exit(1);
}
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);
}
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;
{
int i;
+ if (alen > blen) return FALSE;
+
for (i = 0; i <= blen - alen; i++)
if (strneql(a, b+i, alen))
return TRUE;
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;
}
return (result);
}
-static char *
+static char *
kern_vm_counter_name(uint64_t tag)
{
char * result;
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;
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);
return (result);
}
-static int
+static int
SortName(const void * left, const void * right)
{
const int * idxL;
return (result);
}
-static int
+static int
SortSize(const void * left, const void * right)
{
const mach_memory_info_t * siteL;
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);
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;
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);
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;
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);