blob: 126ab9833137d8febce4f6d928e43627e986775c [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 "garnet/bin/zxdb/client/register.h"
#include "garnet/bin/zxdb/client/session.h"
#include "garnet/bin/zxdb/client/thread.h"
#include "gtest/gtest.h"
namespace zxdb {
using debug_ipc::RegisterCategory;
using debug_ipc::RegisterID;
namespace {
std::vector<uint8_t> CreateData(size_t length) {
std::vector<uint8_t> data;
data.reserve(length);
// So that we get the number backwards (0x0102...).
uint8_t base = length;
for (size_t i = 0; i < length; i++) {
data.emplace_back(base - i);
}
return data;
}
debug_ipc::Register CreateRegister(RegisterID id, size_t length) {
debug_ipc::Register reg;
reg.id = id;
reg.data = CreateData(length);
return reg;
}
} // namespace
TEST(Register, CorrectlyCreatesBoundaries) {
debug_ipc::Register ipc_reg = CreateRegister(RegisterID::kARMv8_x0, 1);
Register reg(ipc_reg);
ASSERT_EQ(reg.size(), 1u);
ASSERT_EQ((size_t)(reg.end() - reg.begin()), ipc_reg.data.size());
EXPECT_EQ(reg.GetValue(), 0x01u);
auto it = reg.begin();
EXPECT_EQ(*it++, ipc_reg.data[0]);
EXPECT_EQ(it, reg.end());
ipc_reg = CreateRegister(RegisterID::kARMv8_x1, 2);
reg = Register(ipc_reg);
ASSERT_EQ(reg.size(), 2u);
ASSERT_EQ((size_t)(reg.end() - reg.begin()), ipc_reg.data.size());
EXPECT_EQ(reg.GetValue(), 0x0102u);
it = reg.begin();
EXPECT_EQ(*it++, ipc_reg.data[0]);
EXPECT_EQ(*it++, ipc_reg.data[1]);
EXPECT_EQ(it, reg.end());
ipc_reg = CreateRegister(RegisterID::kARMv8_lr, 4);
reg = Register(ipc_reg);
ASSERT_EQ(reg.size(), 4u);
ASSERT_EQ((size_t)(reg.end() - reg.begin()), ipc_reg.data.size());
EXPECT_EQ(reg.GetValue(), 0x01020304u);
it = reg.begin();
EXPECT_EQ(*it++, ipc_reg.data[0]);
EXPECT_EQ(*it++, ipc_reg.data[1]);
EXPECT_EQ(*it++, ipc_reg.data[2]);
EXPECT_EQ(*it++, ipc_reg.data[3]);
EXPECT_EQ(it, reg.end());
ipc_reg = CreateRegister(RegisterID::kARMv8_cpsr, 8);
reg = Register(ipc_reg);
ASSERT_EQ(reg.size(), 8u);
ASSERT_EQ((size_t)(reg.end() - reg.begin()), ipc_reg.data.size());
EXPECT_EQ(reg.GetValue(), 0x0102030405060708u);
it = reg.begin();
EXPECT_EQ(*it++, ipc_reg.data[0]);
EXPECT_EQ(*it++, ipc_reg.data[1]);
EXPECT_EQ(*it++, ipc_reg.data[2]);
EXPECT_EQ(*it++, ipc_reg.data[3]);
EXPECT_EQ(*it++, ipc_reg.data[4]);
EXPECT_EQ(*it++, ipc_reg.data[5]);
EXPECT_EQ(*it++, ipc_reg.data[6]);
EXPECT_EQ(*it++, ipc_reg.data[7]);
EXPECT_EQ(it, reg.end());
ipc_reg = CreateRegister(RegisterID::kARMv8_x11, 16);
reg = Register(ipc_reg);
ASSERT_EQ(reg.size(), 16u);
ASSERT_EQ((size_t)(reg.end() - reg.begin()), ipc_reg.data.size());
it = reg.begin();
EXPECT_EQ(*it++, ipc_reg.data[0]);
EXPECT_EQ(*it++, ipc_reg.data[1]);
EXPECT_EQ(*it++, ipc_reg.data[2]);
EXPECT_EQ(*it++, ipc_reg.data[3]);
EXPECT_EQ(*it++, ipc_reg.data[4]);
EXPECT_EQ(*it++, ipc_reg.data[5]);
EXPECT_EQ(*it++, ipc_reg.data[6]);
EXPECT_EQ(*it++, ipc_reg.data[7]);
EXPECT_EQ(*it++, ipc_reg.data[8]);
EXPECT_EQ(*it++, ipc_reg.data[9]);
EXPECT_EQ(*it++, ipc_reg.data[10]);
EXPECT_EQ(*it++, ipc_reg.data[11]);
EXPECT_EQ(*it++, ipc_reg.data[12]);
EXPECT_EQ(*it++, ipc_reg.data[13]);
EXPECT_EQ(*it++, ipc_reg.data[14]);
EXPECT_EQ(*it++, ipc_reg.data[15]);
EXPECT_EQ(it, reg.end());
}
TEST(RegisterSet, RegisterMap) {
std::vector<RegisterCategory> categories;
RegisterCategory cat1;
cat1.type = RegisterCategory::Type::kGeneral;
cat1.registers.push_back(CreateRegister(RegisterID::kARMv8_lr, 2));
cat1.registers.push_back(CreateRegister(RegisterID::kARMv8_pc, 4));
categories.push_back(cat1);
// Sanity check
ASSERT_EQ(*(uint8_t*)&(cat1.registers[0].data[0]), 0x02u);
ASSERT_EQ(*(uint16_t*)&(cat1.registers[1].data[0]), 0x0304u);
RegisterCategory cat2;
cat2.type = RegisterCategory::Type::kVector;
cat2.registers.push_back(CreateRegister(RegisterID::kARMv8_x0, 2));
cat2.registers.push_back(CreateRegister(RegisterID::kARMv8_x1, 4));
categories.push_back(cat2);
RegisterSet set(debug_ipc::Arch::kArm64, categories);
const Register* reg = set[RegisterID::kARMv8_lr];
ASSERT_TRUE(reg);
EXPECT_EQ(reg->id(), RegisterID::kARMv8_lr);
EXPECT_EQ(reg->GetValue(), 0x0102u);
reg = set[RegisterID::kARMv8_x1];
ASSERT_TRUE(reg);
EXPECT_EQ(reg->id(), RegisterID::kARMv8_x1);
EXPECT_EQ(reg->GetValue(), 0x01020304u);
}
TEST(RegisterSet, DWARFMappings) {
std::vector<RegisterCategory> categories;
RegisterCategory cat1;
cat1.type = RegisterCategory::Type::kGeneral;
cat1.registers.push_back(CreateRegister(RegisterID::kARMv8_sp, 2));
cat1.registers.push_back(CreateRegister(RegisterID::kARMv8_cpsr, 4));
categories.push_back(cat1);
// Sanity check
ASSERT_EQ(*(uint8_t*)&(cat1.registers[0].data[0]), 0x02u);
ASSERT_EQ(*(uint16_t*)&(cat1.registers[1].data[0]), 0x0304u);
RegisterCategory cat2;
cat2.type = RegisterCategory::Type::kVector;
cat2.registers.push_back(CreateRegister(RegisterID::kARMv8_x0, 2));
cat2.registers.push_back(CreateRegister(RegisterID::kARMv8_x1, 4));
categories.push_back(cat2);
RegisterSet set(debug_ipc::Arch::kArm64, categories);
const Register* reg = set.GetRegisterFromDWARF(1);
ASSERT_TRUE(reg);
EXPECT_EQ(reg->id(), RegisterID::kARMv8_x1);
EXPECT_EQ(reg->GetValue(), 0x01020304u);
uint64_t val;
ASSERT_TRUE(set.GetRegisterValueFromDWARF(1, &val));
EXPECT_EQ(val, 0x01020304u);
reg = set.GetRegisterFromDWARF(32);
ASSERT_TRUE(reg);
EXPECT_EQ(reg->id(), RegisterID::kARMv8_sp);
EXPECT_EQ(reg->GetValue(), 0x0102u);
ASSERT_TRUE(set.GetRegisterValueFromDWARF(32, &val));
EXPECT_EQ(val, 0x0102u);
reg = set.GetRegisterFromDWARF(10000);
EXPECT_FALSE(reg);
// Wrong architecture
set.set_arch(debug_ipc::Arch::kX64);
for (size_t i = 0; i < 40; i++)
ASSERT_FALSE(set.GetRegisterFromDWARF(i));
}
} // namespace zxdb