| // Copyright 2020 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/lib/fidl_codec/printer.h" | |
| #include <fuchsia/io/cpp/fidl.h> | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <sys/stat.h> | |
| #include <zircon/syscalls/exception.h> | |
| #include <zircon/syscalls/iommu.h> | |
| #include <zircon/syscalls/object.h> | |
| #include <zircon/syscalls/policy.h> | |
| #include <zircon/syscalls/port.h> | |
| #include <zircon/syscalls/profile.h> | |
| #include <zircon/syscalls/system.h> | |
| #include "src/lib/fidl_codec/display_handle.h" | |
| #include "src/lib/fidl_codec/status.h" | |
| #include "src/lib/fidl_codec/syscall_prop_stubs.h" | |
| namespace fidl_codec { | |
| constexpr int kCharactersPerByte = 2; | |
| const Colors WithoutColors("", "", "", "", "", ""); | |
| const Colors WithColors(/*new_reset=*/"\u001b[0m", /*new_red=*/"\u001b[31m", | |
| /*new_green=*/"\u001b[32m", /*new_blue=*/"\u001b[34m", | |
| /*new_white_on_magenta=*/"\u001b[45m\u001b[37m", | |
| /*new_yellow_background=*/"\u001b[103m"); | |
| PrettyPrinter::PrettyPrinter(std::ostream& os, const Colors& colors, bool pretty_print, | |
| std::string_view line_header, int max_line_size, | |
| bool header_on_every_line, int tabulations) | |
| : os_(os), | |
| colors_(colors), | |
| pretty_print_(pretty_print), | |
| line_header_(line_header), | |
| max_line_size_(max_line_size), | |
| header_on_every_line_(header_on_every_line), | |
| tabulations_(tabulations), | |
| remaining_size_(max_line_size - tabulations * kTabSize) { | |
| // Computes the displayed size of the header. The header can contain escape sequences (to add some | |
| // colors) which don't count as displayed characters. Here we count the number of characters in | |
| // the line header skiping everything between escape ('\u001b') and 'm'. | |
| size_t i = 0; | |
| while (i < line_header.size()) { | |
| if (line_header[i] == '\u001b') { | |
| i = line_header.find_first_of('m', i + 1); | |
| if (i == std::string_view::npos) { | |
| break; | |
| } | |
| ++i; | |
| } else { | |
| ++i; | |
| ++line_header_size_; | |
| } | |
| } | |
| } | |
| void PrettyPrinter::DisplayHandle(const zx_handle_disposition_t& handle) { | |
| fidl_codec::DisplayHandle(handle, *this); | |
| } | |
| #define BtiPermCase(name) \ | |
| if ((perm & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayBtiPerm(uint32_t perm) { | |
| if (perm == 0) { | |
| *this << Red << "0" << ResetColor; | |
| return; | |
| } | |
| *this << Blue; | |
| const char* separator = ""; | |
| BtiPermCase(ZX_BTI_PERM_READ); | |
| BtiPermCase(ZX_BTI_PERM_WRITE); | |
| BtiPermCase(ZX_BTI_PERM_EXECUTE); | |
| BtiPermCase(ZX_BTI_COMPRESS); | |
| BtiPermCase(ZX_BTI_CONTIGUOUS); | |
| *this << ResetColor; | |
| } | |
| #define CachePolicyCase(name) \ | |
| case name: \ | |
| *this << Blue << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayCachePolicy(uint32_t cache_policy) { | |
| switch (cache_policy) { | |
| CachePolicyCase(ZX_CACHE_POLICY_CACHED); | |
| CachePolicyCase(ZX_CACHE_POLICY_UNCACHED); | |
| CachePolicyCase(ZX_CACHE_POLICY_UNCACHED_DEVICE); | |
| CachePolicyCase(ZX_CACHE_POLICY_WRITE_COMBINING); | |
| default: | |
| *this << Red << cache_policy << ResetColor; | |
| return; | |
| } | |
| } | |
| #define ChannelOptionCase(name) \ | |
| if ((options & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayChannelOption(uint32_t options) { | |
| if (options == 0) { | |
| *this << Blue << "0" << ResetColor; | |
| return; | |
| } | |
| *this << Blue; | |
| const char* separator = ""; | |
| ChannelOptionCase(ZX_CHANNEL_READ_MAY_DISCARD); | |
| ChannelOptionCase(ZX_CHANNEL_WRITE_USE_IOVEC); | |
| *this << ResetColor; | |
| } | |
| #define ClockCase(name) \ | |
| case name: \ | |
| *this << Blue << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayClock(zx_clock_t clock) { | |
| switch (clock) { | |
| ClockCase(ZX_CLOCK_MONOTONIC); | |
| default: | |
| *this << Red << clock << ResetColor; | |
| return; | |
| } | |
| } | |
| void PrettyPrinter::DisplayDuration(zx_duration_t duration_ns) { | |
| if (duration_ns == ZX_TIME_INFINITE) { | |
| *this << Blue << "ZX_TIME_INFINITE" << ResetColor; | |
| return; | |
| } | |
| if (duration_ns == ZX_TIME_INFINITE_PAST) { | |
| *this << Blue << "ZX_TIME_INFINITE_PAST" << ResetColor; | |
| return; | |
| } | |
| *this << Blue; | |
| if (duration_ns < 0) { | |
| *this << '-'; | |
| duration_ns = -duration_ns; | |
| } | |
| const char* separator = ""; | |
| int64_t nanoseconds = duration_ns % kOneBillion; | |
| int64_t seconds = duration_ns / kOneBillion; | |
| if (seconds != 0) { | |
| int64_t minutes = seconds / kSecondsPerMinute; | |
| if (minutes != 0) { | |
| int64_t hours = minutes / kMinutesPerHour; | |
| if (hours != 0) { | |
| int64_t days = hours / kHoursPerDay; | |
| if (days != 0) { | |
| *this << days << " days"; | |
| separator = ", "; | |
| } | |
| *this << separator << (hours % kHoursPerDay) << " hours"; | |
| separator = ", "; | |
| } | |
| *this << separator << (minutes % kMinutesPerHour) << " minutes"; | |
| separator = ", "; | |
| } | |
| *this << separator << (seconds % kSecondsPerMinute) << " seconds"; | |
| if (nanoseconds != 0) { | |
| *this << " and " << nanoseconds << " nano seconds"; | |
| } | |
| } else if (nanoseconds != 0) { | |
| *this << nanoseconds << " nano seconds"; | |
| } else { | |
| *this << "0 seconds"; | |
| } | |
| *this << ResetColor; | |
| } | |
| #define ExceptionChannelTypeCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| break | |
| void PrettyPrinter::DisplayExceptionChannelType(uint32_t type) { | |
| *this << Blue; | |
| switch (type) { | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_NONE); | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER); | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_THREAD); | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_PROCESS); | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_JOB); | |
| ExceptionChannelTypeCase(ZX_EXCEPTION_CHANNEL_TYPE_JOB_DEBUGGER); | |
| default: | |
| *this << static_cast<uint32_t>(type); | |
| break; | |
| } | |
| *this << ResetColor; | |
| } | |
| #define ExceptionStateCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| break | |
| void PrettyPrinter::DisplayExceptionState(uint32_t state) { | |
| *this << Blue; | |
| switch (state) { | |
| ExceptionStateCase(ZX_EXCEPTION_STATE_TRY_NEXT); | |
| ExceptionStateCase(ZX_EXCEPTION_STATE_HANDLED); | |
| default: | |
| *this << static_cast<uint32_t>(state); | |
| break; | |
| } | |
| *this << ResetColor; | |
| } | |
| #define FeatureKindCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| break | |
| void PrettyPrinter::DisplayFeatureKind(uint32_t kind) { | |
| *this << Red; | |
| switch (kind) { | |
| FeatureKindCase(ZX_FEATURE_KIND_CPU); | |
| FeatureKindCase(ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT); | |
| FeatureKindCase(ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT); | |
| FeatureKindCase(ZX_FEATURE_KIND_ADDRESS_TAGGING); | |
| FeatureKindCase(ZX_FEATURE_KIND_VM); | |
| FeatureKindCase(ZX_FEATURE_KIND_CPU_SVE); | |
| default: | |
| *this << static_cast<uint32_t>(kind); | |
| break; | |
| } | |
| *this << ResetColor; | |
| } | |
| #define GuestTrapCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| break | |
| void PrettyPrinter::DisplayGuestTrap(uint32_t trap_id) { | |
| *this << Red; | |
| switch (trap_id) { | |
| GuestTrapCase(ZX_GUEST_TRAP_BELL); | |
| GuestTrapCase(ZX_GUEST_TRAP_IO); | |
| GuestTrapCase(ZX_GUEST_TRAP_MEM); | |
| default: | |
| *this << static_cast<uint32_t>(trap_id); | |
| break; | |
| } | |
| *this << ResetColor; | |
| } | |
| #define KoidCase(name) \ | |
| case name: \ | |
| *this << #name << " (" << static_cast<uint64_t>(value) << ")"; \ | |
| break | |
| void PrettyPrinter::DisplayKoid(uint64_t value) { | |
| *this << Red; | |
| switch (value) { | |
| KoidCase(ZX_KOID_INVALID); | |
| KoidCase(ZX_KOID_KERNEL); | |
| default: | |
| *this << static_cast<uint64_t>(value); | |
| break; | |
| } | |
| *this << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayHexa8(uint8_t value) { | |
| std::vector<char> buffer(sizeof(uint8_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%02" PRIx8, value); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayHexa16(uint16_t value) { | |
| std::vector<char> buffer(sizeof(uint16_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%04" PRIx16, value); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayHexa32(uint32_t value) { | |
| std::vector<char> buffer(sizeof(uint32_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%08" PRIx32, value); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayHexa64(uint64_t value) { | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIx64, value); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| #define InfoMapsTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayInfoMapsType(zx_info_maps_type_t type) { | |
| *this << Red; | |
| switch (type) { | |
| InfoMapsTypeCase(ZX_INFO_MAPS_TYPE_NONE); | |
| InfoMapsTypeCase(ZX_INFO_MAPS_TYPE_ASPACE); | |
| InfoMapsTypeCase(ZX_INFO_MAPS_TYPE_VMAR); | |
| InfoMapsTypeCase(ZX_INFO_MAPS_TYPE_MAPPING); | |
| default: | |
| *this << type << ResetColor; | |
| return; | |
| } | |
| } | |
| #define InterruptFlagsCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| break | |
| #define InterruptFlagsFlag(name) \ | |
| if ((flags & (name)) == (name)) { \ | |
| *this << " | " << #name; \ | |
| } | |
| void PrettyPrinter::DisplayInterruptFlags(uint32_t flags) { | |
| *this << Red; | |
| switch (flags & ZX_INTERRUPT_MODE_MASK) { | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_DEFAULT); | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_EDGE_LOW); | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_EDGE_HIGH); | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_LEVEL_LOW); | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_LEVEL_HIGH); | |
| InterruptFlagsCase(ZX_INTERRUPT_MODE_EDGE_BOTH); | |
| default: | |
| *this << (flags & ZX_INTERRUPT_MODE_MASK); | |
| break; | |
| } | |
| InterruptFlagsFlag(ZX_INTERRUPT_REMAP_IRQ); | |
| InterruptFlagsFlag(ZX_INTERRUPT_VIRTUAL); | |
| *this << ResetColor; | |
| } | |
| #define IommuTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayIommuType(uint32_t type) { | |
| *this << Red; | |
| switch (type) { | |
| IommuTypeCase(ZX_IOMMU_TYPE_STUB); | |
| IommuTypeCase(ZX_IOMMU_TYPE_INTEL); | |
| default: | |
| *this << type << ResetColor; | |
| return; | |
| } | |
| } | |
| #define KtraceControlActionCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayKtraceControlAction(uint32_t action) { | |
| constexpr uint32_t KTRACE_ACTION_START = 1; | |
| constexpr uint32_t KTRACE_ACTION_STOP = 2; | |
| constexpr uint32_t KTRACE_ACTION_REWIND = 3; | |
| constexpr uint32_t KTRACE_ACTION_NEW_PROBE = 4; | |
| *this << Blue; | |
| switch (action) { | |
| KtraceControlActionCase(KTRACE_ACTION_START); | |
| KtraceControlActionCase(KTRACE_ACTION_STOP); | |
| KtraceControlActionCase(KTRACE_ACTION_REWIND); | |
| KtraceControlActionCase(KTRACE_ACTION_NEW_PROBE); | |
| default: | |
| *this << action << ResetColor; | |
| return; | |
| } | |
| } | |
| #define TopicCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayObjectInfoTopic(uint32_t topic) { | |
| *this << Blue; | |
| switch (topic) { | |
| TopicCase(ZX_INFO_NONE); | |
| TopicCase(ZX_INFO_HANDLE_VALID); | |
| TopicCase(ZX_INFO_HANDLE_BASIC); | |
| TopicCase(ZX_INFO_PROCESS); | |
| TopicCase(ZX_INFO_PROCESS_THREADS); | |
| TopicCase(ZX_INFO_VMAR); | |
| TopicCase(ZX_INFO_JOB_CHILDREN); | |
| TopicCase(ZX_INFO_JOB_PROCESSES); | |
| TopicCase(ZX_INFO_THREAD); | |
| TopicCase(ZX_INFO_THREAD_EXCEPTION_REPORT); | |
| TopicCase(ZX_INFO_TASK_STATS); | |
| TopicCase(ZX_INFO_PROCESS_MAPS); | |
| TopicCase(ZX_INFO_PROCESS_VMOS); | |
| TopicCase(ZX_INFO_THREAD_STATS); | |
| TopicCase(ZX_INFO_CPU_STATS); | |
| TopicCase(ZX_INFO_KMEM_STATS); | |
| TopicCase(ZX_INFO_RESOURCE); | |
| TopicCase(ZX_INFO_HANDLE_COUNT); | |
| TopicCase(ZX_INFO_BTI); | |
| TopicCase(ZX_INFO_PROCESS_HANDLE_STATS); | |
| TopicCase(ZX_INFO_SOCKET); | |
| TopicCase(ZX_INFO_VMO); | |
| TopicCase(ZX_INFO_JOB); | |
| default: | |
| *this << "topic=" << topic << ResetColor; | |
| return; | |
| } | |
| } | |
| #define ObjTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayObjType(zx_obj_type_t obj_type) { | |
| *this << Blue; | |
| switch (obj_type) { | |
| ObjTypeCase(ZX_OBJ_TYPE_NONE); | |
| ObjTypeCase(ZX_OBJ_TYPE_PROCESS); | |
| ObjTypeCase(ZX_OBJ_TYPE_THREAD); | |
| ObjTypeCase(ZX_OBJ_TYPE_VMO); | |
| ObjTypeCase(ZX_OBJ_TYPE_CHANNEL); | |
| ObjTypeCase(ZX_OBJ_TYPE_EVENT); | |
| ObjTypeCase(ZX_OBJ_TYPE_PORT); | |
| ObjTypeCase(ZX_OBJ_TYPE_INTERRUPT); | |
| ObjTypeCase(ZX_OBJ_TYPE_PCI_DEVICE); | |
| ObjTypeCase(ZX_OBJ_TYPE_LOG); | |
| ObjTypeCase(ZX_OBJ_TYPE_SOCKET); | |
| ObjTypeCase(ZX_OBJ_TYPE_RESOURCE); | |
| ObjTypeCase(ZX_OBJ_TYPE_EVENTPAIR); | |
| ObjTypeCase(ZX_OBJ_TYPE_JOB); | |
| ObjTypeCase(ZX_OBJ_TYPE_VMAR); | |
| ObjTypeCase(ZX_OBJ_TYPE_FIFO); | |
| ObjTypeCase(ZX_OBJ_TYPE_GUEST); | |
| ObjTypeCase(ZX_OBJ_TYPE_VCPU); | |
| ObjTypeCase(ZX_OBJ_TYPE_TIMER); | |
| ObjTypeCase(ZX_OBJ_TYPE_IOMMU); | |
| ObjTypeCase(ZX_OBJ_TYPE_BTI); | |
| ObjTypeCase(ZX_OBJ_TYPE_PROFILE); | |
| ObjTypeCase(ZX_OBJ_TYPE_PMT); | |
| ObjTypeCase(ZX_OBJ_TYPE_SUSPEND_TOKEN); | |
| ObjTypeCase(ZX_OBJ_TYPE_PAGER); | |
| ObjTypeCase(ZX_OBJ_TYPE_EXCEPTION); | |
| ObjTypeCase(ZX_OBJ_TYPE_CLOCK); | |
| ObjTypeCase(ZX_OBJ_TYPE_STREAM); | |
| ObjTypeCase(ZX_OBJ_TYPE_MSI); | |
| ObjTypeCase(ZX_OBJ_TYPE_COUNTER); | |
| ObjTypeCase(ZX_OBJ_TYPE_SAMPLER); | |
| default: | |
| *this << obj_type << ResetColor; | |
| return; | |
| } | |
| } | |
| void PrettyPrinter::DisplayPaddr(zx_paddr_t addr) { | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| #ifdef __MACH__ | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIxPTR, addr); | |
| #else | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIx64, addr); | |
| #endif | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| #define PacketGuestVcpuTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayPacketGuestVcpuType(uint8_t type) { | |
| *this << Blue; | |
| switch (type) { | |
| PacketGuestVcpuTypeCase(ZX_PKT_GUEST_VCPU_INTERRUPT); | |
| PacketGuestVcpuTypeCase(ZX_PKT_GUEST_VCPU_STARTUP); | |
| default: | |
| *this << static_cast<uint32_t>(type) << ResetColor; | |
| return; | |
| } | |
| } | |
| #define PacketPageRequestCommandCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayPacketPageRequestCommand(uint16_t command) { | |
| *this << Blue; | |
| switch (command) { | |
| PacketPageRequestCommandCase(ZX_PAGER_VMO_READ); | |
| PacketPageRequestCommandCase(ZX_PAGER_VMO_COMPLETE); | |
| default: | |
| *this << static_cast<uint32_t>(command) << ResetColor; | |
| return; | |
| } | |
| } | |
| #define PolicyCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayPolicyAction(uint32_t action) { | |
| *this << Blue; | |
| switch (action) { | |
| PolicyCase(ZX_POL_ACTION_ALLOW); | |
| PolicyCase(ZX_POL_ACTION_DENY); | |
| PolicyCase(ZX_POL_ACTION_ALLOW_EXCEPTION); | |
| PolicyCase(ZX_POL_ACTION_DENY_EXCEPTION); | |
| PolicyCase(ZX_POL_ACTION_KILL); | |
| default: | |
| *this << action << ResetColor; | |
| return; | |
| } | |
| } | |
| void PrettyPrinter::DisplayPolicyCondition(uint32_t condition) { | |
| *this << Blue; | |
| switch (condition) { | |
| PolicyCase(ZX_POL_BAD_HANDLE); | |
| PolicyCase(ZX_POL_WRONG_OBJECT); | |
| PolicyCase(ZX_POL_VMAR_WX); | |
| PolicyCase(ZX_POL_NEW_ANY); | |
| PolicyCase(ZX_POL_NEW_VMO); | |
| PolicyCase(ZX_POL_NEW_CHANNEL); | |
| PolicyCase(ZX_POL_NEW_EVENT); | |
| PolicyCase(ZX_POL_NEW_EVENTPAIR); | |
| PolicyCase(ZX_POL_NEW_PORT); | |
| PolicyCase(ZX_POL_NEW_SOCKET); | |
| PolicyCase(ZX_POL_NEW_FIFO); | |
| PolicyCase(ZX_POL_NEW_TIMER); | |
| PolicyCase(ZX_POL_NEW_PROCESS); | |
| PolicyCase(ZX_POL_NEW_PROFILE); | |
| PolicyCase(ZX_POL_AMBIENT_MARK_VMO_EXEC); | |
| default: | |
| *this << condition << ResetColor; | |
| return; | |
| } | |
| } | |
| void PrettyPrinter::DisplayPolicyTopic(uint32_t topic) { | |
| *this << Blue; | |
| switch (topic) { | |
| PolicyCase(ZX_JOB_POL_BASIC); | |
| PolicyCase(ZX_JOB_POL_TIMER_SLACK); | |
| default: | |
| *this << topic << ResetColor; | |
| return; | |
| } | |
| } | |
| #define ProfileInfoFlagsCase(name) \ | |
| if ((flags & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayProfileInfoFlags(uint32_t flags) { | |
| *this << Blue; | |
| if (flags == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| ProfileInfoFlagsCase(ZX_PROFILE_INFO_FLAG_PRIORITY); | |
| ProfileInfoFlagsCase(ZX_PROFILE_INFO_FLAG_CPU_MASK); | |
| *this << ResetColor; | |
| } | |
| #define PortPacketTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayPortPacketType(uint32_t type) { | |
| *this << Blue; | |
| switch (type) { | |
| PortPacketTypeCase(ZX_PKT_TYPE_USER); | |
| PortPacketTypeCase(ZX_PKT_TYPE_SIGNAL_ONE); | |
| PortPacketTypeCase(ZX_PKT_TYPE_GUEST_BELL); | |
| PortPacketTypeCase(ZX_PKT_TYPE_GUEST_MEM); | |
| PortPacketTypeCase(ZX_PKT_TYPE_GUEST_IO); | |
| PortPacketTypeCase(ZX_PKT_TYPE_GUEST_VCPU); | |
| PortPacketTypeCase(ZX_PKT_TYPE_INTERRUPT); | |
| PortPacketTypeCase(ZX_PKT_TYPE_PAGE_REQUEST); | |
| default: | |
| *this << "port_packet_type=" << type << ResetColor; | |
| return; | |
| } | |
| } | |
| // ZX_PROP_REGISTER_GS and ZX_PROP_REGISTER_FS are defined in | |
| // <zircon/system/public/zircon/syscalls/object.h> | |
| // but only available for amd64. | |
| // We need these values in all the environments. | |
| #ifndef ZX_PROP_REGISTER_GS | |
| #define ZX_PROP_REGISTER_GS ((uint32_t)2u) | |
| #endif | |
| #ifndef ZX_PROP_REGISTER_FS | |
| #define ZX_PROP_REGISTER_FS ((uint32_t)4u) | |
| #endif | |
| #define PropTypeCase(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| *this << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayPropType(uint32_t type) { | |
| *this << Blue; | |
| switch (type) { | |
| PropTypeCase(ZX_PROP_NAME); | |
| PropTypeCase(ZX_PROP_REGISTER_FS); | |
| PropTypeCase(ZX_PROP_REGISTER_GS); | |
| PropTypeCase(ZX_PROP_PROCESS_DEBUG_ADDR); | |
| PropTypeCase(ZX_PROP_PROCESS_VDSO_BASE_ADDRESS); | |
| PropTypeCase(ZX_PROP_SOCKET_RX_THRESHOLD); | |
| PropTypeCase(ZX_PROP_SOCKET_TX_THRESHOLD); | |
| PropTypeCase(ZX_PROP_JOB_KILL_ON_OOM); | |
| PropTypeCase(ZX_PROP_EXCEPTION_STATE); | |
| default: | |
| *this << type << ResetColor; | |
| return; | |
| } | |
| } | |
| #define RightsCase(name) \ | |
| if ((rights & (name)) != 0) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayRights(uint32_t rights) { | |
| *this << Blue; | |
| if (rights == 0) { | |
| *this << "ZX_RIGHT_NONE" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| RightsCase(ZX_RIGHT_DUPLICATE); | |
| RightsCase(ZX_RIGHT_TRANSFER); | |
| RightsCase(ZX_RIGHT_READ); | |
| RightsCase(ZX_RIGHT_WRITE); | |
| RightsCase(ZX_RIGHT_EXECUTE); | |
| RightsCase(ZX_RIGHT_MAP); | |
| RightsCase(ZX_RIGHT_GET_PROPERTY); | |
| RightsCase(ZX_RIGHT_SET_PROPERTY); | |
| RightsCase(ZX_RIGHT_ENUMERATE); | |
| RightsCase(ZX_RIGHT_DESTROY); | |
| RightsCase(ZX_RIGHT_SET_POLICY); | |
| RightsCase(ZX_RIGHT_GET_POLICY); | |
| RightsCase(ZX_RIGHT_SIGNAL); | |
| RightsCase(ZX_RIGHT_SIGNAL_PEER); | |
| RightsCase(ZX_RIGHT_WAIT); | |
| RightsCase(ZX_RIGHT_INSPECT); | |
| RightsCase(ZX_RIGHT_MANAGE_JOB); | |
| RightsCase(ZX_RIGHT_MANAGE_PROCESS); | |
| RightsCase(ZX_RIGHT_MANAGE_THREAD); | |
| RightsCase(ZX_RIGHT_APPLY_PROFILE); | |
| RightsCase(ZX_RIGHT_MANAGE_SOCKET); | |
| RightsCase(ZX_RIGHT_SAME_RIGHTS); | |
| *this << ResetColor; | |
| } | |
| #define RsrcKindCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayRsrcKind(zx_rsrc_kind_t kind) { | |
| *this << Blue; | |
| switch (kind) { | |
| RsrcKindCase(ZX_RSRC_KIND_MMIO); | |
| RsrcKindCase(ZX_RSRC_KIND_IRQ); | |
| RsrcKindCase(ZX_RSRC_KIND_IOPORT); | |
| RsrcKindCase(ZX_RSRC_KIND_SMC); | |
| RsrcKindCase(ZX_RSRC_KIND_SYSTEM); | |
| RsrcKindCase(ZX_RSRC_KIND_COUNT); | |
| default: | |
| *this << kind << ResetColor; | |
| return; | |
| } | |
| } | |
| #define SignalCase(name) \ | |
| if ((signals & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplaySignals(zx_signals_t signals) { | |
| *this << Blue; | |
| if (signals == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| if (signals == __ZX_OBJECT_SIGNAL_ALL) { | |
| *this << "__ZX_OBJECT_SIGNAL_ALL" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| SignalCase(__ZX_OBJECT_READABLE); | |
| SignalCase(__ZX_OBJECT_WRITABLE); | |
| SignalCase(__ZX_OBJECT_PEER_CLOSED); | |
| SignalCase(__ZX_OBJECT_SIGNALED); | |
| SignalCase(__ZX_OBJECT_SIGNAL_4); | |
| SignalCase(__ZX_OBJECT_SIGNAL_5); | |
| SignalCase(__ZX_OBJECT_SIGNAL_6); | |
| SignalCase(__ZX_OBJECT_SIGNAL_7); | |
| SignalCase(__ZX_OBJECT_SIGNAL_8); | |
| SignalCase(__ZX_OBJECT_SIGNAL_9); | |
| SignalCase(__ZX_OBJECT_SIGNAL_10); | |
| SignalCase(__ZX_OBJECT_SIGNAL_11); | |
| SignalCase(__ZX_OBJECT_SIGNAL_12); | |
| SignalCase(__ZX_OBJECT_SIGNAL_13); | |
| SignalCase(__ZX_OBJECT_SIGNAL_14); | |
| SignalCase(__ZX_OBJECT_SIGNAL_15); | |
| SignalCase(__ZX_OBJECT_SIGNAL_16); | |
| SignalCase(__ZX_OBJECT_SIGNAL_17); | |
| SignalCase(__ZX_OBJECT_SIGNAL_18); | |
| SignalCase(__ZX_OBJECT_SIGNAL_19); | |
| SignalCase(__ZX_OBJECT_SIGNAL_20); | |
| SignalCase(__ZX_OBJECT_SIGNAL_21); | |
| SignalCase(__ZX_OBJECT_SIGNAL_22); | |
| SignalCase(__ZX_OBJECT_HANDLE_CLOSED); | |
| SignalCase(ZX_USER_SIGNAL_0); | |
| SignalCase(ZX_USER_SIGNAL_1); | |
| SignalCase(ZX_USER_SIGNAL_2); | |
| SignalCase(ZX_USER_SIGNAL_3); | |
| SignalCase(ZX_USER_SIGNAL_4); | |
| SignalCase(ZX_USER_SIGNAL_5); | |
| SignalCase(ZX_USER_SIGNAL_6); | |
| SignalCase(ZX_USER_SIGNAL_7); | |
| *this << ResetColor; | |
| } | |
| #define SocketCreateOptionsCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplaySocketCreateOptions(uint32_t options) { | |
| *this << Blue; | |
| switch (options) { | |
| SocketCreateOptionsCase(ZX_SOCKET_STREAM); | |
| SocketCreateOptionsCase(ZX_SOCKET_DATAGRAM); | |
| default: | |
| *this << static_cast<uint32_t>(options) << ResetColor; | |
| return; | |
| } | |
| } | |
| #define SocketReadOptionsCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplaySocketReadOptions(uint32_t options) { | |
| *this << Blue; | |
| switch (options) { | |
| SocketReadOptionsCase(ZX_SOCKET_PEEK); | |
| default: | |
| *this << static_cast<uint32_t>(options) << ResetColor; | |
| return; | |
| } | |
| } | |
| #define SocketDispositionCase(name) \ | |
| if ((disposition & (name)) == (name)) { \ | |
| disposition ^= (name); \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplaySocketDisposition(uint32_t disposition) { | |
| *this << Blue; | |
| if (disposition == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| SocketDispositionCase(ZX_SOCKET_DISPOSITION_WRITE_DISABLED); | |
| SocketDispositionCase(ZX_SOCKET_DISPOSITION_WRITE_ENABLED); | |
| if (disposition) { | |
| *this << separator << disposition; | |
| } | |
| *this << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayStatus(zx_status_t status) { | |
| if (status == ZX_OK) { | |
| *this << Green; | |
| } else { | |
| *this << Red; | |
| } | |
| *this << StatusName(status) << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayString(std::string_view string) { | |
| if (string.data() == nullptr) { | |
| *this << "nullptr\n"; | |
| } else { | |
| *this << Red << '"'; | |
| for (char value : string) { | |
| switch (value) { | |
| case 0: | |
| break; | |
| case '\\': | |
| *this << "\\\\"; | |
| break; | |
| case '\n': | |
| *this << "\\n"; | |
| break; | |
| default: | |
| *this << value; | |
| break; | |
| } | |
| } | |
| *this << '"' << ResetColor; | |
| } | |
| } | |
| #define SystemEventTypeCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplaySystemEventType(zx_system_event_type_t type) { | |
| *this << Blue; | |
| switch (type) { | |
| SystemEventTypeCase(ZX_SYSTEM_EVENT_OUT_OF_MEMORY); | |
| default: | |
| *this << type << ResetColor; | |
| return; | |
| } | |
| } | |
| #define SystemPowerctlCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplaySystemPowerctl(uint32_t powerctl) { | |
| *this << Blue; | |
| switch (powerctl) { | |
| SystemPowerctlCase(ZX_SYSTEM_POWERCTL_REBOOT); | |
| SystemPowerctlCase(ZX_SYSTEM_POWERCTL_REBOOT_BOOTLOADER); | |
| SystemPowerctlCase(ZX_SYSTEM_POWERCTL_REBOOT_RECOVERY); | |
| SystemPowerctlCase(ZX_SYSTEM_POWERCTL_SHUTDOWN); | |
| default: | |
| *this << powerctl << ResetColor; | |
| return; | |
| } | |
| } | |
| #define ThreadStateCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayThreadState(uint32_t state) { | |
| *this << Blue; | |
| switch (state) { | |
| ThreadStateCase(ZX_THREAD_STATE_NEW); | |
| ThreadStateCase(ZX_THREAD_STATE_RUNNING); | |
| ThreadStateCase(ZX_THREAD_STATE_SUSPENDED); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED); | |
| ThreadStateCase(ZX_THREAD_STATE_DYING); | |
| ThreadStateCase(ZX_THREAD_STATE_DEAD); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_EXCEPTION); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_SLEEPING); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_FUTEX); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_PORT); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_CHANNEL); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_WAIT_ONE); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_WAIT_MANY); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_INTERRUPT); | |
| ThreadStateCase(ZX_THREAD_STATE_BLOCKED_PAGER); | |
| default: | |
| *this << static_cast<uint32_t>(state) << ResetColor; | |
| return; | |
| } | |
| } | |
| #define ThreadStateTopicCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayThreadStateTopic(zx_thread_state_topic_t topic) { | |
| *this << Blue; | |
| switch (topic) { | |
| ThreadStateTopicCase(ZX_THREAD_STATE_GENERAL_REGS); | |
| ThreadStateTopicCase(ZX_THREAD_STATE_FP_REGS); | |
| ThreadStateTopicCase(ZX_THREAD_STATE_VECTOR_REGS); | |
| ThreadStateTopicCase(ZX_THREAD_STATE_DEBUG_REGS); | |
| ThreadStateTopicCase(ZX_THREAD_STATE_SINGLE_STEP); | |
| default: | |
| *this << static_cast<uint32_t>(topic) << ResetColor; | |
| return; | |
| } | |
| } | |
| void PrettyPrinter::DisplayTime(zx_time_t time_ns) { | |
| if (time_ns == ZX_TIME_INFINITE) { | |
| (*this) << Blue << "ZX_TIME_INFINITE" << ResetColor; | |
| } else if (time_ns == ZX_TIME_INFINITE_PAST) { | |
| (*this) << Blue << "ZX_TIME_INFINITE_PAST" << ResetColor; | |
| } else { | |
| // Gets the time in seconds. | |
| time_t value = time_ns / kOneBillion; | |
| struct tm tm; | |
| if (localtime_r(&value, &tm) == &tm) { | |
| char buffer[100]; | |
| strftime(buffer, sizeof(buffer), "%c", &tm); | |
| // And now, displays the nano seconds. | |
| (*this) << Blue << buffer << " and "; | |
| snprintf(buffer, sizeof(buffer), "%09" PRId64, time_ns % kOneBillion); | |
| (*this) << buffer << " ns" << ResetColor; | |
| } else { | |
| (*this) << Red << "unknown time" << ResetColor; | |
| } | |
| } | |
| } | |
| #define TimerOptionCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayTimerOption(uint32_t option) { | |
| *this << Blue; | |
| switch (option) { | |
| TimerOptionCase(ZX_TIMER_SLACK_CENTER); | |
| TimerOptionCase(ZX_TIMER_SLACK_EARLY); | |
| TimerOptionCase(ZX_TIMER_SLACK_LATE); | |
| default: | |
| *this << option << ResetColor; | |
| return; | |
| } | |
| } | |
| #ifdef __MACH__ | |
| void PrettyPrinter::DisplayUintptr(uintptr_t ptr) { | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIxPTR, ptr); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| #else | |
| void PrettyPrinter::DisplayUintptr(uint64_t ptr) { | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIx64, ptr); | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| #endif | |
| void PrettyPrinter::DisplayVaddr(zx_vaddr_t addr) { | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| #ifdef __MACH__ | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIxPTR, addr); | |
| #else | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIx64, addr); | |
| #endif | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| void PrettyPrinter::DisplayGpAddr(zx_gpaddr_t addr) { | |
| #ifdef __MACH__ | |
| std::vector<char> buffer(sizeof(uintptr_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIxPTR, addr); | |
| #else | |
| std::vector<char> buffer(sizeof(uint64_t) * kCharactersPerByte + 1); | |
| snprintf(buffer.data(), buffer.size(), "%016" PRIx64, addr); | |
| #endif | |
| *this << Blue << buffer.data() << ResetColor; | |
| } | |
| #define VcpuCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayVcpu(uint32_t type) { | |
| *this << Red; | |
| switch (type) { | |
| VcpuCase(ZX_VCPU_STATE); | |
| VcpuCase(ZX_VCPU_IO); | |
| default: | |
| *this << type << ResetColor; | |
| return; | |
| } | |
| } | |
| #define VmOptionAlign(name) \ | |
| case name: \ | |
| *this << #name; \ | |
| separator = " | "; \ | |
| break; | |
| #define VmOptionCase(name) \ | |
| if ((option & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayVmOption(zx_vm_option_t option) { | |
| *this << Red; | |
| if (option == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| switch (option & ~((1 << ZX_VM_ALIGN_BASE) - 1)) { | |
| VmOptionAlign(ZX_VM_ALIGN_1KB); | |
| VmOptionAlign(ZX_VM_ALIGN_2KB); | |
| VmOptionAlign(ZX_VM_ALIGN_4KB); | |
| VmOptionAlign(ZX_VM_ALIGN_8KB); | |
| VmOptionAlign(ZX_VM_ALIGN_16KB); | |
| VmOptionAlign(ZX_VM_ALIGN_32KB); | |
| VmOptionAlign(ZX_VM_ALIGN_64KB); | |
| VmOptionAlign(ZX_VM_ALIGN_128KB); | |
| VmOptionAlign(ZX_VM_ALIGN_256KB); | |
| VmOptionAlign(ZX_VM_ALIGN_512KB); | |
| VmOptionAlign(ZX_VM_ALIGN_1MB); | |
| VmOptionAlign(ZX_VM_ALIGN_2MB); | |
| VmOptionAlign(ZX_VM_ALIGN_4MB); | |
| VmOptionAlign(ZX_VM_ALIGN_8MB); | |
| VmOptionAlign(ZX_VM_ALIGN_16MB); | |
| VmOptionAlign(ZX_VM_ALIGN_32MB); | |
| VmOptionAlign(ZX_VM_ALIGN_64MB); | |
| VmOptionAlign(ZX_VM_ALIGN_128MB); | |
| VmOptionAlign(ZX_VM_ALIGN_256MB); | |
| VmOptionAlign(ZX_VM_ALIGN_512MB); | |
| VmOptionAlign(ZX_VM_ALIGN_1GB); | |
| VmOptionAlign(ZX_VM_ALIGN_2GB); | |
| VmOptionAlign(ZX_VM_ALIGN_4GB); | |
| default: | |
| if ((option >> ZX_VM_ALIGN_BASE) != 0) { | |
| *this << (option >> ZX_VM_ALIGN_BASE); | |
| } | |
| break; | |
| } | |
| VmOptionCase(ZX_VM_PERM_READ); | |
| VmOptionCase(ZX_VM_PERM_WRITE); | |
| VmOptionCase(ZX_VM_PERM_EXECUTE); | |
| VmOptionCase(ZX_VM_COMPACT); | |
| VmOptionCase(ZX_VM_SPECIFIC); | |
| VmOptionCase(ZX_VM_SPECIFIC_OVERWRITE); | |
| VmOptionCase(ZX_VM_CAN_MAP_SPECIFIC); | |
| VmOptionCase(ZX_VM_CAN_MAP_READ); | |
| VmOptionCase(ZX_VM_CAN_MAP_WRITE); | |
| VmOptionCase(ZX_VM_CAN_MAP_EXECUTE); | |
| VmOptionCase(ZX_VM_MAP_RANGE); | |
| VmOptionCase(ZX_VM_REQUIRE_NON_RESIZABLE); | |
| VmOptionCase(ZX_VM_ALLOW_FAULTS); | |
| *this << ResetColor; | |
| } | |
| #define VmoCreationOptionCase(name) \ | |
| if ((options & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayVmoCreationOption(uint32_t options) { | |
| *this << Blue; | |
| if (options == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| VmoCreationOptionCase(ZX_VMO_RESIZABLE); | |
| *this << ResetColor; | |
| } | |
| #define VmoOpCase(name) \ | |
| case name: \ | |
| *this << #name << ResetColor; \ | |
| return | |
| void PrettyPrinter::DisplayVmoOp(uint32_t op) { | |
| *this << Blue; | |
| switch (op) { | |
| VmoOpCase(ZX_VMO_OP_COMMIT); | |
| VmoOpCase(ZX_VMO_OP_DECOMMIT); | |
| VmoOpCase(ZX_VMO_OP_LOCK); | |
| VmoOpCase(ZX_VMO_OP_UNLOCK); | |
| VmoOpCase(ZX_VMO_OP_CACHE_SYNC); | |
| VmoOpCase(ZX_VMO_OP_CACHE_INVALIDATE); | |
| VmoOpCase(ZX_VMO_OP_CACHE_CLEAN); | |
| VmoOpCase(ZX_VMO_OP_CACHE_CLEAN_INVALIDATE); | |
| default: | |
| *this << op << ResetColor; | |
| return; | |
| } | |
| } | |
| #define VmoOptionCase(name) \ | |
| if ((options & (name)) == (name)) { \ | |
| *this << separator << #name; \ | |
| separator = " | "; \ | |
| } | |
| void PrettyPrinter::DisplayVmoOption(uint32_t options) { | |
| *this << Blue; | |
| if (options == 0) { | |
| *this << "0" << ResetColor; | |
| return; | |
| } | |
| const char* separator = ""; | |
| VmoOptionCase(ZX_VMO_CHILD_SNAPSHOT); | |
| VmoOptionCase(ZX_VMO_CHILD_RESIZABLE); | |
| VmoOptionCase(ZX_VMO_CHILD_SLICE); | |
| VmoOptionCase(ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE); | |
| *this << ResetColor; | |
| } | |
| #define VmoTypeCase(name) \ | |
| if ((type & (name)) == (name)) { \ | |
| *this << " | " << #name; \ | |
| } | |
| void PrettyPrinter::DisplayVmoType(uint32_t type) { | |
| *this << Blue; | |
| if ((type & 1) == ZX_INFO_VMO_TYPE_PHYSICAL) { | |
| *this << "ZX_INFO_VMO_TYPE_PHYSICAL"; | |
| } else { | |
| *this << "ZX_INFO_VMO_TYPE_PAGED"; | |
| } | |
| VmoTypeCase(ZX_INFO_VMO_RESIZABLE); | |
| VmoTypeCase(ZX_INFO_VMO_IS_COW_CLONE); | |
| VmoTypeCase(ZX_INFO_VMO_VIA_HANDLE); | |
| VmoTypeCase(ZX_INFO_VMO_VIA_MAPPING); | |
| VmoTypeCase(ZX_INFO_VMO_PAGER_BACKED); | |
| VmoTypeCase(ZX_INFO_VMO_CONTIGUOUS); | |
| *this << ResetColor; | |
| } | |
| void PrettyPrinter::IncrementTabulations() { | |
| ++tabulations_; | |
| if (need_to_print_header_) { | |
| remaining_size_ -= kTabSize; | |
| } | |
| } | |
| void PrettyPrinter::DecrementTabulations() { | |
| --tabulations_; | |
| if (need_to_print_header_) { | |
| remaining_size_ += kTabSize; | |
| } | |
| } | |
| void PrettyPrinter::NeedHeader() { | |
| remaining_size_ = max_line_size_ - line_header_size_ - tabulations_ * kTabSize; | |
| need_to_print_header_ = true; | |
| } | |
| void PrettyPrinter::PrintHeader(char first_character) { | |
| FX_DCHECK(need_to_print_header_); | |
| need_to_print_header_ = false; | |
| if (line_header_size_ > 0) { | |
| os_ << line_header_; | |
| if (!header_on_every_line_) { | |
| line_header_size_ = 0; | |
| } | |
| } | |
| if (first_character != '\n') { | |
| for (int tab = tabulations_ * kTabSize; tab > 0; --tab) { | |
| os_ << ' '; | |
| } | |
| } | |
| } | |
| PrettyPrinter& PrettyPrinter::operator<<(std::string_view data) { | |
| if (data.empty()) { | |
| return *this; | |
| } | |
| if (need_to_print_header_) { | |
| PrintHeader(data[0]); | |
| } | |
| size_t end_of_line = data.find('\n', 0); | |
| if (end_of_line == std::string_view::npos) { | |
| os_ << data; | |
| remaining_size_ -= data.size(); | |
| return *this; | |
| } | |
| size_t current = 0; | |
| for (;;) { | |
| std::string_view tmp = data.substr(current, end_of_line - current + 1); | |
| os_ << tmp; | |
| NeedHeader(); | |
| current = end_of_line + 1; | |
| if (current >= data.size()) { | |
| return *this; | |
| } | |
| end_of_line = data.find('\n', current); | |
| if (end_of_line == std::string_view::npos) { | |
| os_ << data; | |
| remaining_size_ -= data.size(); | |
| return *this; | |
| } | |
| PrintHeader(data[current]); | |
| } | |
| } | |
| } // namespace fidl_codec |