|  | // Copyright 2018 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/developer/debug/ipc/records.h" | 
|  |  | 
|  | #include <lib/syslog/cpp/macros.h> | 
|  | #include <zircon/syscalls/object.h> | 
|  |  | 
|  | #include <algorithm> | 
|  |  | 
|  | namespace debug_ipc { | 
|  |  | 
|  | bool IsDebug(ExceptionType type) { | 
|  | switch (type) { | 
|  | // There's an argument to be had about whether these belong here. | 
|  | case ExceptionType::kThreadStarting: | 
|  | case ExceptionType::kThreadExiting: | 
|  | case ExceptionType::kProcessStarting: | 
|  |  | 
|  | case ExceptionType::kHardwareBreakpoint: | 
|  | case ExceptionType::kWatchpoint: | 
|  | case ExceptionType::kSingleStep: | 
|  | case ExceptionType::kSoftwareBreakpoint: | 
|  | case ExceptionType::kSynthetic: | 
|  | return true; | 
|  | default: | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | __int128 Register::GetValue() const { | 
|  | __int128 result = 0; | 
|  | if (!data.empty()) | 
|  | memcpy(&result, &data[0], std::min(sizeof(result), data.size())); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | const char* ExceptionTypeToString(ExceptionType type) { | 
|  | switch (type) { | 
|  | case ExceptionType::kNone: | 
|  | return "None"; | 
|  | case ExceptionType::kGeneral: | 
|  | return "General"; | 
|  | case ExceptionType::kPageFault: | 
|  | return "Fatal Page Fault"; | 
|  | case ExceptionType::kUndefinedInstruction: | 
|  | return "Undefined Instruction"; | 
|  | case ExceptionType::kUnalignedAccess: | 
|  | return "Unaligned Access"; | 
|  | case ExceptionType::kPolicyError: | 
|  | return "Policy Error"; | 
|  | case ExceptionType::kThreadStarting: | 
|  | return "Thread Starting"; | 
|  | case ExceptionType::kThreadExiting: | 
|  | return "Thread Exiting"; | 
|  | case ExceptionType::kProcessStarting: | 
|  | return "Process Starting"; | 
|  | case ExceptionType::kHardwareBreakpoint: | 
|  | return "Hardware Breakpoint"; | 
|  | case ExceptionType::kWatchpoint: | 
|  | return "Watchpoint"; | 
|  | case ExceptionType::kSingleStep: | 
|  | return "Single Step"; | 
|  | case ExceptionType::kSoftwareBreakpoint: | 
|  | return "Software Breakpoint"; | 
|  | case ExceptionType::kSynthetic: | 
|  | return "Synthetic"; | 
|  | case ExceptionType::kUnknown: | 
|  | return "Unknown"; | 
|  | case ExceptionType::kLast: | 
|  | return "kLast"; | 
|  | } | 
|  | FX_NOTREACHED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | const char* ExceptionStrategyToString(ExceptionStrategy strategy) { | 
|  | switch (strategy) { | 
|  | case ExceptionStrategy::kNone: | 
|  | return "None"; | 
|  | case ExceptionStrategy::kFirstChance: | 
|  | return "First-Chance"; | 
|  | case ExceptionStrategy::kSecondChance: | 
|  | return "Second-Chance"; | 
|  | case ExceptionStrategy::kLast: | 
|  | return "kLast"; | 
|  | } | 
|  | FX_NOTREACHED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | std::optional<ExceptionStrategy> ToExceptionStrategy(uint32_t raw_value) { | 
|  | switch (raw_value) { | 
|  | case ZX_EXCEPTION_STRATEGY_FIRST_CHANCE: | 
|  | return ExceptionStrategy::kFirstChance; | 
|  | case ZX_EXCEPTION_STRATEGY_SECOND_CHANCE: | 
|  | return ExceptionStrategy::kSecondChance; | 
|  | default: | 
|  | return {}; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::optional<uint32_t> ToRawValue(ExceptionStrategy strategy) { | 
|  | switch (strategy) { | 
|  | case ExceptionStrategy::kNone: | 
|  | case ExceptionStrategy::kLast: | 
|  | return {}; | 
|  | case ExceptionStrategy::kFirstChance: | 
|  | return ZX_EXCEPTION_STRATEGY_FIRST_CHANCE; | 
|  | case ExceptionStrategy::kSecondChance: | 
|  | return ZX_EXCEPTION_STRATEGY_SECOND_CHANCE; | 
|  | }; | 
|  | } | 
|  |  | 
|  | const char* ThreadRecord::StateToString(ThreadRecord::State state) { | 
|  | switch (state) { | 
|  | case ThreadRecord::State::kNew: | 
|  | return "New"; | 
|  | case ThreadRecord::State::kRunning: | 
|  | return "Running"; | 
|  | case ThreadRecord::State::kSuspended: | 
|  | return "Suspended"; | 
|  | case ThreadRecord::State::kBlocked: | 
|  | return "Blocked"; | 
|  | case ThreadRecord::State::kDying: | 
|  | return "Dying"; | 
|  | case ThreadRecord::State::kDead: | 
|  | return "Dead"; | 
|  | case ThreadRecord::State::kCoreDump: | 
|  | return "Core Dump"; | 
|  | case ThreadRecord::State::kLast: | 
|  | break; | 
|  | } | 
|  |  | 
|  | FX_NOTREACHED(); | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | const char* ThreadRecord::BlockedReasonToString(BlockedReason reason) { | 
|  | switch (reason) { | 
|  | case ThreadRecord::BlockedReason::kNotBlocked: | 
|  | return "Not blocked"; | 
|  | case ThreadRecord::BlockedReason::kException: | 
|  | return "Exception"; | 
|  | case ThreadRecord::BlockedReason::kSleeping: | 
|  | return "Sleeping"; | 
|  | case ThreadRecord::BlockedReason::kFutex: | 
|  | return "Futex"; | 
|  | case ThreadRecord::BlockedReason::kPort: | 
|  | return "Port"; | 
|  | case ThreadRecord::BlockedReason::kChannel: | 
|  | return "Channel"; | 
|  | case ThreadRecord::BlockedReason::kWaitOne: | 
|  | return "Wait one"; | 
|  | case ThreadRecord::BlockedReason::kWaitMany: | 
|  | return "Wait many"; | 
|  | case ThreadRecord::BlockedReason::kInterrupt: | 
|  | return "Interrupt"; | 
|  | case ThreadRecord::BlockedReason::kPager: | 
|  | return "Pager"; | 
|  | case ThreadRecord::BlockedReason::kLast: | 
|  | break; | 
|  | } | 
|  |  | 
|  | FX_NOTREACHED(); | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | const char* BreakpointTypeToString(BreakpointType type) { | 
|  | switch (type) { | 
|  | case BreakpointType::kSoftware: | 
|  | return "Software"; | 
|  | case BreakpointType::kHardware: | 
|  | return "Hardware"; | 
|  | case BreakpointType::kReadWrite: | 
|  | return "ReadWrite"; | 
|  | case BreakpointType::kWrite: | 
|  | return "Write"; | 
|  | case BreakpointType::kLast: | 
|  | return "Last"; | 
|  | } | 
|  |  | 
|  | FX_NOTREACHED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | bool IsWatchpointType(debug_ipc::BreakpointType type) { | 
|  | // clang-format off | 
|  | return type == BreakpointType::kReadWrite || | 
|  | type == BreakpointType::kWrite; | 
|  | // clang-format on | 
|  | } | 
|  |  | 
|  | const char* ConfigAction::TypeToString(Type type) { | 
|  | switch (type) { | 
|  | case Type::kQuitOnExit: | 
|  | return "Quit On Exit"; | 
|  | case Type::kLast: | 
|  | return "Last"; | 
|  | } | 
|  |  | 
|  | FX_NOTREACHED(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | }  // namespace debug_ipc |