185 lines · cpp
1//===-- RegisterContextLinux_x86_64.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===---------------------------------------------------------------------===//8 9#include "RegisterContextLinux_x86_64.h"10#include "RegisterContextLinux_i386.h"11#include "RegisterContextPOSIX_x86.h"12#include <vector>13 14using namespace lldb_private;15using namespace lldb;16 17typedef struct _GPR {18 uint64_t r15;19 uint64_t r14;20 uint64_t r13;21 uint64_t r12;22 uint64_t rbp;23 uint64_t rbx;24 uint64_t r11;25 uint64_t r10;26 uint64_t r9;27 uint64_t r8;28 uint64_t rax;29 uint64_t rcx;30 uint64_t rdx;31 uint64_t rsi;32 uint64_t rdi;33 uint64_t orig_rax;34 uint64_t rip;35 uint64_t cs;36 uint64_t rflags;37 uint64_t rsp;38 uint64_t ss;39 uint64_t fs_base;40 uint64_t gs_base;41 uint64_t ds;42 uint64_t es;43 uint64_t fs;44 uint64_t gs;45} GPR;46 47struct DBG {48 uint64_t dr[8];49};50 51struct UserArea {52 GPR gpr; // General purpose registers.53 int32_t fpvalid; // True if FPU is being used.54 int32_t pad0;55 FXSAVE fpr; // General purpose floating point registers (see FPR for extended56 // register sets).57 uint64_t tsize; // Text segment size.58 uint64_t dsize; // Data segment size.59 uint64_t ssize; // Stack segment size.60 uint64_t start_code; // VM address of text.61 uint64_t start_stack; // VM address of stack bottom (top in rsp).62 int64_t signal; // Signal causing core dump.63 int32_t reserved; // Unused.64 int32_t pad1;65 uint64_t ar0; // Location of GPR's.66 FXSAVE *fpstate; // Location of FPR's.67 uint64_t magic; // Identifier for core dumps.68 char u_comm[32]; // Command causing core dump.69 DBG dbg; // Debug registers.70 uint64_t error_code; // CPU error code.71 uint64_t fault_address; // Control register CR3.72};73 74#define DR_OFFSET(reg_index) \75 (LLVM_EXTENSION offsetof(UserArea, dbg) + \76 LLVM_EXTENSION offsetof(DBG, dr[reg_index]))77 78// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64_with_base79// structure.80#define DECLARE_REGISTER_INFOS_X86_64_STRUCT81#include "RegisterInfos_x86_64_with_base.h"82#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT83 84static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {85 static std::vector<lldb_private::RegisterInfo> g_register_infos;86 return g_register_infos;87}88 89static const RegisterInfo *90GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {91 std::vector<lldb_private::RegisterInfo> &g_register_infos =92 GetPrivateRegisterInfoVector();93 94 // Allocate RegisterInfo only once95 if (g_register_infos.empty()) {96 // Copy the register information from base class97 std::unique_ptr<RegisterContextLinux_i386> reg_interface(98 new RegisterContextLinux_i386(arch));99 const RegisterInfo *base_info = reg_interface->GetRegisterInfo();100 g_register_infos.insert(g_register_infos.end(), &base_info[0],101 &base_info[k_num_registers_i386]);102 103// Include RegisterInfos_x86_64 to update the g_register_infos structure104// with x86_64 offsets.105#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS106#include "RegisterInfos_x86_64_with_base.h"107#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS108 }109 110 return &g_register_infos[0];111}112 113static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {114 switch (target_arch.GetMachine()) {115 case llvm::Triple::x86:116 return GetRegisterInfo_i386(target_arch);117 case llvm::Triple::x86_64:118 return g_register_infos_x86_64_with_base;119 default:120 assert(false && "Unhandled target architecture.");121 return nullptr;122 }123}124 125static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {126 switch (target_arch.GetMachine()) {127 case llvm::Triple::x86: {128 assert(!GetPrivateRegisterInfoVector().empty() &&129 "i386 register info not yet filled.");130 return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size());131 }132 case llvm::Triple::x86_64:133 return static_cast<uint32_t>(sizeof(g_register_infos_x86_64_with_base) /134 sizeof(g_register_infos_x86_64_with_base[0]));135 default:136 assert(false && "Unhandled target architecture.");137 return 0;138 }139}140 141static uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch) {142 switch (target_arch.GetMachine()) {143 case llvm::Triple::x86:144 return static_cast<uint32_t>(k_num_user_registers_i386);145 case llvm::Triple::x86_64:146 return static_cast<uint32_t>(x86_64_with_base::k_num_user_registers);147 default:148 assert(false && "Unhandled target architecture.");149 return 0;150 }151}152 153RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(154 const ArchSpec &target_arch)155 : lldb_private::RegisterContextLinux_x86(156 target_arch,157 {"orig_rax",158 nullptr,159 sizeof(((GPR *)nullptr)->orig_rax),160 (LLVM_EXTENSION offsetof(GPR, orig_rax)),161 eEncodingUint,162 eFormatHex,163 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,164 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},165 nullptr,166 nullptr,167 nullptr}),168 m_register_info_p(GetRegisterInfoPtr(target_arch)),169 m_register_info_count(GetRegisterInfoCount(target_arch)),170 m_user_register_count(GetUserRegisterInfoCount(target_arch)) {}171 172size_t RegisterContextLinux_x86_64::GetGPRSizeStatic() { return sizeof(GPR); }173 174const RegisterInfo *RegisterContextLinux_x86_64::GetRegisterInfo() const {175 return m_register_info_p;176}177 178uint32_t RegisterContextLinux_x86_64::GetRegisterCount() const {179 return m_register_info_count;180}181 182uint32_t RegisterContextLinux_x86_64::GetUserRegisterCount() const {183 return m_user_register_count;184}185