X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/1a7e3f61d38d679bba59130891c2031b5a0092b6..bd6521f0fc816ab056bc71376f9706a69b3b52c1:/KDBG/MachineProcess.mutable-impl.hpp?ds=sidebyside diff --git a/KDBG/MachineProcess.mutable-impl.hpp b/KDBG/MachineProcess.mutable-impl.hpp new file mode 100644 index 0000000..caf2b6f --- /dev/null +++ b/KDBG/MachineProcess.mutable-impl.hpp @@ -0,0 +1,163 @@ +// +// MachineProcess.mutable-impl.hpp +// KDBG +// +// Created by James McIlree on 10/30/12. +// Copyright (c) 2014 Apple. All rights reserved. +// + +#include "KDebug.h" + +template +void MachineProcess::set_exit_by_syscall(AbsTime timestamp, int32_t exit_status) { + ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); + ASSERT(_exit_initiated_timestamp == 0, "Sanity"); + ASSERT(!is_kernel(), "Kernel process is attempting to exit"); + + _exit_status = exit_status; + _exit_initiated_timestamp = timestamp; + + set_flags(kMachineProcessFlag::IsExitBySyscall); +} + +template +void MachineProcess::set_exit_by_jetsam(AbsTime timestamp) { + ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); + ASSERT(_exit_initiated_timestamp == 0, "Sanity"); + ASSERT(!is_kernel(), "Kernel process is attempting to exit"); + + _exit_initiated_timestamp = timestamp; + + set_flags(kMachineProcessFlag::IsExitByJetsam); +} + +template +void MachineProcess::set_exit_by_exec(AbsTime timestamp) { + ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); + ASSERT(_exit_initiated_timestamp == 0, "Sanity"); + ASSERT(!is_kernel(), "Kernel process is attempting to exit"); + + _exit_initiated_timestamp = timestamp; + set_flags(kMachineProcessFlag::IsExitByExec); + + for (MachineThread* thread : _threads_by_time) { + if (!thread->is_trace_terminated()) { + thread->set_trace_terminated(timestamp); + } + } + + set_trace_terminated(timestamp); +} + +template +void MachineProcess::set_trace_terminated(AbsTime timestamp){ + ASSERT(is_exiting(), "Attempting to set trace terminated without precursor exit event"); + ASSERT(!is_kernel(), "Kernel process is attempting to set trace terminated"); + + DEBUG_ONLY({ + for (MachineThread* thread : _threads_by_time) { + ASSERT(thread->is_trace_terminated(), "Setting process as trace terminated when it still has live threads"); + } + }) + + _timespan.set_max(timestamp + AbsTime(1)); + set_flags(kMachineProcessFlag::IsTraceTerminated); +} + +template +void MachineProcess::set_apptype(uint32_t type) { + ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); + ASSERT(_apptype == -1 || _apptype == type, "Attempt to set apptype more than once, or to change an inherited apptype"); + ASSERT(!is_kernel(), "Kernel is attempting to set apptype"); + ASSERT(!is_exiting(), "Setting apptype after exit"); + + _apptype = type; +} + +template +void MachineProcess::set_apptype_from_trequested(uint32_t type) { + ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); + ASSERT(_apptype == -1 || _apptype == type, "trequested apptype does not match set apptype"); + + _apptype = type; +} + +template +void MachineProcess::set_name(const char* name) { + ASSERT(name, "Sanity"); + ASSERT(strlen(name) < sizeof(_name) - 1, "Sanity"); + + strlcpy(_name, name, sizeof(_name)); +} + +template +void MachineProcess::clear_fork_exec_in_progress() { + ASSERT(!is_unknown(), "Sanity"); + ASSERT(!is_kernel(), "Sanity"); + ASSERT(!is_exiting(), "Sanity"); + ASSERT(!is_exec_in_progress(), "Sanity"); + ASSERT(is_fork_exec_in_progress(), "Sanity"); + + clear_flags(kMachineProcessFlag::IsForkExecInProgress); +} + +template +void MachineProcess::clear_exec_in_progress() { + ASSERT(!is_unknown(), "Sanity"); + ASSERT(!is_kernel(), "Sanity"); + ASSERT(!is_exiting(), "Sanity"); + ASSERT(!is_fork_exec_in_progress(), "Sanity"); + ASSERT(is_exec_in_progress(), "Sanity"); + + clear_flags(kMachineProcessFlag::IsExecInProgress); +} + +template +void MachineProcess::add_thread(MachineThread* thread) { + ASSERT(thread, "Sanity"); + ASSERT(&thread->process() == this, "Sanity"); + ASSERT(!thread->is_trace_terminated(), "Attempt to add thread that is already terminated"); + ASSERT(thread->timespan().location() >= _timespan.location(), "Attempt to add thread that started before this process"); + ASSERT(!is_exiting(), "Adding thread to process that has exited"); + + // 6/20/2014, reworking time handling, is this still true? + // + // Process/thread created by a previous machine state will violate these + // rules, during initialization. However, only threads created in that + // form will be so tagged, and so we can exclude them from this assert. + // + // ASSERT(!is_exited() || thread->is_created_by_previous_machine_state(), "Adding thread to process that has marked itself as exited"); + + DEBUG_ONLY({ + // At this point, the threads vector is not sorted. + // We have to look at everything :-(. + for (MachineThread* process_thread : _threads_by_time) { + if (process_thread->tid() == thread->tid()) { + ASSERT(!process_thread->timespan().intersects(thread->timespan()), "Overlapping duplicate threads"); + } + } + }) + + _threads_by_time.push_back(thread); +} + +template +void MachineProcess::post_initialize(AbsTime last_machine_timestamp) { + // + // For processes that are still alive at the post_initialize phase, + // we want to extend their timespan(s) to the end of the machine state, + // so they can be looked up by pid/name. + // + if (!is_trace_terminated()) { + ASSERT(_timespan.length() == 0, "Should not have timespan set"); + + // Time in a range is always half open. [ 10, 11 ) means 10 is included, + // but 11 is not. In order to include a given timestamp, we must use + // a value one greater. + AbsTime half_open_timestamp = last_machine_timestamp + AbsTime(1); + + _timespan.set_max(half_open_timestamp); + } + + std::sort(_threads_by_time.begin(), _threads_by_time.end(), thread_by_time_sort); +}