blob: 6384e9fee2abc2e5919ac48d81e4edac61bfc08f [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 <filesystem>
#include <map>
#include <gtest/gtest.h>
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/process_observer.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/system_observer.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/client/thread_observer.h"
#include "src/developer/debug/zxdb/common/host_util.h"
#include "src/developer/debug/zxdb/common/test_with_loop.h"
namespace zxdb {
class MinidumpTest : public TestWithLoop, public ThreadObserver, public SystemObserver {
public:
MinidumpTest();
virtual ~MinidumpTest();
Session& session() { return *session_; }
debug_ipc::ExceptionType last_hit() { return last_hit_; }
Err TryOpen(const std::string& filename);
template <typename RequestType, typename ReplyType>
void DoRequest(RequestType request, ReplyType& reply, Err& err,
void (RemoteAPI::*handler)(const RequestType&,
fit::callback<void(const Err&, ReplyType)>));
// ThreadObserver implementation.
void OnThreadStopped(Thread*, const StopInfo& info) override;
private:
debug_ipc::ExceptionType last_hit_ = debug_ipc::ExceptionType::kNone;
std::unique_ptr<Session> session_;
};
MinidumpTest::MinidumpTest() {
session_ = std::make_unique<Session>();
session().thread_observers().AddObserver(this);
}
MinidumpTest::~MinidumpTest() { session().thread_observers().RemoveObserver(this); }
Err MinidumpTest::TryOpen(const std::string& filename) {
static auto data_dir = std::filesystem::path(GetSelfPath()).parent_path() / "test_data" / "zxdb";
Err err;
auto path = (data_dir / filename).string();
session().OpenMinidump(path, [&err](const Err& got) { err = got; });
loop().RunUntilNoTasks();
return err;
}
template <typename RequestType, typename ReplyType>
void MinidumpTest::DoRequest(
RequestType request, ReplyType& reply, Err& err,
void (RemoteAPI::*handler)(const RequestType&, fit::callback<void(const Err&, ReplyType)>)) {
(session().remote_api()->*handler)(request, [&reply, &err](const Err& e, ReplyType r) {
err = e;
reply = r;
});
loop().RunUntilNoTasks();
}
void MinidumpTest::OnThreadStopped(Thread*, const StopInfo& info) {
last_hit_ = info.exception_type;
}
template <typename Data>
std::vector<uint8_t> AsData(Data d) {
std::vector<uint8_t> ret;
ret.resize(sizeof(d));
*reinterpret_cast<Data*>(ret.data()) = d;
return ret;
}
#define EXPECT_ZXDB_SUCCESS(e_) \
({ \
Err e = e_; \
EXPECT_FALSE(e.has_error()) << e.msg(); \
})
#define ASSERT_ZXDB_SUCCESS(e_) \
({ \
Err e = e_; \
ASSERT_FALSE(e.has_error()) << e.msg(); \
})
constexpr uint32_t kTestExampleMinidumpKOID = 656254UL;
constexpr uint32_t kTestExampleMinidumpNewCvRecordKOID = 12843UL;
constexpr uint32_t kTestExampleMinidumpThreadKOID = 671806UL;
constexpr uint64_t kTestExampleMinidumpStackAddr = 0x37f880947000;
constexpr uint32_t kTestExampleMinidumpStackSize = 0x40000;
constexpr uint32_t kTestExampleMinidumpWithAspaceKOID = 9462UL;
TEST_F(MinidumpTest, Load) {
EXPECT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_NE(nullptr, session().system().ProcessFromKoid(kTestExampleMinidumpKOID));
}
TEST_F(MinidumpTest, ProcessTreeRecord) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::ProcessTreeReply reply;
DoRequest(debug_ipc::ProcessTreeRequest(), reply, err, &RemoteAPI::ProcessTree);
ASSERT_ZXDB_SUCCESS(err);
auto record = reply.root;
EXPECT_EQ(debug_ipc::ProcessTreeRecord::Type::kProcess, record.type);
EXPECT_EQ("scenic", record.name);
EXPECT_EQ(kTestExampleMinidumpKOID, record.koid);
EXPECT_EQ(0UL, record.children.size());
}
TEST_F(MinidumpTest, AttachDetach) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::AttachRequest request;
debug_ipc::AttachReply reply;
request.koid = kTestExampleMinidumpKOID;
DoRequest(request, reply, err, &RemoteAPI::Attach);
ASSERT_ZXDB_SUCCESS(err);
EXPECT_TRUE(reply.status.ok());
EXPECT_EQ("scenic", reply.name);
debug_ipc::DetachRequest detach_request;
debug_ipc::DetachReply detach_reply;
detach_request.koid = kTestExampleMinidumpKOID;
DoRequest(detach_request, detach_reply, err, &RemoteAPI::Detach);
ASSERT_ZXDB_SUCCESS(err);
EXPECT_TRUE(detach_reply.status.ok());
/* Try to detach when not attached */
DoRequest(detach_request, detach_reply, err, &RemoteAPI::Detach);
ASSERT_ZXDB_SUCCESS(err);
EXPECT_TRUE(detach_reply.status.has_error());
}
TEST_F(MinidumpTest, AttachFail) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::AttachRequest request;
debug_ipc::AttachReply reply;
request.koid = 42;
DoRequest(request, reply, err, &RemoteAPI::Attach);
ASSERT_ZXDB_SUCCESS(err);
EXPECT_TRUE(reply.status.has_error());
}
TEST_F(MinidumpTest, Threads) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::ThreadsRequest request;
debug_ipc::ThreadsReply reply;
request.process_koid = kTestExampleMinidumpKOID;
DoRequest(request, reply, err, &RemoteAPI::Threads);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_LT(0UL, reply.threads.size());
EXPECT_EQ(1UL, reply.threads.size());
auto& thread = reply.threads[0];
EXPECT_EQ(kTestExampleMinidumpThreadKOID, thread.id.thread);
EXPECT_EQ("", thread.name);
EXPECT_EQ(debug_ipc::ThreadRecord::State::kCoreDump, thread.state);
}
TEST_F(MinidumpTest, Registers) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::ReadRegistersRequest request;
debug_ipc::ReadRegistersReply reply;
request.id.process = kTestExampleMinidumpKOID;
request.id.thread = kTestExampleMinidumpThreadKOID;
request.categories = {
debug::RegisterCategory::kGeneral,
debug::RegisterCategory::kFloatingPoint,
debug::RegisterCategory::kVector,
debug::RegisterCategory::kDebug,
};
DoRequest(request, reply, err, &RemoteAPI::ReadRegisters);
ASSERT_ZXDB_SUCCESS(err);
std::map<debug::RegisterID, std::vector<uint8_t>> got;
for (const auto& reg : reply.registers)
got[reg.id] = reg.data;
std::vector<uint8_t> zero_short = {0, 0};
std::vector<uint8_t> zero_128 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
EXPECT_EQ(AsData(0x83UL), got[debug::RegisterID::kX64_rax]);
EXPECT_EQ(AsData(0x2FE150062100UL), got[debug::RegisterID::kX64_rbx]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_rcx]);
EXPECT_EQ(AsData(0x4DC647A67264UL), got[debug::RegisterID::kX64_rdx]);
EXPECT_EQ(AsData(0x5283B9A79945UL), got[debug::RegisterID::kX64_rsi]);
EXPECT_EQ(AsData(0x4DC647A671D8UL), got[debug::RegisterID::kX64_rdi]);
EXPECT_EQ(AsData(0x37F880986D70UL), got[debug::RegisterID::kX64_rbp]);
EXPECT_EQ(AsData(0x37F880986D48UL), got[debug::RegisterID::kX64_rsp]);
EXPECT_EQ(AsData(0x1UL), got[debug::RegisterID::kX64_r8]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_r9]);
EXPECT_EQ(AsData(0x4DC647A671D8UL), got[debug::RegisterID::kX64_r10]);
EXPECT_EQ(AsData(0x83UL), got[debug::RegisterID::kX64_r11]);
EXPECT_EQ(AsData(0x2FE150077070UL), got[debug::RegisterID::kX64_r12]);
EXPECT_EQ(AsData(0x3F4C20970A28UL), got[debug::RegisterID::kX64_r13]);
EXPECT_EQ(AsData(0xFFFFFFF5UL), got[debug::RegisterID::kX64_r14]);
EXPECT_EQ(AsData(0x2FE150062138UL), got[debug::RegisterID::kX64_r15]);
EXPECT_EQ(AsData(0x4DC6479A5B1EUL), got[debug::RegisterID::kX64_rip]);
EXPECT_EQ(AsData(0x10206UL), got[debug::RegisterID::kX64_rflags]);
EXPECT_EQ(zero_short, got[debug::RegisterID::kX64_fcw]);
EXPECT_EQ(zero_short, got[debug::RegisterID::kX64_fsw]);
EXPECT_EQ(AsData('\0'), got[debug::RegisterID::kX64_ftw]);
EXPECT_EQ(zero_short, got[debug::RegisterID::kX64_fop]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_fip]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_fdp]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st0]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st1]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st2]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st3]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st4]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st5]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st6]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_st7]);
EXPECT_EQ(AsData(0x0U), got[debug::RegisterID::kX64_mxcsr]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm0]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm1]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm2]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm3]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm4]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm5]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm6]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm7]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm8]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm9]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm10]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm11]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm12]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm13]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm14]);
EXPECT_EQ(zero_128, got[debug::RegisterID::kX64_xmm15]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr0]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr1]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr2]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr3]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr6]);
EXPECT_EQ(AsData(0x0UL), got[debug::RegisterID::kX64_dr7]);
}
TEST_F(MinidumpTest, Modules) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump_new_cvrecord.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kSoftwareBreakpoint, last_hit());
Err err;
debug_ipc::ModulesRequest request;
debug_ipc::ModulesReply reply;
request.process_koid = kTestExampleMinidumpNewCvRecordKOID;
DoRequest(request, reply, err, &RemoteAPI::Modules);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(11UL, reply.modules.size());
EXPECT_EQ("<_>", reply.modules[0].name);
EXPECT_EQ(0xdb9f3c9ee000UL, reply.modules[0].base);
EXPECT_EQ("bbe04258f9aee727", reply.modules[0].build_id);
EXPECT_EQ("libfxl_logging.so", reply.modules[1].name);
EXPECT_EQ(0x88fde9aa2000UL, reply.modules[1].base);
EXPECT_EQ("6990f44a2b829d04", reply.modules[1].build_id);
EXPECT_EQ("libfdio.so", reply.modules[2].name);
EXPECT_EQ(0xf84d6c82a000UL, reply.modules[2].base);
EXPECT_EQ("47521571b0824b71ddc745a01d7a0352539dd803", reply.modules[2].build_id);
EXPECT_EQ("libzircon.so", reply.modules[3].name);
EXPECT_EQ(0xe0a9f4b35000UL, reply.modules[3].base);
EXPECT_EQ("b0cb33d5e533ba8f6dcb73cc9c158cb8247f0263", reply.modules[3].build_id);
EXPECT_EQ("libasync-default.so", reply.modules[4].name);
EXPECT_EQ(0xacc33bf02000UL, reply.modules[4].base);
EXPECT_EQ("94dee2c0e27202b524255e07f7a9a9e5e282bdb0", reply.modules[4].build_id);
EXPECT_EQ("libsyslog.so", reply.modules[5].name);
EXPECT_EQ(0xf4e730afa000UL, reply.modules[5].base);
EXPECT_EQ("d9ea935594739f99127a67a1816b4afa2d2fd486", reply.modules[5].build_id);
EXPECT_EQ("libtrace-engine.so", reply.modules[6].name);
EXPECT_EQ(0xe0f0f0035000UL, reply.modules[6].base);
EXPECT_EQ("b1f55f8a9a49d4bd5040c17b69b3e795f5e9ee84", reply.modules[6].build_id);
EXPECT_EQ("libc++.so.2", reply.modules[7].name);
EXPECT_EQ(0xd9512a2b0000UL, reply.modules[7].base);
EXPECT_EQ("e2805c6c256fe3bc", reply.modules[7].build_id);
EXPECT_EQ("libc.so", reply.modules[8].name);
EXPECT_EQ(0xd339f6596000UL, reply.modules[8].base);
EXPECT_EQ("c92393053718b514a70777d18c4c0cc415d544b0", reply.modules[8].build_id);
EXPECT_EQ("libc++abi.so.1", reply.modules[9].name);
EXPECT_EQ(0xbcd34b71000UL, reply.modules[9].base);
EXPECT_EQ("91766972c93894f3", reply.modules[9].build_id);
EXPECT_EQ("libunwind.so.1", reply.modules[10].name);
EXPECT_EQ(0xbcc263255000UL, reply.modules[10].base);
EXPECT_EQ("3a4ebe2ee4046112", reply.modules[10].build_id);
}
TEST_F(MinidumpTest, AddressSpace) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump_with_aspace.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kPageFault, last_hit());
Err err;
debug_ipc::AddressSpaceRequest request;
debug_ipc::AddressSpaceReply reply;
request.process_koid = kTestExampleMinidumpWithAspaceKOID;
DoRequest(request, reply, err, &RemoteAPI::AddressSpace);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(18UL, reply.map.size());
EXPECT_EQ("", reply.map[0].name);
EXPECT_EQ(0x12766084a000UL, reply.map[0].base);
EXPECT_EQ(262144UL, reply.map[0].size);
EXPECT_EQ(0UL, reply.map[0].depth);
EXPECT_EQ("", reply.map[1].name);
EXPECT_EQ(0x1a531e112000UL, reply.map[1].base);
EXPECT_EQ(262144UL, reply.map[1].size);
EXPECT_EQ(0UL, reply.map[1].depth);
EXPECT_EQ("", reply.map[2].name);
EXPECT_EQ(0x38b28bf10000UL, reply.map[2].base);
EXPECT_EQ(4096UL, reply.map[2].size);
EXPECT_EQ(0UL, reply.map[2].depth);
EXPECT_EQ("", reply.map[3].name);
EXPECT_EQ(0x41ea65c3d000UL, reply.map[3].base);
EXPECT_EQ(4096UL, reply.map[3].size);
EXPECT_EQ(0UL, reply.map[3].depth);
EXPECT_EQ("", reply.map[4].name);
EXPECT_EQ(0x44b8c3369000UL, reply.map[4].base);
EXPECT_EQ(2097152UL, reply.map[4].size);
EXPECT_EQ(0UL, reply.map[4].depth);
EXPECT_EQ("", reply.map[5].name);
EXPECT_EQ(0x45226ca65000UL, reply.map[5].base);
EXPECT_EQ(2097152UL, reply.map[5].size);
EXPECT_EQ(0UL, reply.map[5].depth);
EXPECT_EQ("", reply.map[6].name);
EXPECT_EQ(0x513737c43000UL, reply.map[6].base);
EXPECT_EQ(28672UL, reply.map[6].size);
EXPECT_EQ(0UL, reply.map[6].depth);
EXPECT_EQ("", reply.map[7].name);
EXPECT_EQ(0x513737c4a000UL, reply.map[7].base);
EXPECT_EQ(4096UL, reply.map[7].size);
EXPECT_EQ(0UL, reply.map[7].depth);
EXPECT_EQ("", reply.map[8].name);
EXPECT_EQ(0x5e008a746000UL, reply.map[8].base);
EXPECT_EQ(139264UL, reply.map[8].size);
EXPECT_EQ(0UL, reply.map[8].depth);
EXPECT_EQ("", reply.map[9].name);
EXPECT_EQ(0x5e008a768000UL, reply.map[9].base);
EXPECT_EQ(8192UL, reply.map[9].size);
EXPECT_EQ(0UL, reply.map[9].depth);
EXPECT_EQ("", reply.map[10].name);
EXPECT_EQ(0x5e008a76a000UL, reply.map[10].base);
EXPECT_EQ(12288UL, reply.map[10].size);
EXPECT_EQ(0UL, reply.map[10].depth);
EXPECT_EQ("", reply.map[11].name);
EXPECT_EQ(0x652d9b6bb000UL, reply.map[11].base);
EXPECT_EQ(831488UL, reply.map[11].size);
EXPECT_EQ(0UL, reply.map[11].depth);
EXPECT_EQ("", reply.map[12].name);
EXPECT_EQ(0x652d9b787000UL, reply.map[12].base);
EXPECT_EQ(12288UL, reply.map[12].size);
EXPECT_EQ(0UL, reply.map[12].depth);
EXPECT_EQ("", reply.map[13].name);
EXPECT_EQ(0x652d9b78a000UL, reply.map[13].base);
EXPECT_EQ(12288UL, reply.map[13].size);
EXPECT_EQ(0UL, reply.map[13].depth);
EXPECT_EQ("", reply.map[14].name);
EXPECT_EQ(0x7328c9333000UL, reply.map[14].base);
EXPECT_EQ(8192UL, reply.map[14].size);
EXPECT_EQ(0UL, reply.map[14].depth);
EXPECT_EQ("", reply.map[15].name);
EXPECT_EQ(0x7328c9335000UL, reply.map[15].base);
EXPECT_EQ(4096UL, reply.map[15].size);
EXPECT_EQ(0UL, reply.map[15].depth);
EXPECT_EQ("", reply.map[16].name);
EXPECT_EQ(0x7328c9336000UL, reply.map[16].base);
EXPECT_EQ(4096UL, reply.map[16].size);
EXPECT_EQ(0UL, reply.map[16].depth);
EXPECT_EQ("", reply.map[17].name);
EXPECT_EQ(0x7c1d710c8000UL, reply.map[17].base);
EXPECT_EQ(4096UL, reply.map[17].size);
EXPECT_EQ(0UL, reply.map[17].depth);
}
TEST_F(MinidumpTest, ReadMemory) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::ReadMemoryRequest request;
debug_ipc::ReadMemoryReply reply;
request.process_koid = kTestExampleMinidumpKOID;
request.address = kTestExampleMinidumpStackAddr;
request.size = kTestExampleMinidumpStackSize;
DoRequest(request, reply, err, &RemoteAPI::ReadMemory);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(1u, reply.blocks.size());
const auto& block = reply.blocks.back();
EXPECT_EQ(kTestExampleMinidumpStackAddr, block.address);
EXPECT_EQ(kTestExampleMinidumpStackSize, block.size);
ASSERT_TRUE(block.valid);
ASSERT_EQ(block.size, block.data.size());
EXPECT_EQ(0u, block.data[0]);
EXPECT_EQ(0u, block.data[10]);
EXPECT_EQ(0u, block.data[100]);
EXPECT_EQ(0u, block.data[1000]);
EXPECT_EQ(0u, block.data[10000]);
EXPECT_EQ(0u, block.data[100000]);
EXPECT_EQ(2u, block.data[260400]);
EXPECT_EQ(0u, block.data[260401]);
EXPECT_EQ(0u, block.data[260402]);
EXPECT_EQ(0u, block.data[260403]);
EXPECT_EQ(0u, block.data[260404]);
EXPECT_EQ(240u, block.data[260410]);
EXPECT_EQ(251u, block.data[260420]);
EXPECT_EQ(0u, block.data[260430]);
EXPECT_EQ(1u, block.data[260440]);
}
TEST_F(MinidumpTest, ReadMemory_Empty) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
Err err;
debug_ipc::ReadMemoryRequest request;
debug_ipc::ReadMemoryReply reply;
request.process_koid = kTestExampleMinidumpKOID;
request.address = kTestExampleMinidumpStackAddr;
request.size = 0;
DoRequest(request, reply, err, &RemoteAPI::ReadMemory);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(0u, reply.blocks.size());
}
TEST_F(MinidumpTest, ReadMemory_Short) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
const uint32_t kOverReadSize = kTestExampleMinidumpStackSize + 36;
Err err;
debug_ipc::ReadMemoryRequest request;
debug_ipc::ReadMemoryReply reply;
request.process_koid = kTestExampleMinidumpKOID;
request.address = kTestExampleMinidumpStackAddr;
request.size = kOverReadSize;
DoRequest(request, reply, err, &RemoteAPI::ReadMemory);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(2u, reply.blocks.size());
const auto& block = reply.blocks.front();
EXPECT_EQ(kTestExampleMinidumpStackAddr, block.address);
EXPECT_EQ(kTestExampleMinidumpStackSize, block.size);
ASSERT_TRUE(block.valid);
ASSERT_EQ(block.size, block.data.size());
const auto& bad_block = reply.blocks.back();
EXPECT_EQ(kTestExampleMinidumpStackAddr + kTestExampleMinidumpStackSize, bad_block.address);
EXPECT_EQ(kOverReadSize - kTestExampleMinidumpStackSize, bad_block.size);
ASSERT_FALSE(bad_block.valid);
ASSERT_EQ(0u, bad_block.data.size());
}
TEST_F(MinidumpTest, SysInfo) {
ASSERT_ZXDB_SUCCESS(TryOpen("test_example_minidump.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kUndefinedInstruction, last_hit());
Err err;
debug_ipc::SysInfoRequest request;
debug_ipc::SysInfoReply reply;
DoRequest(request, reply, err, &RemoteAPI::SysInfo);
ASSERT_ZXDB_SUCCESS(err);
EXPECT_EQ("Zircon prerelease git-50fbb1100548dc716d72abd4024461a85f5c8eb8 x86_64", reply.version);
EXPECT_EQ(4u, reply.num_cpus);
EXPECT_EQ(0u, reply.memory_mb);
EXPECT_EQ(0u, reply.hw_breakpoint_count);
EXPECT_EQ(0u, reply.hw_watchpoint_count);
}
TEST_F(MinidumpTest, Backtrace) {
const uint64_t kProcessKOID = 10363;
const uint64_t kThreadKOID = 65232;
auto core_dir = std::filesystem::path(GetSelfPath()).parent_path() / "test_data" / "zxdb" /
"sample_core" / "core";
session().system().settings().SetList(ClientSettings::System::kSymbolPaths, {core_dir});
ASSERT_ZXDB_SUCCESS(TryOpen(core_dir / "core.dmp"));
EXPECT_EQ(debug_ipc::ExceptionType::kGeneral, last_hit());
Err err;
debug_ipc::ThreadStatusRequest request;
debug_ipc::ThreadStatusReply reply;
request.id = {.process = kProcessKOID, .thread = kThreadKOID};
DoRequest(request, reply, err, &RemoteAPI::ThreadStatus);
ASSERT_ZXDB_SUCCESS(err);
ASSERT_EQ(3u, reply.record.frames.size());
EXPECT_EQ(0x6df7cb8a10a3u, reply.record.frames[0].ip);
EXPECT_EQ(0x6df7cb8a1063u, reply.record.frames[1].ip);
EXPECT_EQ(0x575953094968u, reply.record.frames[2].ip);
}
} // namespace zxdb