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