| // 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/client_protocol.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include "src/developer/debug/ipc/message_reader.h" | |
| #include "src/developer/debug/ipc/message_writer.h" | |
| #include "src/developer/debug/ipc/protocol_helpers.h" | |
| namespace debug_ipc { | |
| // Record deserializers ---------------------------------------------------------------------------- | |
| bool Deserialize(MessageReader* reader, ProcessTreeRecord* record) { | |
| if (!reader->ReadUint32(reinterpret_cast<uint32_t*>(&record->type))) | |
| return false; | |
| if (!reader->ReadUint64(&record->koid)) | |
| return false; | |
| if (!reader->ReadString(&record->name)) | |
| return false; | |
| return Deserialize(reader, &record->children); | |
| } | |
| bool Deserialize(MessageReader* reader, ThreadRecord* record) { | |
| if (!reader->ReadUint64(&record->process_koid)) | |
| return false; | |
| if (!reader->ReadUint64(&record->thread_koid)) | |
| return false; | |
| if (!reader->ReadString(&record->name)) | |
| return false; | |
| uint32_t state; | |
| if (!reader->ReadUint32(&state)) | |
| return false; | |
| if (state >= static_cast<uint32_t>(ThreadRecord::State::kLast)) | |
| return false; | |
| record->state = static_cast<ThreadRecord::State>(state); | |
| uint32_t blocked_reason; | |
| if (!reader->ReadUint32(&blocked_reason)) | |
| return false; | |
| if (state >= static_cast<uint32_t>(ThreadRecord::BlockedReason::kLast)) | |
| return false; | |
| record->blocked_reason = static_cast<ThreadRecord::BlockedReason>(blocked_reason); | |
| uint32_t stack_amount; | |
| if (!reader->ReadUint32(&stack_amount)) | |
| return false; | |
| if (stack_amount >= static_cast<uint32_t>(ThreadRecord::StackAmount::kLast)) | |
| return false; | |
| record->stack_amount = static_cast<ThreadRecord::StackAmount>(stack_amount); | |
| if (!Deserialize(reader, &record->frames)) | |
| return false; | |
| return true; | |
| } | |
| bool Deserialize(MessageReader* reader, ProcessRecord* record) { | |
| if (!reader->ReadUint64(&record->process_koid) || !reader->ReadString(&record->process_name)) { | |
| return false; | |
| } | |
| return Deserialize(reader, &record->threads); | |
| } | |
| bool Deserialize(MessageReader* reader, MemoryBlock* block) { | |
| if (!reader->ReadUint64(&block->address)) | |
| return false; | |
| if (!reader->ReadBool(&block->valid)) | |
| return false; | |
| if (!reader->ReadUint32(&block->size)) | |
| return false; | |
| if (block->valid) { | |
| if (block->size > reader->remaining()) | |
| return false; | |
| block->data.resize(block->size); | |
| if (!reader->ReadBytes(block->size, &block->data[0])) | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool Deserialize(MessageReader* reader, Module* module) { | |
| if (!reader->ReadString(&module->name)) | |
| return false; | |
| if (!reader->ReadUint64(&module->base)) | |
| return false; | |
| if (!reader->ReadUint64(&module->debug_address)) | |
| return false; | |
| if (!reader->ReadString(&module->build_id)) | |
| return false; | |
| return true; | |
| } | |
| bool Deserialize(MessageReader* reader, StackFrame* frame) { | |
| if (!reader->ReadUint64(&frame->ip)) | |
| return false; | |
| if (!reader->ReadUint64(&frame->sp)) | |
| return false; | |
| if (!reader->ReadUint64(&frame->cfa)) | |
| return false; | |
| return Deserialize(reader, &frame->regs); | |
| } | |
| bool Deserialize(MessageReader* reader, BreakpointStats* stats) { | |
| if (!reader->ReadUint32(&stats->id)) | |
| return false; | |
| if (!reader->ReadUint32(&stats->hit_count)) | |
| return false; | |
| return reader->ReadBool(&stats->should_delete); | |
| } | |
| bool Deserialize(MessageReader* reader, AddressRegion* region) { | |
| if (!reader->ReadString(®ion->name)) | |
| return false; | |
| if (!reader->ReadUint64(®ion->base)) | |
| return false; | |
| if (!reader->ReadUint64(®ion->size)) | |
| return false; | |
| if (!reader->ReadUint64(®ion->depth)) | |
| return false; | |
| return true; | |
| } | |
| // Record serializers ------------------------------------------------------------------------------ | |
| void Serialize(const ProcessBreakpointSettings& settings, MessageWriter* writer) { | |
| writer->WriteUint64(settings.process_koid); | |
| writer->WriteUint64(settings.thread_koid); | |
| writer->WriteUint64(settings.address); | |
| Serialize(settings.address_range, writer); | |
| } | |
| void Serialize(const BreakpointSettings& settings, MessageWriter* writer) { | |
| writer->WriteUint32(settings.id); | |
| writer->WriteUint32(static_cast<uint32_t>(settings.type)); | |
| writer->WriteString(settings.name); | |
| writer->WriteBool(settings.one_shot); | |
| writer->WriteUint32(static_cast<uint32_t>(settings.stop)); | |
| Serialize(settings.locations, writer); | |
| } | |
| void Serialize(const ConfigAction& action, MessageWriter* writer) { | |
| writer->WriteUint32(static_cast<uint32_t>(action.type)); | |
| writer->WriteString(action.value); | |
| } | |
| // Hello ------------------------------------------------------------------------------------------- | |
| void WriteRequest(const HelloRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kHello, transaction_id); | |
| } | |
| bool ReadReply(MessageReader* reader, HelloReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return reader->ReadBytes(sizeof(HelloReply), reply); | |
| } | |
| // Status ------------------------------------------------------------------------------------------ | |
| void WriteRequest(const StatusRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kStatus, transaction_id); | |
| } | |
| bool ReadReply(MessageReader* reader, StatusReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!Deserialize(reader, &reply->processes)) | |
| return false; | |
| return Deserialize(reader, &reply->limbo); | |
| } | |
| // ProcessStatus ----------------------------------------------------------------------------------- | |
| void WriteRequest(const ProcessStatusRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kProcessStatus, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| } | |
| bool ReadReply(MessageReader* reader, ProcessStatusReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadUint32(&reply->status)) | |
| return false; | |
| return true; | |
| } | |
| // Launch ------------------------------------------------------------------------------------------ | |
| void WriteRequest(const LaunchRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kLaunch, transaction_id); | |
| writer->WriteUint32(static_cast<uint32_t>(request.inferior_type)); | |
| Serialize(request.argv, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, LaunchReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| uint32_t inferior_type; | |
| if (!reader->ReadUint32(&inferior_type) || | |
| inferior_type >= static_cast<uint32_t>(InferiorType::kLast)) { | |
| return false; | |
| } | |
| reply->inferior_type = static_cast<InferiorType>(inferior_type); | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| if (!reader->ReadUint64(&reply->process_id)) | |
| return false; | |
| if (!reader->ReadUint64(&reply->component_id)) | |
| return false; | |
| if (!reader->ReadString(&reply->process_name)) | |
| return false; | |
| return true; | |
| } | |
| // Kill -------------------------------------------------------------------------------------------- | |
| void WriteRequest(const KillRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kKill, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| } | |
| bool ReadReply(MessageReader* reader, KillReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| return true; | |
| } | |
| // Attach ------------------------------------------------------------------------------------------ | |
| void WriteRequest(const AttachRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kAttach, transaction_id); | |
| writer->WriteUint32(static_cast<uint32_t>(request.type)); | |
| writer->WriteUint64(request.koid); | |
| } | |
| bool ReadReply(MessageReader* reader, AttachReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadUint64(&reply->koid)) | |
| return false; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| if (!reader->ReadString(&reply->name)) | |
| return false; | |
| return true; | |
| } | |
| // Detach ------------------------------------------------------------------------------------------ | |
| void WriteRequest(const DetachRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kDetach, transaction_id); | |
| writer->WriteUint32(static_cast<uint32_t>(request.type)); | |
| writer->WriteUint64(request.koid); | |
| } | |
| bool ReadReply(MessageReader* reader, DetachReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| return true; | |
| } | |
| // Pause ------------------------------------------------------------------------------------------- | |
| void WriteRequest(const PauseRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kPause, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| writer->WriteUint64(request.thread_koid); | |
| } | |
| bool ReadReply(MessageReader* reader, PauseReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->threads); | |
| } | |
| // QuitAgent --------------------------------------------------------------------------------------- | |
| void WriteRequest(const QuitAgentRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kQuitAgent, transaction_id); | |
| } | |
| bool ReadReply(MessageReader* reader, QuitAgentReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return true; | |
| } | |
| // Resume ------------------------------------------------------------------------------------------ | |
| void WriteRequest(const ResumeRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kResume, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| Serialize(request.thread_koids, writer); | |
| writer->WriteUint32(static_cast<uint32_t>(request.how)); | |
| writer->WriteUint64(request.range_begin); | |
| writer->WriteUint64(request.range_end); | |
| } | |
| bool ReadReply(MessageReader* reader, ResumeReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return true; | |
| } | |
| // ProcessTree ------------------------------------------------------------------------------------- | |
| void WriteRequest(const ProcessTreeRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kProcessTree, transaction_id); | |
| writer->WriteBytes(&request, sizeof(ProcessTreeRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, ProcessTreeReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->root); | |
| } | |
| // Threads ----------------------------------------------------------------------------------------- | |
| void WriteRequest(const ThreadsRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kThreads, transaction_id); | |
| writer->WriteBytes(&request, sizeof(ThreadsRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, ThreadsReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->threads); | |
| } | |
| // ReadMemory -------------------------------------------------------------------------------------- | |
| void WriteRequest(const ReadMemoryRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kReadMemory, transaction_id); | |
| writer->WriteBytes(&request, sizeof(ReadMemoryRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, ReadMemoryReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->blocks); | |
| } | |
| // ReadRegisters ----------------------------------------------------------------------------------- | |
| void WriteRequest(const ReadRegistersRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kReadRegisters, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| writer->WriteUint64(request.thread_koid); | |
| Serialize(request.categories, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, ReadRegistersReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->registers); | |
| } | |
| // WriteRegisters ---------------------------------------------------------------------------------- | |
| void WriteRequest(const WriteRegistersRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kWriteRegisters, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| writer->WriteUint64(request.thread_koid); | |
| Serialize(request.registers, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, WriteRegistersReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| return Deserialize(reader, &reply->registers); | |
| } | |
| // AddOrChangeBreakpoint --------------------------------------------------------------------------- | |
| void WriteRequest(const AddOrChangeBreakpointRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kAddOrChangeBreakpoint, transaction_id); | |
| Serialize(request.breakpoint, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, AddOrChangeBreakpointReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return reader->ReadInt32(&reply->status); | |
| } | |
| // RemoveBreakpoint -------------------------------------------------------------------------------- | |
| void WriteRequest(const RemoveBreakpointRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kRemoveBreakpoint, transaction_id); | |
| writer->WriteBytes(&request, sizeof(RemoveBreakpointRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, RemoveBreakpointReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return true; | |
| } | |
| // SysInfo ----------------------------------------------------------------------------------------- | |
| void WriteRequest(const SysInfoRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kSysInfo, transaction_id); | |
| } | |
| bool ReadReply(MessageReader* reader, SysInfoReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadString(&reply->version) || !reader->ReadUint32(&reply->num_cpus) || | |
| !reader->ReadUint32(&reply->memory_mb) || !reader->ReadUint32(&reply->hw_breakpoint_count) || | |
| !reader->ReadUint32(&reply->hw_watchpoint_count)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| // ThreadStatus ------------------------------------------------------------------------------------ | |
| void WriteRequest(const ThreadStatusRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kThreadStatus, transaction_id); | |
| writer->WriteBytes(&request, sizeof(ThreadStatusRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, ThreadStatusReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| Deserialize(reader, &reply->record); | |
| return true; | |
| } | |
| // Modules ----------------------------------------------------------------------------------------- | |
| void WriteRequest(const ModulesRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kModules, transaction_id); | |
| writer->WriteBytes(&request, sizeof(ModulesRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, ModulesReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| Deserialize(reader, &reply->modules); | |
| return true; | |
| } | |
| // Address Space ----------------------------------------------------------------------------------- | |
| void WriteRequest(const AddressSpaceRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kAddressSpace, transaction_id); | |
| writer->WriteBytes(&request, sizeof(AddressSpaceRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, AddressSpaceReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->map); | |
| } | |
| // JobFilter -------------------------------------------------------------------------------------- | |
| void WriteRequest(const JobFilterRequest& request, uint32_t transaction_id, MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kJobFilter, transaction_id); | |
| writer->WriteUint64(request.job_koid); | |
| return Serialize(request.filters, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, JobFilterReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| return Deserialize(reader, &reply->matched_processes); | |
| } | |
| // WriteMemory ------------------------------------------------------------------------------------- | |
| void WriteRequest(const WriteMemoryRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kWriteMemory, transaction_id); | |
| writer->WriteUint64(request.process_koid); | |
| writer->WriteUint64(request.address); | |
| return Serialize(request.data, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, WriteMemoryReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return reader->ReadInt32(&reply->status); | |
| } | |
| // LoadInfoHandleTable | |
| // ------------------------------------------------------------------------------------- | |
| void WriteRequest(const LoadInfoHandleTableRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kLoadInfoHandleTable, transaction_id); | |
| writer->WriteBytes(&request, sizeof(LoadInfoHandleTableRequest)); | |
| } | |
| bool ReadReply(MessageReader* reader, LoadInfoHandleTableReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| if (!reader->ReadInt32(&reply->status)) | |
| return false; | |
| return Deserialize(reader, &reply->handles); | |
| } | |
| // UpdateGlobalSettings --------------------------------------------------------------------------- | |
| void WriteRequest(const UpdateGlobalSettingsRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kUpdateGlobalSettings, transaction_id); | |
| Serialize(request.exception_strategies, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, UpdateGlobalSettingsReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return reader->ReadInt32(&reply->status); | |
| } | |
| // ConfigAgent ------------------------------------------------------------------------------------- | |
| void WriteRequest(const ConfigAgentRequest& request, uint32_t transaction_id, | |
| MessageWriter* writer) { | |
| writer->WriteHeader(MsgHeader::Type::kConfigAgent, transaction_id); | |
| Serialize(request.actions, writer); | |
| } | |
| bool ReadReply(MessageReader* reader, ConfigAgentReply* reply, uint32_t* transaction_id) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| *transaction_id = header.transaction_id; | |
| return Deserialize(reader, &reply->results); | |
| } | |
| // Notifications ----------------------------------------------------------------------------------- | |
| bool ReadNotifyProcessExiting(MessageReader* reader, NotifyProcessExiting* process) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| if (!reader->ReadUint64(&process->process_koid)) | |
| return false; | |
| if (!reader->ReadInt64(&process->return_code)) | |
| return false; | |
| return true; | |
| } | |
| bool ReadNotifyProcessStarting(MessageReader* reader, NotifyProcessStarting* process) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| uint32_t type = UINT32_MAX; | |
| if (!reader->ReadUint32(&type) || | |
| type >= static_cast<uint32_t>(NotifyProcessStarting::Type::kLast)) { | |
| return false; | |
| } | |
| process->type = static_cast<NotifyProcessStarting::Type>(type); | |
| if (!reader->ReadUint64(&process->koid)) | |
| return false; | |
| if (!reader->ReadUint32(&process->component_id)) | |
| return false; | |
| if (!reader->ReadString(&process->name)) | |
| return false; | |
| return true; | |
| } | |
| bool ReadNotifyThread(MessageReader* reader, NotifyThread* notify) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| return Deserialize(reader, ¬ify->record); | |
| } | |
| bool ReadNotifyException(MessageReader* reader, NotifyException* notify) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| if (!Deserialize(reader, ¬ify->thread)) | |
| return false; | |
| if (!Deserialize(reader, ¬ify->type)) | |
| return false; | |
| if (!reader->ReadBytes(sizeof(notify->exception), ¬ify->exception)) | |
| return false; | |
| if (!Deserialize(reader, ¬ify->hit_breakpoints)) | |
| return false; | |
| return Deserialize(reader, ¬ify->other_affected_threads); | |
| } | |
| bool ReadNotifyModules(MessageReader* reader, NotifyModules* notify) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| if (!reader->ReadUint64(¬ify->process_koid)) | |
| return false; | |
| if (!Deserialize(reader, ¬ify->modules)) | |
| return false; | |
| return Deserialize(reader, ¬ify->stopped_thread_koids); | |
| } | |
| bool ReadNotifyIO(MessageReader* reader, NotifyIO* notify) { | |
| MsgHeader header; | |
| if (!reader->ReadHeader(&header)) | |
| return false; | |
| if (!reader->ReadUint64(¬ify->process_koid)) | |
| return false; | |
| uint32_t type; | |
| if (!reader->ReadUint32(&type) || type >= static_cast<uint32_t>(NotifyIO::Type::kLast)) { | |
| return false; | |
| } | |
| notify->type = static_cast<NotifyIO::Type>(type); | |
| if (!reader->ReadString(¬ify->data) || !reader->ReadBool(¬ify->more_data_available)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| } // namespace debug_ipc |