From 5fb2009931908ae28872d9ae789a8f129dae352a Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 14 Apr 2015 17:44:12 -0400 Subject: [PATCH] Debugger: Restrict registers via CPU feature detection. DebuggerInterface,Architecture{X86,X8664}: - Add hook function for retrieving a feature flag mask for the target CPU, and corresponding implementation in Architecture-specific classes. ArchitectureX86: - Read CPU features on init, and use them to restrict the exposed set of registers such that the MMX and SSE registers will only be visible if the target CPU actually supports the respective instructions. --- src/apps/debugger/arch/Architecture.h | 4 +- .../debugger/arch/x86/ArchitectureX86.cpp | 75 ++++++++++++++----- src/apps/debugger/arch/x86/ArchitectureX86.h | 12 ++- .../arch/x86_64/ArchitectureX8664.cpp | 9 +++ .../debugger/arch/x86_64/ArchitectureX8664.h | 2 + .../debugger_interface/DebuggerInterface.cpp | 9 ++- .../debugger_interface/DebuggerInterface.h | 2 + 7 files changed, 93 insertions(+), 20 deletions(-) diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index b792232a87..f86bc89590 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2012, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef ARCHITECTURE_H @@ -70,6 +70,8 @@ public: RegisterMap** _fromDwarf) const = 0; // returns references + virtual status_t GetCpuFeatures(uint32& flags) = 0; + virtual status_t CreateCpuState(CpuState*& _state) = 0; virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state) = 0; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 4a000608f6..b423501fed 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -29,6 +29,10 @@ #include "disasm/DisassemblerX86.h" +#define IA32_FEATURE_MMX (1 << 23) +#define IA32_FEATURE_SSE (1 << 25) + + static const int32 kFromDwarfRegisters[] = { X86_REGISTER_EAX, X86_REGISTER_ECX, @@ -124,6 +128,7 @@ struct ArchitectureX86::FromDwarfRegisterMap : RegisterMap { ArchitectureX86::ArchitectureX86(TeamMemory* teamMemory) : Architecture(teamMemory, 4, false), + fFeatureFlags(0), fAssemblyLanguage(NULL), fToDwarfRegisterMap(NULL), fFromDwarfRegisterMap(NULL) @@ -149,6 +154,20 @@ ArchitectureX86::Init() if (fAssemblyLanguage == NULL) return B_NO_MEMORY; +#if defined(__INTEL__) + cpuid_info info; + status_t error = get_cpuid(&info, 1, 0); + if (error != B_OK) + return error; + + if ((info.eax_1.features & IA32_FEATURE_MMX) != 0) + fFeatureFlags |= X86_CPU_FEATURE_FLAG_MMX; + + if ((info.eax_1.features & IA32_FEATURE_SSE) != 0) + fFeatureFlags |= X86_CPU_FEATURE_FLAG_SSE; + +#endif + try { _AddIntegerRegister(X86_REGISTER_EIP, "eip", B_UINT32_TYPE, REGISTER_TYPE_INSTRUCTION_POINTER, false); @@ -193,23 +212,35 @@ ArchitectureX86::Init() _AddFPRegister(X86_REGISTER_ST6, "st6"); _AddFPRegister(X86_REGISTER_ST7, "st7"); - _AddSIMDRegister(X86_REGISTER_MM0, "mm0", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM1, "mm1", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM2, "mm2", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM3, "mm3", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM4, "mm4", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM5, "mm5", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM6, "mm6", sizeof(uint64)); - _AddSIMDRegister(X86_REGISTER_MM7, "mm7", sizeof(uint64)); + if ((fFeatureFlags & X86_CPU_FEATURE_FLAG_MMX) != 0) { + _AddSIMDRegister(X86_REGISTER_MM0, "mm0", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM1, "mm1", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM2, "mm2", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM3, "mm3", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM4, "mm4", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM5, "mm5", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM6, "mm6", sizeof(uint64)); + _AddSIMDRegister(X86_REGISTER_MM7, "mm7", sizeof(uint64)); + } - _AddSIMDRegister(X86_REGISTER_XMM0, "xmm0", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM1, "xmm1", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM2, "xmm2", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM3, "xmm3", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM4, "xmm4", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM5, "xmm5", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM6, "xmm6", sizeof(x86_xmm_register)); - _AddSIMDRegister(X86_REGISTER_XMM7, "xmm7", sizeof(x86_xmm_register)); + if ((fFeatureFlags & X86_CPU_FEATURE_FLAG_SSE) != 0) { + _AddSIMDRegister(X86_REGISTER_XMM0, "xmm0", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM1, "xmm1", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM2, "xmm2", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM3, "xmm3", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM4, "xmm4", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM5, "xmm5", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM6, "xmm6", + sizeof(x86_xmm_register)); + _AddSIMDRegister(X86_REGISTER_XMM7, "xmm7", + sizeof(x86_xmm_register)); + } } catch (std::bad_alloc) { return B_NO_MEMORY; @@ -246,6 +277,7 @@ ArchitectureX86::Registers() const } + status_t ArchitectureX86::InitRegisterRules(CfaContext& context) const { @@ -279,6 +311,15 @@ ArchitectureX86::GetDwarfRegisterMaps(RegisterMap** _toDwarf, } +status_t +ArchitectureX86::GetCpuFeatures(uint32& flags) +{ + flags = fFeatureFlags; + + return B_OK; +} + + status_t ArchitectureX86::CreateCpuState(CpuState*& _state) { diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index c0e6244f9f..92099c54de 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef ARCHITECTURE_X86_H @@ -13,6 +13,13 @@ #include "Register.h" +enum { + X86_CPU_FEATURE_FLAG_NONE = 0, + X86_CPU_FEATURE_FLAG_MMX = 1, + X86_CPU_FEATURE_FLAG_SSE = 2 +}; + + class SourceLanguage; @@ -32,6 +39,8 @@ public: virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf, RegisterMap** _fromDwarf) const; + virtual status_t GetCpuFeatures(uint32& flags); + virtual status_t CreateCpuState(CpuState*& _state); virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state); @@ -94,6 +103,7 @@ private: FunctionDebugInfo* function) const; private: + uint32 fFeatureFlags; Array fRegisters; SourceLanguage* fAssemblyLanguage; ToDwarfRegisterMap* fToDwarfRegisterMap; diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index 2581cd1682..4ec4e6a678 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -341,6 +341,15 @@ ArchitectureX8664::GetDwarfRegisterMaps(RegisterMap** _toDwarf, } +status_t +ArchitectureX8664::GetCpuFeatures(uint32& flags) +{ + // TODO: implement if/when it winds up being needed. + flags = 0; + return B_OK; +} + + status_t ArchitectureX8664::CreateCpuState(CpuState*& _state) { diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h index 33da8bc6e7..dfeb2ed886 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h @@ -33,6 +33,8 @@ public: virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf, RegisterMap** _fromDwarf) const; + virtual status_t GetCpuFeatures(uint32& flags); + virtual status_t CreateCpuState(CpuState*& _state); virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state); diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index 9d413a4fbc..79eb6651d1 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2010-2013, Rene Gollent, rene@gollent.com. + * Copyright 2010-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -701,6 +701,13 @@ DebuggerInterface::SetCpuState(thread_id thread, const CpuState* state) } +status_t +DebuggerInterface::GetCpuFeatures(uint32& flags) +{ + return fArchitecture->GetCpuFeatures(flags); +} + + ssize_t DebuggerInterface::ReadMemory(target_addr_t address, void* buffer, size_t size) { diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.h b/src/apps/debugger/debugger_interface/DebuggerInterface.h index def878efff..8770c7c0bd 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.h +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.h @@ -80,6 +80,8 @@ public: virtual status_t SetCpuState(thread_id thread, const CpuState* state); + virtual status_t GetCpuFeatures(uint32& flags); + // TeamMemory virtual ssize_t ReadMemory(target_addr_t address, void* buffer, size_t size);