blob: fd3f6476c5740224bafadc3f29628b89c6f565c8 [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.
#ifndef SRC_DEVELOPER_DEBUG_SHARED_REGISTER_INFO_H_
#define SRC_DEVELOPER_DEBUG_SHARED_REGISTER_INFO_H_
#include <stdint.h>
#include <optional>
#include <string>
#include "src/developer/debug/shared/arch.h"
#include "src/developer/debug/shared/register_id.h"
#include "src/developer/debug/shared/register_value.h"
#include "src/lib/containers/cpp/array_view.h"
// Holds constant description values for all the register data for all the
// supported architectures.
// The enum definitions mirror the structs defined in the debug information
// for zircon (see zircon/system/public/zircon/syscalls/debug.h).
namespace debug {
enum class SpecialRegisterType {
kNone,
kIP, // Instruction Pointer
kSP, // Stack Pointer
kTP // Thread Pointer
};
// Note that we separate out "void" addresses and "word" addresses so the debugger frontend can
// assign types to register values when appropriate.
enum class RegisterFormat {
kGeneral, // General register that might hold any integer or an address.
kFloat, // Floating-point number.
kVector, // Vector registers that hold multiple values.
kVoidAddress, // Registers that point to void*.
kWordAddress, // Registers that point to uint64_t.
kSpecial, // Things like flag registers that neither hold addresses nor numbers.
};
struct RegisterInfo {
RegisterID id;
std::string name;
Arch arch;
// Some registers refer to a subset of another register, e.g. "al" (low byte of "rax") on X86 or
// "w0" (low 32-bits of "x0") on ARM. This ID will be the larger canonical ID. For registers that
// are themselves canonical, this will be the same as "id".
RegisterID canonical_id;
// When asking for a name-to-register mapping, sometimes they map to a part of a register. For
// example "al" on x64 is the low 8 bits of rax. These will both be 0 for the "canonical" register
// record.
//
// Currently these both must be a multiple of 8 for GetRegisterData() below.
int bits = 0;
int shift = 0; // How many bits shited to the right is the low bit of the value.
// DWARF register ID if there is one.
static constexpr uint32_t kNoDwarfId = 0xffffffff;
uint32_t dwarf_id = kNoDwarfId;
RegisterFormat format = RegisterFormat::kGeneral;
};
const RegisterInfo* InfoForRegister(RegisterID id);
const RegisterInfo* InfoForRegister(Arch arch, const std::string& name);
const char* RegisterIDToString(RegisterID);
RegisterID StringToRegisterID(const std::string&);
// Returns the register ID for the given special register.
RegisterID GetSpecialRegisterID(Arch, SpecialRegisterType);
// Returns the special register type for a register ID.
SpecialRegisterType GetSpecialRegisterType(RegisterID id);
// Converts the ID number used by DWARF to our register info. Returns null if not found.
const RegisterInfo* DWARFToRegisterInfo(Arch, uint32_t dwarf_reg_id);
// Find out what arch a register ID belongs to
Arch GetArchForRegisterID(RegisterID);
// Returns true if the given register is a "general" register. General
// registers are sent as part of the unwind frame data. Other registers must
// be requested specially from the target.
bool IsGeneralRegister(RegisterID);
// Gets the data for the given register from the array.
//
// This does two things. It searches for either the requested register or the canonical register.
// If it's a different canonical register (like you're asking for the a 32 bits pseudoregister out
// of a 64 bit register), the relevant bits will be extracted.
//
// If found, the return value will be the range of data within the data owned by |regs|
// corresponding to the requested register. If the source data is truncated, the result will be
// truncated also so it may have less data than expected.
//
// If the register is not found, the returned view will be empty.
containers::array_view<uint8_t> GetRegisterData(const std::vector<RegisterValue>& regs,
RegisterID id);
// These ranges permit to make transformation from registerID to category and
// make some formal verifications.
constexpr uint32_t kARMv8GeneralBegin = 1000;
constexpr uint32_t kARMv8GeneralEnd = 1099;
constexpr uint32_t kARMv8VectorBegin = 1100;
constexpr uint32_t kARMv8VectorEnd = 1299;
constexpr uint32_t kARMv8DebugBegin = 1300;
constexpr uint32_t kARMv8DebugEnd = 1399;
constexpr uint32_t kX64GeneralBegin = 2000;
constexpr uint32_t kX64GeneralEnd = 2099;
constexpr uint32_t kX64FPBegin = 2100;
constexpr uint32_t kX64FPEnd = 2199;
constexpr uint32_t kX64VectorBegin = 2200;
constexpr uint32_t kX64VectorEnd = 2599;
constexpr uint32_t kX64DebugBegin = 2600;
constexpr uint32_t kX64DebugEnd = 2699;
// Categories --------------------------------------------------------------------------------------
enum class RegisterCategory : uint32_t {
kNone = 0,
kGeneral,
kFloatingPoint,
kVector,
kDebug,
kLast, // Not an element, for marking the max size.
};
const char* RegisterCategoryToString(RegisterCategory);
RegisterCategory RegisterIDToCategory(RegisterID);
} // namespace debug
#endif // SRC_DEVELOPER_DEBUG_SHARED_REGISTER_INFO_H_