diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj index 4c18f7333936..79175c6d9dd7 100644 --- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -39,8 +39,6 @@ 26CE05BD115C36430022F371 /* PThreadMutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */; }; 26CE05BE115C36440022F371 /* SysSignal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C638010C71334A0024798E /* SysSignal.cpp */; }; 26CE05BF115C364D0022F371 /* DNBArchImplX86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */; }; - 26CE05C0115C364F0022F371 /* DNBArchImplI386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */; }; - 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; 26CE05C3115C36580022F371 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; 26CE05CF115C36F70022F371 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; @@ -70,8 +68,6 @@ 456F675C1AD46CE9002850C2 /* PThreadMutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */; }; 456F675D1AD46CE9002850C2 /* SysSignal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C638010C71334A0024798E /* SysSignal.cpp */; }; 456F675E1AD46CE9002850C2 /* DNBArchImplX86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */; }; - 456F675F1AD46CE9002850C2 /* DNBArchImplI386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */; }; - 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; 456F67641AD46CE9002850C2 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; 456F67651AD46CE9002850C2 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; @@ -107,8 +103,6 @@ 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplARM64.cpp; sourceTree = ""; }; 266B5ED01460A68200E43F0A /* DNBArchImplARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBArchImplARM64.h; sourceTree = ""; }; 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PThreadMutex.cpp; sourceTree = ""; }; - 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DNBArchImpl.cpp; path = arm/DNBArchImpl.cpp; sourceTree = ""; }; - 2675D4230CCEB705000F49AF /* DNBArchImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DNBArchImpl.h; path = arm/DNBArchImpl.h; sourceTree = ""; }; 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFBundle.cpp; sourceTree = ""; }; 2695DD920D3EBFF6007E4CA2 /* CFBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFBundle.h; sourceTree = ""; }; 2695DD9A0D3EC160007E4CA2 /* CFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFString.h; sourceTree = ""; }; @@ -142,8 +136,6 @@ 26C637E30C71334A0024798E /* DNBRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBRegisterInfo.h; sourceTree = ""; }; 26C637E70C71334A0024798E /* CFUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CFUtils.h; sourceTree = ""; }; 26C637E80C71334A0024798E /* dbgnub-mig.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 30; path = "dbgnub-mig.defs"; sourceTree = ""; }; - 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplI386.cpp; sourceTree = ""; }; - 26C637EB0C71334A0024798E /* DNBArchImplI386.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArchImplI386.h; sourceTree = ""; }; 26C637EE0C71334A0024798E /* MachException.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachException.cpp; sourceTree = ""; }; 26C637EF0C71334A0024798E /* MachException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachException.h; sourceTree = ""; }; 26C637F00C71334A0024798E /* MachProcess.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = MachProcess.mm; sourceTree = ""; }; @@ -170,9 +162,12 @@ 26E6B9DA0D1329010037ECDD /* RNBDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBDefs.h; sourceTree = ""; }; 456F67721AD46CE9002850C2 /* debugserver-nonui */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "debugserver-nonui"; sourceTree = BUILT_PRODUCTS_DIR; }; 49D404611E39260F00570CDC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 49F530111331519C008956F6 /* MachRegisterStatesI386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesI386.h; sourceTree = ""; }; 49F5301213316D7F008956F6 /* MachRegisterStatesX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesX86_64.h; sourceTree = ""; }; 9457ECF61419864100DFE7D8 /* stack_logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stack_logging.h; sourceTree = ""; }; + 9684D93A29FCA1E10046D45E /* debugserver-macosx-private-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "debugserver-macosx-private-entitlements.plist"; path = "resources/debugserver-macosx-private-entitlements.plist"; sourceTree = SOURCE_ROOT; }; + 9684D93B29FCA1E10046D45E /* lldb-debugserver-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "lldb-debugserver-Info.plist"; path = "resources/lldb-debugserver-Info.plist"; sourceTree = SOURCE_ROOT; }; + 9684D93C29FCA1E10046D45E /* debugserver-macosx-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "debugserver-macosx-entitlements.plist"; path = "resources/debugserver-macosx-entitlements.plist"; sourceTree = SOURCE_ROOT; }; + 9684D93D29FCA1E10046D45E /* debugserver-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "debugserver-entitlements.plist"; path = "resources/debugserver-entitlements.plist"; sourceTree = SOURCE_ROOT; }; AF0934BA18E12B92005A11FD /* Genealogy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Genealogy.h; sourceTree = ""; }; AF0934BB18E12B92005A11FD /* GenealogySPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenealogySPI.h; sourceTree = ""; }; AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdStringExtractor.cpp; sourceTree = ""; }; @@ -239,18 +234,13 @@ path = arm64; sourceTree = ""; }; - 2675D41C0CCEB6CF000F49AF /* arm */ = { - isa = PBXGroup; - children = ( - 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */, - 2675D4230CCEB705000F49AF /* DNBArchImpl.h */, - ); - name = arm; - sourceTree = ""; - }; 26A028FE114AB6A60029C479 /* Resources */ = { isa = PBXGroup; children = ( + 9684D93D29FCA1E10046D45E /* debugserver-entitlements.plist */, + 9684D93C29FCA1E10046D45E /* debugserver-macosx-entitlements.plist */, + 9684D93A29FCA1E10046D45E /* debugserver-macosx-private-entitlements.plist */, + 9684D93B29FCA1E10046D45E /* lldb-debugserver-Info.plist */, 26A4BAED0D498B7D00A9BEAB /* com.apple.debugserver.plist */, EF88788B0D9C7558001831DA /* com.apple.debugserver.applist.plist */, 269E8DF8164B2ED200AD65F6 /* com.apple.debugserver.posix.plist */, @@ -336,9 +326,7 @@ 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */, 26C637E70C71334A0024798E /* CFUtils.h */, 2307CCCC1D4A5DAE0016ABC0 /* CMakeLists.txt */, - 2675D41C0CCEB6CF000F49AF /* arm */, 266B5ECE1460A68200E43F0A /* arm64 */, - 26C637E90C71334A0024798E /* i386 */, 26CF99A11142EB7400011AAB /* x86_64 */, 26C637E80C71334A0024798E /* dbgnub-mig.defs */, AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */, @@ -365,16 +353,6 @@ path = MacOSX; sourceTree = ""; }; - 26C637E90C71334A0024798E /* i386 */ = { - isa = PBXGroup; - children = ( - 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */, - 26C637EB0C71334A0024798E /* DNBArchImplI386.h */, - 49F530111331519C008956F6 /* MachRegisterStatesI386.h */, - ); - path = i386; - sourceTree = ""; - }; 26CF99A11142EB7400011AAB /* x86_64 */ = { isa = PBXGroup; children = ( @@ -422,7 +400,6 @@ buildPhases = ( 26CE0591115C31C20022F371 /* Sources */, 26CE0592115C31C20022F371 /* Frameworks */, - 4C3326CB18B2A2F600EB5DD7 /* ShellScript */, ); buildRules = ( ); @@ -478,22 +455,6 @@ }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - 4C3326CB18B2A2F600EB5DD7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = "/bin/sh -x"; - shellScript = "if [ \"${CONFIGURATION}\" != BuildAndIntegration ]\nthen\n if [ -n \"${DEBUGSERVER_USE_FROM_SYSTEM}\" ]\n then\n\t\tditto \"${DEVELOPER_DIR}/../SharedFrameworks/LLDB.framework/Resources/debugserver\" \"${TARGET_BUILD_DIR}/${TARGET_NAME}\"\n elif [ \"${DEBUGSERVER_DISABLE_CODESIGN}\" == \"\" ]\n then\n codesign -f -s lldb_codesign --entitlements ${SRCROOT}/resources/debugserver-macosx-entitlements.plist \"${TARGET_BUILD_DIR}/${TARGET_NAME}\"\n fi\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 26CE0591115C31C20022F371 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -529,8 +490,6 @@ 26CE05BD115C36430022F371 /* PThreadMutex.cpp in Sources */, 26CE05BE115C36440022F371 /* SysSignal.cpp in Sources */, 26CE05BF115C364D0022F371 /* DNBArchImplX86_64.cpp in Sources */, - 26CE05C0115C364F0022F371 /* DNBArchImplI386.cpp in Sources */, - 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */, 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */, 26CE05C3115C36580022F371 /* CFString.cpp in Sources */, 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */, @@ -570,8 +529,6 @@ 456F675C1AD46CE9002850C2 /* PThreadMutex.cpp in Sources */, 456F675D1AD46CE9002850C2 /* SysSignal.cpp in Sources */, 456F675E1AD46CE9002850C2 /* DNBArchImplX86_64.cpp in Sources */, - 456F675F1AD46CE9002850C2 /* DNBArchImplI386.cpp in Sources */, - 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */, 23043C9E1D35DBFA00FC25CA /* StringConvert.cpp in Sources */, AF588449206077BD00A0CB5A /* SocketAddress.cpp in Sources */, 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */, @@ -600,7 +557,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 360.99.0; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -666,10 +623,10 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; - "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "source/debugserver-entitlements.plist"; - "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "source/debugserver-macosx-entitlements.plist"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; + "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "resources/debugserver-entitlements.plist"; + "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "resources/debugserver-macosx-entitlements.plist"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; COPY_PHASE_STRIP = YES; CURRENT_PROJECT_VERSION = 360.99.0; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; @@ -766,10 +723,10 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; - "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "source/debugserver-entitlements.plist"; - "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "source/debugserver-macosx-entitlements.plist"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; + "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "resources/debugserver-entitlements.plist"; + "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "resources/debugserver-macosx-entitlements.plist"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; COPY_PHASE_STRIP = YES; CURRENT_PROJECT_VERSION = 360.99.0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -875,8 +832,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "source/debugserver-macosx-entitlements.plist"; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 360.99.0; @@ -955,7 +912,7 @@ CLANG_CXX_LIBRARY = "libc++"; "CODE_SIGN_ENTITLEMENTS[sdk=*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "source/debugserver-macosx-entitlements.plist"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = ""; COPY_PHASE_STRIP = YES; CURRENT_PROJECT_VERSION = 360.99.0; diff --git a/lldb/tools/debugserver/source/CMakeLists.txt b/lldb/tools/debugserver/source/CMakeLists.txt index 2aaefb56cb4b..43accc363ef3 100644 --- a/lldb/tools/debugserver/source/CMakeLists.txt +++ b/lldb/tools/debugserver/source/CMakeLists.txt @@ -3,9 +3,7 @@ include(CheckLibraryExists) include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) include_directories(${LLDB_SOURCE_DIR}/source) include_directories(MacOSX) -include_directories(MacOSX/i386) include_directories(MacOSX/x86_64) -include_directories(MacOSX/arm) include_directories(MacOSX/arm64) function(check_certificate identity result_valid) @@ -228,9 +226,7 @@ set(lldbDebugserverCommonSources MacOSX/MachVMMemory.cpp MacOSX/MachVMRegion.cpp MacOSX/OsLogger.cpp - MacOSX/arm/DNBArchImpl.cpp MacOSX/arm64/DNBArchImplARM64.cpp - MacOSX/i386/DNBArchImplI386.cpp MacOSX/x86_64/DNBArchImplX86_64.cpp ${generated_mach_interfaces} ${DEBUGSERVER_VERS_GENERATED_FILE}) diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index 07423ea56e6e..bab5b4a81305 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -1768,10 +1768,8 @@ std::string DNBGetMacCatalystVersionString() { void DNBInitialize() { DNBLogThreadedIf(LOG_PROCESS, "DNBInitialize ()"); #if defined(__i386__) || defined(__x86_64__) - DNBArchImplI386::Initialize(); DNBArchImplX86_64::Initialize(); #elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - DNBArchMachARM::Initialize(); DNBArchMachARM64::Initialize(); #endif } diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h index b673e403feb4..85b2d1caf9af 100644 --- a/lldb/tools/debugserver/source/DNBArch.h +++ b/lldb/tools/debugserver/source/DNBArch.h @@ -122,9 +122,7 @@ protected: // SaveRegisterState/RestoreRegisterState }; -#include "MacOSX/arm/DNBArchImpl.h" #include "MacOSX/arm64/DNBArchImplARM64.h" -#include "MacOSX/i386/DNBArchImplI386.h" #include "MacOSX/x86_64/DNBArchImplX86_64.h" #endif diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp deleted file mode 100644 index 92717f1c5754..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ /dev/null @@ -1,2195 +0,0 @@ -//===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include "MacOSX/arm/DNBArchImpl.h" -#include "ARM_DWARF_Registers.h" -#include "ARM_ehframe_Registers.h" -#include "DNB.h" -#include "DNBBreakpoint.h" -#include "DNBLog.h" -#include "DNBRegisterInfo.h" -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachThread.h" - -#include -#include - -// BCR address match type -#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) -#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) -#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) -#define BCR_M_RESERVED ((uint32_t)(3u << 21)) - -// Link a BVR/BCR or WVR/WCR pair to another -#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) - -// Byte Address Select -#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) -#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) -#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) -#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) -#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) -#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) -#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) - -// Break only in privileged or user mode -#define S_RSVD ((uint32_t)(0u << 1)) -#define S_PRIV ((uint32_t)(1u << 1)) -#define S_USER ((uint32_t)(2u << 1)) -#define S_PRIV_USER ((S_PRIV) | (S_USER)) - -#define BCR_ENABLE ((uint32_t)(1u)) -#define WCR_ENABLE ((uint32_t)(1u)) - -// Watchpoint load/store -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) - -// Definitions for the Debug Status and Control Register fields: -// [5:2] => Method of debug entry -//#define WATCHPOINT_OCCURRED ((uint32_t)(2u)) -// I'm seeing this, instead. -#define WATCHPOINT_OCCURRED ((uint32_t)(10u)) - -// 0xE120BE70 -static const uint8_t g_arm_breakpoint_opcode[] = {0x70, 0xBE, 0x20, 0xE1}; -static const uint8_t g_thumb_breakpoint_opcode[] = {0x70, 0xBE}; - -// A watchpoint may need to be implemented using two watchpoint registers. -// e.g. watching an 8-byte region when the device can only watch 4-bytes. -// -// This stores the lo->hi mappings. It's safe to initialize to all 0's -// since hi > lo and therefore LoHi[i] cannot be 0. -static uint32_t LoHi[16] = {0}; - -// ARM constants used during decoding -#define REG_RD 0 -#define LDM_REGLIST 1 -#define PC_REG 15 -#define PC_REGLIST_BIT 0x8000 - -// ARM conditions -#define COND_EQ 0x0 -#define COND_NE 0x1 -#define COND_CS 0x2 -#define COND_HS 0x2 -#define COND_CC 0x3 -#define COND_LO 0x3 -#define COND_MI 0x4 -#define COND_PL 0x5 -#define COND_VS 0x6 -#define COND_VC 0x7 -#define COND_HI 0x8 -#define COND_LS 0x9 -#define COND_GE 0xA -#define COND_LT 0xB -#define COND_GT 0xC -#define COND_LE 0xD -#define COND_AL 0xE -#define COND_UNCOND 0xF - -#define MASK_CPSR_T (1u << 5) -#define MASK_CPSR_J (1u << 24) - -#define MNEMONIC_STRING_SIZE 32 -#define OPERAND_STRING_SIZE 128 - -#if !defined(__arm64__) && !defined(__aarch64__) -// Returns true if the first 16 bit opcode of a thumb instruction indicates -// the instruction will be a 32 bit thumb opcode -static bool IsThumb32Opcode(uint16_t opcode) { - if (((opcode & 0xE000) == 0xE000) && (opcode & 0x1800)) - return true; - return false; -} -#endif - -void DNBArchMachARM::Initialize() { - DNBArchPluginInfo arch_plugin_info = { - CPU_TYPE_ARM, DNBArchMachARM::Create, DNBArchMachARM::GetRegisterSetInfo, - DNBArchMachARM::SoftwareBreakpointOpcode}; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); -} - -DNBArchProtocol *DNBArchMachARM::Create(MachThread *thread) { - DNBArchMachARM *obj = new DNBArchMachARM(thread); - return obj; -} - -const uint8_t *DNBArchMachARM::SoftwareBreakpointOpcode(nub_size_t byte_size) { - switch (byte_size) { - case 2: - return g_thumb_breakpoint_opcode; - case 4: - return g_arm_breakpoint_opcode; - } - return NULL; -} - -uint32_t DNBArchMachARM::GetCPUType() { return CPU_TYPE_ARM; } - -uint64_t DNBArchMachARM::GetPC(uint64_t failValue) { - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__pc; - return failValue; -} - -kern_return_t DNBArchMachARM::SetPC(uint64_t value) { - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) { - m_state.context.gpr.__pc = (uint32_t)value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; -} - -uint64_t DNBArchMachARM::GetSP(uint64_t failValue) { - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__sp; - return failValue; -} - -kern_return_t DNBArchMachARM::GetGPRState(bool force) { - int set = e_regSetGPR; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, &count); - uint32_t *r = &m_state.context.gpr.__r[0]; - DNBLogThreadedIf( - LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = " - "%u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x " - "r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x " - "r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", - m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, - kret, count, r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], - r[10], r[11], r[12], r[13], r[14], r[15], r[16]); - m_state.SetError(set, Read, kret); - return kret; -} - -kern_return_t DNBArchMachARM::GetVFPState(bool force) { - int set = e_regSetVFP; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - kern_return_t kret; - -#if defined(__arm64__) || defined(__aarch64__) - // Read the registers from our thread - mach_msg_type_number_t count = ARM_NEON_STATE_COUNT; - kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE, - (thread_state_t)&m_state.context.vfp, &count); - if (DNBLogEnabledForAny(LOG_THREAD)) { - DNBLogThreaded( - "thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" - "\n q0 = 0x%16.16llx%16.16llx" - "\n q1 = 0x%16.16llx%16.16llx" - "\n q2 = 0x%16.16llx%16.16llx" - "\n q3 = 0x%16.16llx%16.16llx" - "\n q4 = 0x%16.16llx%16.16llx" - "\n q5 = 0x%16.16llx%16.16llx" - "\n q6 = 0x%16.16llx%16.16llx" - "\n q7 = 0x%16.16llx%16.16llx" - "\n q8 = 0x%16.16llx%16.16llx" - "\n q9 = 0x%16.16llx%16.16llx" - "\n q10 = 0x%16.16llx%16.16llx" - "\n q11 = 0x%16.16llx%16.16llx" - "\n q12 = 0x%16.16llx%16.16llx" - "\n q13 = 0x%16.16llx%16.16llx" - "\n q14 = 0x%16.16llx%16.16llx" - "\n q15 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), ARM_NEON_STATE, ARM_NEON_STATE_COUNT, kret, - count, ((uint64_t *)&m_state.context.vfp.__v[0])[0], - ((uint64_t *)&m_state.context.vfp.__v[0])[1], - ((uint64_t *)&m_state.context.vfp.__v[1])[0], - ((uint64_t *)&m_state.context.vfp.__v[1])[1], - ((uint64_t *)&m_state.context.vfp.__v[2])[0], - ((uint64_t *)&m_state.context.vfp.__v[2])[1], - ((uint64_t *)&m_state.context.vfp.__v[3])[0], - ((uint64_t *)&m_state.context.vfp.__v[3])[1], - ((uint64_t *)&m_state.context.vfp.__v[4])[0], - ((uint64_t *)&m_state.context.vfp.__v[4])[1], - ((uint64_t *)&m_state.context.vfp.__v[5])[0], - ((uint64_t *)&m_state.context.vfp.__v[5])[1], - ((uint64_t *)&m_state.context.vfp.__v[6])[0], - ((uint64_t *)&m_state.context.vfp.__v[6])[1], - ((uint64_t *)&m_state.context.vfp.__v[7])[0], - ((uint64_t *)&m_state.context.vfp.__v[7])[1], - ((uint64_t *)&m_state.context.vfp.__v[8])[0], - ((uint64_t *)&m_state.context.vfp.__v[8])[1], - ((uint64_t *)&m_state.context.vfp.__v[9])[0], - ((uint64_t *)&m_state.context.vfp.__v[9])[1], - ((uint64_t *)&m_state.context.vfp.__v[10])[0], - ((uint64_t *)&m_state.context.vfp.__v[10])[1], - ((uint64_t *)&m_state.context.vfp.__v[11])[0], - ((uint64_t *)&m_state.context.vfp.__v[11])[1], - ((uint64_t *)&m_state.context.vfp.__v[12])[0], - ((uint64_t *)&m_state.context.vfp.__v[12])[1], - ((uint64_t *)&m_state.context.vfp.__v[13])[0], - ((uint64_t *)&m_state.context.vfp.__v[13])[1], - ((uint64_t *)&m_state.context.vfp.__v[14])[0], - ((uint64_t *)&m_state.context.vfp.__v[14])[1], - ((uint64_t *)&m_state.context.vfp.__v[15])[0], - ((uint64_t *)&m_state.context.vfp.__v[15])[1], - m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); - } -#else - // Read the registers from our thread - mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; - kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, - (thread_state_t)&m_state.context.vfp, &count); - - if (DNBLogEnabledForAny(LOG_THREAD)) { - uint32_t *r = &m_state.context.vfp.__r[0]; - DNBLogThreaded( - "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", - m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, - kret, count); - DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x " - "s5=%8.8x s6=%8.8x s7=%8.8x", - r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); - DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x " - "s13=%8.8x s14=%8.8x s15=%8.8x", - r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); - DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x " - "s21=%8.8x s22=%8.8x s23=%8.8x", - r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); - DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x " - "s29=%8.8x s30=%8.8x s31=%8.8x", - r[24], r[25], r[26], r[27], r[28], r[29], r[30], r[31]); - DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x " - "s37=%8.8x s38=%8.8x s39=%8.8x", - r[32], r[33], r[34], r[35], r[36], r[37], r[38], r[39]); - DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x " - "s45=%8.8x s46=%8.8x s47=%8.8x", - r[40], r[41], r[42], r[43], r[44], r[45], r[46], r[47]); - DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x " - "s53=%8.8x s54=%8.8x s55=%8.8x", - r[48], r[49], r[50], r[51], r[52], r[53], r[54], r[55]); - DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x " - "s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x", - r[56], r[57], r[58], r[59], r[60], r[61], r[62], r[63], - r[64]); - } - -#endif - m_state.SetError(set, Read, kret); - return kret; -} - -kern_return_t DNBArchMachARM::GetEXCState(bool force) { - int set = e_regSetEXC; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, &count); - m_state.SetError(set, Read, kret); - return kret; -} - -#if 0 -static void DumpDBGState(const DNBArchMachARM::DBG &dbg) { - uint32_t i = 0; - for (i = 0; i < 16; i++) { - DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } " - "WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", - i, i, dbg.__bvr[i], dbg.__bcr[i], i, i, dbg.__wvr[i], - dbg.__wcr[i]); - } -} -#endif - -kern_return_t DNBArchMachARM::GetDBGState(bool force) { - int set = e_regSetDBG; - - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - -// Read the registers from our thread -#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) - mach_msg_type_number_t count = ARM_DEBUG_STATE32_COUNT; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE32, - (thread_state_t)&m_state.dbg, &count); -#else - mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, - (thread_state_t)&m_state.dbg, &count); -#endif - m_state.SetError(set, Read, kret); - - return kret; -} - -kern_return_t DNBArchMachARM::SetGPRState() { - int set = e_regSetGPR; - kern_return_t kret = ::thread_set_state( - m_thread->MachPortNumber(), ARM_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT); - m_state.SetError(set, Write, - kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register - // state in case registers are read - // back differently - return kret; // Return the error code -} - -kern_return_t DNBArchMachARM::SetVFPState() { - int set = e_regSetVFP; - kern_return_t kret; - mach_msg_type_number_t count; - -#if defined(__arm64__) || defined(__aarch64__) - count = ARM_NEON_STATE_COUNT; - kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_NEON_STATE, - (thread_state_t)&m_state.context.vfp, count); -#else - count = ARM_VFP_STATE_COUNT; - kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_VFP_STATE, - (thread_state_t)&m_state.context.vfp, count); -#endif - -#if defined(__arm64__) || defined(__aarch64__) - if (DNBLogEnabledForAny(LOG_THREAD)) { - DNBLogThreaded( - "thread_set_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" - "\n q0 = 0x%16.16llx%16.16llx" - "\n q1 = 0x%16.16llx%16.16llx" - "\n q2 = 0x%16.16llx%16.16llx" - "\n q3 = 0x%16.16llx%16.16llx" - "\n q4 = 0x%16.16llx%16.16llx" - "\n q5 = 0x%16.16llx%16.16llx" - "\n q6 = 0x%16.16llx%16.16llx" - "\n q7 = 0x%16.16llx%16.16llx" - "\n q8 = 0x%16.16llx%16.16llx" - "\n q9 = 0x%16.16llx%16.16llx" - "\n q10 = 0x%16.16llx%16.16llx" - "\n q11 = 0x%16.16llx%16.16llx" - "\n q12 = 0x%16.16llx%16.16llx" - "\n q13 = 0x%16.16llx%16.16llx" - "\n q14 = 0x%16.16llx%16.16llx" - "\n q15 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), ARM_NEON_STATE, ARM_NEON_STATE_COUNT, kret, - count, ((uint64_t *)&m_state.context.vfp.__v[0])[0], - ((uint64_t *)&m_state.context.vfp.__v[0])[1], - ((uint64_t *)&m_state.context.vfp.__v[1])[0], - ((uint64_t *)&m_state.context.vfp.__v[1])[1], - ((uint64_t *)&m_state.context.vfp.__v[2])[0], - ((uint64_t *)&m_state.context.vfp.__v[2])[1], - ((uint64_t *)&m_state.context.vfp.__v[3])[0], - ((uint64_t *)&m_state.context.vfp.__v[3])[1], - ((uint64_t *)&m_state.context.vfp.__v[4])[0], - ((uint64_t *)&m_state.context.vfp.__v[4])[1], - ((uint64_t *)&m_state.context.vfp.__v[5])[0], - ((uint64_t *)&m_state.context.vfp.__v[5])[1], - ((uint64_t *)&m_state.context.vfp.__v[6])[0], - ((uint64_t *)&m_state.context.vfp.__v[6])[1], - ((uint64_t *)&m_state.context.vfp.__v[7])[0], - ((uint64_t *)&m_state.context.vfp.__v[7])[1], - ((uint64_t *)&m_state.context.vfp.__v[8])[0], - ((uint64_t *)&m_state.context.vfp.__v[8])[1], - ((uint64_t *)&m_state.context.vfp.__v[9])[0], - ((uint64_t *)&m_state.context.vfp.__v[9])[1], - ((uint64_t *)&m_state.context.vfp.__v[10])[0], - ((uint64_t *)&m_state.context.vfp.__v[10])[1], - ((uint64_t *)&m_state.context.vfp.__v[11])[0], - ((uint64_t *)&m_state.context.vfp.__v[11])[1], - ((uint64_t *)&m_state.context.vfp.__v[12])[0], - ((uint64_t *)&m_state.context.vfp.__v[12])[1], - ((uint64_t *)&m_state.context.vfp.__v[13])[0], - ((uint64_t *)&m_state.context.vfp.__v[13])[1], - ((uint64_t *)&m_state.context.vfp.__v[14])[0], - ((uint64_t *)&m_state.context.vfp.__v[14])[1], - ((uint64_t *)&m_state.context.vfp.__v[15])[0], - ((uint64_t *)&m_state.context.vfp.__v[15])[1], - m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); - } -#else - if (DNBLogEnabledForAny(LOG_THREAD)) { - uint32_t *r = &m_state.context.vfp.__r[0]; - DNBLogThreaded( - "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", - m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, - kret, count); - DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x " - "s5=%8.8x s6=%8.8x s7=%8.8x", - r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); - DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x " - "s13=%8.8x s14=%8.8x s15=%8.8x", - r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); - DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x " - "s21=%8.8x s22=%8.8x s23=%8.8x", - r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); - DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x " - "s29=%8.8x s30=%8.8x s31=%8.8x", - r[24], r[25], r[26], r[27], r[28], r[29], r[30], r[31]); - DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x " - "s37=%8.8x s38=%8.8x s39=%8.8x", - r[32], r[33], r[34], r[35], r[36], r[37], r[38], r[39]); - DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x " - "s45=%8.8x s46=%8.8x s47=%8.8x", - r[40], r[41], r[42], r[43], r[44], r[45], r[46], r[47]); - DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x " - "s53=%8.8x s54=%8.8x s55=%8.8x", - r[48], r[49], r[50], r[51], r[52], r[53], r[54], r[55]); - DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x " - "s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x", - r[56], r[57], r[58], r[59], r[60], r[61], r[62], r[63], - r[64]); - } -#endif - - m_state.SetError(set, Write, - kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register - // state in case registers are read - // back differently - return kret; // Return the error code -} - -kern_return_t DNBArchMachARM::SetEXCState() { - int set = e_regSetEXC; - kern_return_t kret = ::thread_set_state( - m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT); - m_state.SetError(set, Write, - kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register - // state in case registers are read - // back differently - return kret; // Return the error code -} - -kern_return_t DNBArchMachARM::SetDBGState(bool also_set_on_task) { - int set = e_regSetDBG; -#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) - kern_return_t kret = - ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE32, - (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); - if (also_set_on_task) { - kern_return_t task_kret = ::task_set_state( - m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE32, - (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to " - "set debug control register state: " - "0x%8.8x.", - kret); - } -#else - kern_return_t kret = - ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, - (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); - if (also_set_on_task) { - kern_return_t task_kret = ::task_set_state( - m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE, - (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to " - "set debug control register state: " - "0x%8.8x.", - kret); - } -#endif - - m_state.SetError(set, Write, - kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register - // state in case registers are read - // back differently - return kret; // Return the error code -} - -void DNBArchMachARM::ThreadWillResume() { - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) { - // This is the primary thread, let the arch do anything it needs - if (NumSupportedHardwareBreakpoints() > 0) { - if (EnableHardwareSingleStep(true) != KERN_SUCCESS) { - DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable " - "hardware single step"); - } - } - } - - // Disable the triggered watchpoint temporarily before we resume. - // Plus, we try to enable hardware single step to execute past the instruction - // which triggered our watchpoint. - if (m_watchpoint_did_occur) { - if (m_watchpoint_hw_index >= 0) { - kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS && - !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { - // The watchpoint might have been disabled by the user. We don't need - // to do anything at all - // to enable hardware single stepping. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - return; - } - - DisableHardwareWatchpoint(m_watchpoint_hw_index, false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " - "DisableHardwareWatchpoint(%d) called", - m_watchpoint_hw_index); - - // Enable hardware single step to move past the watchpoint-triggering - // instruction. - m_watchpoint_resume_single_step_enabled = - (EnableHardwareSingleStep(true) == KERN_SUCCESS); - - // If we are not able to enable single step to move past the - // watchpoint-triggering instruction, - // at least we should reset the two watchpoint member variables so that - // the next time around - // this callback function is invoked, the enclosing logical branch is - // skipped. - if (!m_watchpoint_resume_single_step_enabled) { - // Reset the two watchpoint member variables. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchMachARM::ThreadWillResume() failed to enable single step"); - } else - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " - "succeeded to enable single step"); - } - } -} - -bool DNBArchMachARM::ThreadDidStop() { - bool success = true; - - m_state.InvalidateRegisterSetState(e_regSetALL); - - if (m_watchpoint_resume_single_step_enabled) { - // Great! We now disable the hardware single step as well as re-enable the - // hardware watchpoint. - // See also ThreadWillResume(). - if (EnableHardwareSingleStep(false) == KERN_SUCCESS) { - if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) { - ReenableHardwareWatchpoint(m_watchpoint_hw_index); - m_watchpoint_resume_single_step_enabled = false; - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - } else { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " - "is true but (m_watchpoint_did_occur && " - "m_watchpoint_hw_index >= 0) does not hold!"); - } - } else { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " - "is true but unable to disable single step!"); - } - } - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) { - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } else { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } - } - return success; -} - -bool DNBArchMachARM::NotifyException(MachException::Data &exc) { - switch (exc.exc_type) { - default: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) { - // The data break address is passed as exc_data[1]. - nub_addr_t addr = exc.exc_data[1]; - // Find the hardware index with the side effect of possibly massaging the - // addr to return the starting address as seen from the debugger side. - uint32_t hw_index = GetHardwareWatchpointHit(addr); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " - "watchpoint %d was hit on address " - "0x%llx", - hw_index, (uint64_t)addr); - const uint32_t num_watchpoints = NumSupportedHardwareWatchpoints(); - for (uint32_t i = 0; i < num_watchpoints; i++) { - if (LoHi[i] != 0 && LoHi[i] == hw_index && LoHi[i] != i && - GetWatchpointAddressByIndex(i) != INVALID_NUB_ADDRESS) { - addr = GetWatchpointAddressByIndex(i); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " - "It is a linked watchpoint; " - "rewritten to index %d addr 0x%llx", - LoHi[i], (uint64_t)addr); - } - } - if (hw_index != INVALID_NUB_HW_INDEX) { - m_watchpoint_did_occur = true; - m_watchpoint_hw_index = hw_index; - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; - } - return false; -} - -bool DNBArchMachARM::StepNotComplete() { - if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) { - kern_return_t kret = KERN_INVALID_ARGUMENT; - kret = GetGPRState(false); - if (kret == KERN_SUCCESS) { - if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) { - DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8llx", - (uint64_t)m_hw_single_chained_step_addr); - return true; - } - } - } - - m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; - return false; -} - -// Set the single step bit in the processor status register. -kern_return_t DNBArchMachARM::EnableHardwareSingleStep(bool enable) { - DNBError err; - DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); - - err = GetGPRState(false); - - if (err.Fail()) { - err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); - return err.Status(); - } - - err = GetDBGState(false); - - if (err.Fail()) { - err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); - return err.Status(); - } - -// The use of __arm64__ here is not ideal. If debugserver is running on -// an armv8 device, regardless of whether it was built for arch arm or arch -// arm64, -// it needs to use the MDSCR_EL1 SS bit to single instruction step. - -#if defined(__arm64__) || defined(__aarch64__) - if (enable) { - DNBLogThreadedIf(LOG_STEP, - "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", - __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 |= - 1; // Set bit 0 (single step, SS) in the MDSCR_EL1. - } else { - DNBLogThreadedIf(LOG_STEP, - "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", - __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 &= - ~(1ULL); // Clear bit 0 (single step, SS) in the MDSCR_EL1. - } -#else - const uint32_t i = 0; - if (enable) { - m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; - - // Save our previous state - m_dbg_save = m_state.dbg; - // Set a breakpoint that will stop when the PC doesn't match the current - // one! - m_state.dbg.__bvr[i] = - m_state.context.gpr.__pc & - 0xFFFFFFFCu; // Set the current PC as the breakpoint address - m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch - S_USER | // Stop only in user mode - BCR_ENABLE; // Enable this breakpoint - if (m_state.context.gpr.__cpsr & 0x20) { - // Thumb breakpoint - if (m_state.context.gpr.__pc & 2) - m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; - else - m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; - - uint16_t opcode; - if (sizeof(opcode) == - m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, - sizeof(opcode), &opcode)) { - if (IsThumb32Opcode(opcode)) { - // 32 bit thumb opcode... - if (m_state.context.gpr.__pc & 2) { - // We can't take care of a 32 bit thumb instruction single step - // with just IVA mismatching. We will need to chain an extra - // hardware single step in order to complete this single step... - m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; - } else { - // Extend the number of bits to ignore for the mismatch - m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; - } - } - } - } else { - // ARM breakpoint - m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change - } - - DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x BCR%u=0x%8.8x", __FUNCTION__, - i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]); - - for (uint32_t j = i + 1; j < 16; ++j) { - // Disable all others - m_state.dbg.__bvr[j] = 0; - m_state.dbg.__bcr[j] = 0; - } - } else { - // Just restore the state we had before we did single stepping - m_state.dbg = m_dbg_save; - } -#endif - - return SetDBGState(false); -} - -// return 1 if bit "BIT" is set in "value" -static inline uint32_t bit(uint32_t value, uint32_t bit) { - return (value >> bit) & 1u; -} - -// return the bitfield "value[msbit:lsbit]". -static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) { - assert(msbit >= lsbit); - uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; - value <<= - shift_left; // shift anything above the msbit off of the unsigned edge - value >>= (shift_left + lsbit); // shift it back again down to the lsbit - // (including undoing any shift from above) - return value; // return our result -} - -bool DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) { - uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag - uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag - uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag - uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag - - switch (condition) { - case COND_EQ: // (0x0) - if (cpsr_z == 1) - return true; - break; - case COND_NE: // (0x1) - if (cpsr_z == 0) - return true; - break; - case COND_CS: // (0x2) - if (cpsr_c == 1) - return true; - break; - case COND_CC: // (0x3) - if (cpsr_c == 0) - return true; - break; - case COND_MI: // (0x4) - if (cpsr_n == 1) - return true; - break; - case COND_PL: // (0x5) - if (cpsr_n == 0) - return true; - break; - case COND_VS: // (0x6) - if (cpsr_v == 1) - return true; - break; - case COND_VC: // (0x7) - if (cpsr_v == 0) - return true; - break; - case COND_HI: // (0x8) - if ((cpsr_c == 1) && (cpsr_z == 0)) - return true; - break; - case COND_LS: // (0x9) - if ((cpsr_c == 0) || (cpsr_z == 1)) - return true; - break; - case COND_GE: // (0xA) - if (cpsr_n == cpsr_v) - return true; - break; - case COND_LT: // (0xB) - if (cpsr_n != cpsr_v) - return true; - break; - case COND_GT: // (0xC) - if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) - return true; - break; - case COND_LE: // (0xD) - if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) - return true; - break; - default: - return true; - break; - } - - return false; -} - -uint32_t DNBArchMachARM::NumSupportedHardwareBreakpoints() { - // Set the init value to something that will let us know that we need to - // autodetect how many breakpoints are supported dynamically... - static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; - if (g_num_supported_hw_breakpoints == UINT_MAX) { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_breakpoints = 0; - - size_t len; - uint32_t n = 0; - len = sizeof(n); - if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) { - g_num_supported_hw_breakpoints = n; - DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); - } else { -#if !defined(__arm64__) && !defined(__aarch64__) - // Read the DBGDIDR to get the number of available hardware breakpoints - // However, in some of our current armv7 processors, hardware - // breakpoints/watchpoints were not properly connected. So detect those - // cases using a field in a sysctl. For now we are using "hw.cpusubtype" - // field to distinguish CPU architectures. This is a hack until we can - // get fixed, at which point we will switch to - // using a different sysctl string that will tell us how many BRPs - // are available to us directly without having to read DBGDIDR. - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); - uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); - // Zero is reserved for the BRP count, so don't increment it if it is zero - if (numBRPs > 0) - numBRPs++; - DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", - register_DBGDIDR, numBRPs); - - if (numBRPs > 0) { - uint32_t cpusubtype; - len = sizeof(cpusubtype); - // TODO: remove this hack and change to using hw.optional.xx when - // implmented - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) { - DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); - if (cpusubtype == CPU_SUBTYPE_ARM_V7) - DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for " - "armv7 (rdar://problem/6372672)"); - else - g_num_supported_hw_breakpoints = numBRPs; - } - } -#endif - } - } - return g_num_supported_hw_breakpoints; -} - -uint32_t DNBArchMachARM::NumSupportedHardwareWatchpoints() { - // Set the init value to something that will let us know that we need to - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; - if (g_num_supported_hw_watchpoints == UINT_MAX) { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_watchpoints = 0; - - size_t len; - uint32_t n = 0; - len = sizeof(n); - if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) { - g_num_supported_hw_watchpoints = n; - DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); - } else { -#if !defined(__arm64__) && !defined(__aarch64__) - // Read the DBGDIDR to get the number of available hardware breakpoints - // However, in some of our current armv7 processors, hardware - // breakpoints/watchpoints were not properly connected. So detect those - // cases using a field in a sysctl. For now we are using "hw.cpusubtype" - // field to distinguish CPU architectures. This is a hack until we can - // get fixed, at which point we will switch to - // using a different sysctl string that will tell us how many WRPs - // are available to us directly without having to read DBGDIDR. - - uint32_t register_DBGDIDR; - asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); - uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; - DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", - register_DBGDIDR, numWRPs); - - if (numWRPs > 0) { - uint32_t cpusubtype; - size_t len; - len = sizeof(cpusubtype); - // TODO: remove this hack and change to using hw.optional.xx when - // implmented - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) { - DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); - - if (cpusubtype == CPU_SUBTYPE_ARM_V7) - DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for " - "armv7 (rdar://problem/6372672)"); - else - g_num_supported_hw_watchpoints = numWRPs; - } - } -#endif - } - } - return g_num_supported_hw_watchpoints; -} - -uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr, - nub_size_t size, - bool also_set_on_task) { - // Make sure our address isn't bogus - if (addr & 1) - return INVALID_NUB_HW_INDEX; - - kern_return_t kret = GetDBGState(false); - - if (kret == KERN_SUCCESS) { - const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); - uint32_t i; - for (i = 0; i < num_hw_breakpoints; ++i) { - if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_breakpoints) { - // Make sure bits 1:0 are clear in our address - m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); - - if (size == 2 || addr & 2) { - uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; - - // We have a thumb breakpoint - // We have an ARM breakpoint - m_state.dbg.__bcr[i] = - BCR_M_IMVA_MATCH | // Stop on address match - byte_addr_select | // Set the correct byte address select so we only - // trigger on the correct opcode - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchMachARM::EnableHardwareBreakpoint( addr = " - "0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / " - "0x%8.8x (Thumb)", - (uint64_t)addr, (uint64_t)size, i, i, - m_state.dbg.__bvr[i], m_state.dbg.__bcr[i]); - } else if (size == 4) { - // We have an ARM breakpoint - m_state.dbg.__bcr[i] = - BCR_M_IMVA_MATCH | // Stop on address match - BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchMachARM::EnableHardwareBreakpoint( addr = " - "0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / " - "0x%8.8x (ARM)", - (uint64_t)addr, (uint64_t)size, i, i, - m_state.dbg.__bvr[i], m_state.dbg.__bcr[i]); - } - - kret = SetDBGState(false); - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::" - "EnableHardwareBreakpoint() " - "SetDBGState() => 0x%8.8x.", - kret); - - if (kret == KERN_SUCCESS) - return i; - } else { - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchMachARM::EnableHardwareBreakpoint(addr = " - "0x%8.8llx, size = %llu) => all hardware breakpoint " - "resources are being used.", - (uint64_t)addr, (uint64_t)size); - } - } - - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index, - bool also_set_on_task) { - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); - if (kret == KERN_SUCCESS) { - if (hw_index < num_hw_points) { - m_state.dbg.__bcr[hw_index] = 0; - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint(" - " %u ) - BVR%u = 0x%8.8x BCR%u = " - "0x%8.8x", - hw_index, hw_index, m_state.dbg.__bvr[hw_index], - hw_index, m_state.dbg.__bcr[hw_index]); - - kret = SetDBGState(false); - - if (kret == KERN_SUCCESS) - return true; - } - } - return false; -} - -// ARM v7 watchpoints may be either word-size or double-word-size. -// It's implementation defined which they can handle. It looks like on an -// armv8 device, armv7 processes can watch dwords. But on a genuine armv7 -// device I tried, only word watchpoints are supported. - -#if defined(__arm64__) || defined(__aarch64__) -#define WATCHPOINTS_ARE_DWORD 1 -#else -#undef WATCHPOINTS_ARE_DWORD -#endif - -uint32_t DNBArchMachARM::EnableHardwareWatchpoint(nub_addr_t addr, - nub_size_t size, bool read, - bool write, - bool also_set_on_task) { - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(" - "addr = 0x%8.8llx, size = %zu, read = %u, " - "write = %u)", - (uint64_t)addr, size, read, write); - - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - // Can't watch zero bytes - if (size == 0) - return INVALID_NUB_HW_INDEX; - - // We must watch for either read or write - if (read == false && write == false) - return INVALID_NUB_HW_INDEX; - - // Otherwise, can't watch more than 8 bytes per WVR/WCR pair - if (size > 8) - return INVALID_NUB_HW_INDEX; - -// Treat arm watchpoints as having an 8-byte alignment requirement. You can put -// a watchpoint on a 4-byte -// offset address but you can only watch 4 bytes with that watchpoint. - -// arm watchpoints on an 8-byte (double word) aligned addr can watch any bytes -// in that -// 8-byte long region of memory. They can watch the 1st byte, the 2nd byte, 3rd -// byte, etc, or any -// combination therein by setting the bits in the BAS [12:5] (Byte Address -// Select) field of -// the DBGWCRn_EL1 reg for the watchpoint. - -// If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to -// monitor a larger region -// of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield -// then selects a larger -// range of bytes, instead of individual bytes. See the ARMv8 Debug -// Architecture manual for details. -// This implementation does not currently use the MASK bits; the largest single -// region watched by a single -// watchpoint right now is 8-bytes. - -#if defined(WATCHPOINTS_ARE_DWORD) - nub_addr_t aligned_wp_address = addr & ~0x7; - uint32_t addr_dword_offset = addr & 0x7; - const int max_watchpoint_size = 8; -#else - nub_addr_t aligned_wp_address = addr & ~0x3; - uint32_t addr_dword_offset = addr & 0x3; - const int max_watchpoint_size = 4; -#endif - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint " - "aligned_wp_address is 0x%llx and " - "addr_dword_offset is 0x%x", - (uint64_t)aligned_wp_address, addr_dword_offset); - - // Do we need to split up this logical watchpoint into two hardware watchpoint - // registers? - // e.g. a watchpoint of length 4 on address 6. We need do this with - // one watchpoint on address 0 with bytes 6 & 7 being monitored - // one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored - - if (addr_dword_offset + size > max_watchpoint_size) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" - "EnableHardwareWatchpoint(addr = " - "0x%8.8llx, size = %zu) needs two " - "hardware watchpoints slots to monitor", - (uint64_t)addr, size); - int low_watchpoint_size = max_watchpoint_size - addr_dword_offset; - int high_watchpoint_size = addr_dword_offset + size - max_watchpoint_size; - - uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, - write, also_set_on_task); - if (lo == INVALID_NUB_HW_INDEX) - return INVALID_NUB_HW_INDEX; - uint32_t hi = EnableHardwareWatchpoint( - aligned_wp_address + max_watchpoint_size, high_watchpoint_size, read, - write, also_set_on_task); - if (hi == INVALID_NUB_HW_INDEX) { - DisableHardwareWatchpoint(lo, also_set_on_task); - return INVALID_NUB_HW_INDEX; - } - // Tag this lo->hi mapping in our database. - LoHi[lo] = hi; - return lo; - } - - // At this point - // 1 aligned_wp_address is the requested address rounded down to 8-byte - // alignment - // 2 addr_dword_offset is the offset into that double word (8-byte) region - // that we are watching - // 3 size is the number of bytes within that 8-byte region that we are - // watching - - // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the - // above. - // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, - // etc, up to 0b11111111 for 8. - // then we shift those bits left by the offset into this dword that we are - // interested in. - // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of - // 0b11110000. - uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset; - - // Read the debug state - kern_return_t kret = GetDBGState(true); - - if (kret == KERN_SUCCESS) { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i = 0; i < num_hw_watchpoints; ++i) { - if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw watchpoint slot (in i) - } - - // See if we found an available hw watchpoint slot above - if (i < num_hw_watchpoints) { - // DumpDBGState(m_state.dbg); - - // Clear any previous LoHi joined-watchpoint that may have been in use - LoHi[i] = 0; - - // shift our Byte Address Select bits up to the correct bit range for the - // DBGWCRn_EL1 - byte_address_select = byte_address_select << 5; - - // Make sure bits 1:0 are clear in our address - m_state.dbg.__wvr[i] = aligned_wp_address; // DVA (Data Virtual Address) - m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow - // the DVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; - - DNBLogThreadedIf( - LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() adding " - "watchpoint on address 0x%llx with control register " - "value 0x%x", - (uint64_t)m_state.dbg.__wvr[i], (uint32_t)m_state.dbg.__wcr[i]); - - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us - // automatically, don't need to do it here. - - kret = SetDBGState(also_set_on_task); - // DumpDBGState(m_state.dbg); - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" - "EnableHardwareWatchpoint() " - "SetDBGState() => 0x%8.8x.", - kret); - - if (kret == KERN_SUCCESS) - return i; - } else { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" - "EnableHardwareWatchpoint(): All " - "hardware resources (%u) are in use.", - num_hw_watchpoints); - } - } - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchMachARM::ReenableHardwareWatchpoint(uint32_t hw_index) { - // If this logical watchpoint # is actually implemented using - // two hardware watchpoint registers, re-enable both of them. - - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { - return ReenableHardwareWatchpoint_helper(hw_index) && - ReenableHardwareWatchpoint_helper(LoHi[hw_index]); - } else { - return ReenableHardwareWatchpoint_helper(hw_index); - } -} - -bool DNBArchMachARM::ReenableHardwareWatchpoint_helper(uint32_t hw_index) { - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; - - m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr; - m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control; - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( " - "%u ) - WVR%u = 0x%8.8llx WCR%u = " - "0x%8.8llx", - hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], - hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us - // automatically, don't need to do it here. - - kret = SetDBGState(false); - - return (kret == KERN_SUCCESS); -} - -bool DNBArchMachARM::DisableHardwareWatchpoint(uint32_t hw_index, - bool also_set_on_task) { - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { - return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task) && - DisableHardwareWatchpoint_helper(LoHi[hw_index], also_set_on_task); - } else { - return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task); - } -} - -bool DNBArchMachARM::DisableHardwareWatchpoint_helper(uint32_t hw_index, - bool also_set_on_task) { - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; - - m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index]; - m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index]; - - m_state.dbg.__wvr[hw_index] = 0; - m_state.dbg.__wcr[hw_index] = 0; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint(" - " %u ) - WVR%u = 0x%8.8llx WCR%u = " - "0x%8.8llx", - hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], - hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - - kret = SetDBGState(also_set_on_task); - - return (kret == KERN_SUCCESS); -} - -// Returns -1 if the trailing bit patterns are not one of: -// { 0b???1, 0b??10, 0b?100, 0b1000 }. -static inline int32_t LowestBitSet(uint32_t val) { - for (unsigned i = 0; i < 4; ++i) { - if (bit(val, i)) - return i; - } - return -1; -} - -// Iterate through the debug registers; return the index of the first watchpoint -// whose address matches. -// As a side effect, the starting address as understood by the debugger is -// returned which could be -// different from 'addr' passed as an in/out argument. -uint32_t DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) { - // Read the debug state - kern_return_t kret = GetDBGState(true); - // DumpDBGState(m_state.dbg); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", - kret); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", - (uint64_t)addr); - -// This is the watchpoint value to match against, i.e., word address. -#if defined(WATCHPOINTS_ARE_DWORD) - nub_addr_t wp_val = addr & ~((nub_addr_t)7); -#else - nub_addr_t wp_val = addr & ~((nub_addr_t)3); -#endif - if (kret == KERN_SUCCESS) { - DBG &debug_state = m_state.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) { - nub_addr_t wp_addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" - "GetHardwareWatchpointHit() slot: %u " - "(addr = 0x%llx).", - i, (uint64_t)wp_addr); - if (wp_val == wp_addr) { -#if defined(WATCHPOINTS_ARE_DWORD) - uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); -#else - uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5); -#endif - - // Sanity check the byte_mask, first. - if (LowestBitSet(byte_mask) < 0) - continue; - - // Compute the starting address (from the point of view of the - // debugger). - addr = wp_addr + LowestBitSet(byte_mask); - return i; - } - } - } - return INVALID_NUB_HW_INDEX; -} - -nub_addr_t DNBArchMachARM::GetWatchpointAddressByIndex(uint32_t hw_index) { - kern_return_t kret = GetDBGState(true); - if (kret != KERN_SUCCESS) - return INVALID_NUB_ADDRESS; - const uint32_t num = NumSupportedHardwareWatchpoints(); - if (hw_index >= num) - return INVALID_NUB_ADDRESS; - if (IsWatchpointEnabled(m_state.dbg, hw_index)) - return GetWatchAddress(m_state.dbg, hw_index); - return INVALID_NUB_ADDRESS; -} - -bool DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, - uint32_t hw_index) { - // Watchpoint Control Registers, bitfield definitions - // ... - // Bits Value Description - // [0] 0 Watchpoint disabled - // 1 Watchpoint enabled. - return (debug_state.__wcr[hw_index] & 1u); -} - -nub_addr_t DNBArchMachARM::GetWatchAddress(const DBG &debug_state, - uint32_t hw_index) { - // Watchpoint Value Registers, bitfield definitions - // Bits Description - // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) - // [1:0] RAZ/SBZP - return bits(debug_state.__wvr[hw_index], 31, 0); -} - -// Register information definitions for 32 bit ARMV7. -enum gpr_regnums { - gpr_r0 = 0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_sp, - gpr_lr, - gpr_pc, - gpr_cpsr -}; - -enum { - vfp_s0 = 0, - vfp_s1, - vfp_s2, - vfp_s3, - vfp_s4, - vfp_s5, - vfp_s6, - vfp_s7, - vfp_s8, - vfp_s9, - vfp_s10, - vfp_s11, - vfp_s12, - vfp_s13, - vfp_s14, - vfp_s15, - vfp_s16, - vfp_s17, - vfp_s18, - vfp_s19, - vfp_s20, - vfp_s21, - vfp_s22, - vfp_s23, - vfp_s24, - vfp_s25, - vfp_s26, - vfp_s27, - vfp_s28, - vfp_s29, - vfp_s30, - vfp_s31, - vfp_d0, - vfp_d1, - vfp_d2, - vfp_d3, - vfp_d4, - vfp_d5, - vfp_d6, - vfp_d7, - vfp_d8, - vfp_d9, - vfp_d10, - vfp_d11, - vfp_d12, - vfp_d13, - vfp_d14, - vfp_d15, - vfp_d16, - vfp_d17, - vfp_d18, - vfp_d19, - vfp_d20, - vfp_d21, - vfp_d22, - vfp_d23, - vfp_d24, - vfp_d25, - vfp_d26, - vfp_d27, - vfp_d28, - vfp_d29, - vfp_d30, - vfp_d31, - vfp_q0, - vfp_q1, - vfp_q2, - vfp_q3, - vfp_q4, - vfp_q5, - vfp_q6, - vfp_q7, - vfp_q8, - vfp_q9, - vfp_q10, - vfp_q11, - vfp_q12, - vfp_q13, - vfp_q14, - vfp_q15, -#if defined(__arm64__) || defined(__aarch64__) - vfp_fpsr, - vfp_fpcr, -#else - vfp_fpscr -#endif -}; - -enum { - exc_exception, - exc_fsr, - exc_far, -}; - -#define GPR_OFFSET_IDX(idx) (offsetof(DNBArchMachARM::GPR, __r[idx])) -#define GPR_OFFSET_NAME(reg) (offsetof(DNBArchMachARM::GPR, __##reg)) - -#define EXC_OFFSET(reg) \ - (offsetof(DNBArchMachARM::EXC, __##reg) + \ - offsetof(DNBArchMachARM::Context, exc)) - -// These macros will auto define the register name, alt name, register size, -// register offset, encoding, format and native register. This ensures that -// the register state structures are defined correctly and have the correct -// sizes and offsets. -#define DEFINE_GPR_IDX(idx, reg, alt, gen) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), \ - ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, NULL \ - } -#define DEFINE_GPR_NAME(reg, alt, gen, inval) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), \ - ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, inval \ - } - -// In case we are debugging to a debug target that the ability to -// change into the protected modes with folded registers (ABT, IRQ, -// FIQ, SYS, USR, etc..), we should invalidate r8-r14 if the CPSR -// gets modified. - -const char *g_invalidate_cpsr[] = {"r8", "r9", "r10", "r11", - "r12", "sp", "lr", NULL}; - -// General purpose registers -const DNBRegisterInfo DNBArchMachARM::g_gpr_registers[] = { - DEFINE_GPR_IDX(0, r0, "arg1", GENERIC_REGNUM_ARG1), - DEFINE_GPR_IDX(1, r1, "arg2", GENERIC_REGNUM_ARG2), - DEFINE_GPR_IDX(2, r2, "arg3", GENERIC_REGNUM_ARG3), - DEFINE_GPR_IDX(3, r3, "arg4", GENERIC_REGNUM_ARG4), - DEFINE_GPR_IDX(4, r4, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(5, r5, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(6, r6, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(7, r7, "fp", GENERIC_REGNUM_FP), - DEFINE_GPR_IDX(8, r8, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(9, r9, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(10, r10, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(11, r11, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(12, r12, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_NAME(sp, "r13", GENERIC_REGNUM_SP, NULL), - DEFINE_GPR_NAME(lr, "r14", GENERIC_REGNUM_RA, NULL), - DEFINE_GPR_NAME(pc, "r15", GENERIC_REGNUM_PC, NULL), - DEFINE_GPR_NAME(cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr)}; - -const char *g_contained_q0[]{"q0", NULL}; -const char *g_contained_q1[]{"q1", NULL}; -const char *g_contained_q2[]{"q2", NULL}; -const char *g_contained_q3[]{"q3", NULL}; -const char *g_contained_q4[]{"q4", NULL}; -const char *g_contained_q5[]{"q5", NULL}; -const char *g_contained_q6[]{"q6", NULL}; -const char *g_contained_q7[]{"q7", NULL}; -const char *g_contained_q8[]{"q8", NULL}; -const char *g_contained_q9[]{"q9", NULL}; -const char *g_contained_q10[]{"q10", NULL}; -const char *g_contained_q11[]{"q11", NULL}; -const char *g_contained_q12[]{"q12", NULL}; -const char *g_contained_q13[]{"q13", NULL}; -const char *g_contained_q14[]{"q14", NULL}; -const char *g_contained_q15[]{"q15", NULL}; - -const char *g_invalidate_q0[]{"q0", "d0", "d1", "s0", "s1", "s2", "s3", NULL}; -const char *g_invalidate_q1[]{"q1", "d2", "d3", "s4", "s5", "s6", "s7", NULL}; -const char *g_invalidate_q2[]{"q2", "d4", "d5", "s8", "s9", "s10", "s11", NULL}; -const char *g_invalidate_q3[]{"q3", "d6", "d7", "s12", - "s13", "s14", "s15", NULL}; -const char *g_invalidate_q4[]{"q4", "d8", "d9", "s16", - "s17", "s18", "s19", NULL}; -const char *g_invalidate_q5[]{"q5", "d10", "d11", "s20", - "s21", "s22", "s23", NULL}; -const char *g_invalidate_q6[]{"q6", "d12", "d13", "s24", - "s25", "s26", "s27", NULL}; -const char *g_invalidate_q7[]{"q7", "d14", "d15", "s28", - "s29", "s30", "s31", NULL}; -const char *g_invalidate_q8[]{"q8", "d16", "d17", NULL}; -const char *g_invalidate_q9[]{"q9", "d18", "d19", NULL}; -const char *g_invalidate_q10[]{"q10", "d20", "d21", NULL}; -const char *g_invalidate_q11[]{"q11", "d22", "d23", NULL}; -const char *g_invalidate_q12[]{"q12", "d24", "d25", NULL}; -const char *g_invalidate_q13[]{"q13", "d26", "d27", NULL}; -const char *g_invalidate_q14[]{"q14", "d28", "d29", NULL}; -const char *g_invalidate_q15[]{"q15", "d30", "d31", NULL}; - -#define VFP_S_OFFSET_IDX(idx) \ - (((idx) % 4) * 4) // offset into q reg: 0, 4, 8, 12 -#define VFP_D_OFFSET_IDX(idx) (((idx) % 2) * 8) // offset into q reg: 0, 8 -#define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX((idx)*4)) - -#define VFP_OFFSET_NAME(reg) \ - (offsetof(DNBArchMachARM::FPU, __##reg) + \ - offsetof(DNBArchMachARM::Context, vfp)) - -#define FLOAT_FORMAT Float - -#define DEFINE_VFP_S_IDX(idx) \ - e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, \ - VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM -#define DEFINE_VFP_D_IDX(idx) \ - e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, \ - VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM -#define DEFINE_VFP_Q_IDX(idx) \ - e_regSetVFP, vfp_q##idx, "q" #idx, NULL, Vector, VectorOfUInt8, 16, \ - VFP_Q_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_q##idx, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM - -// Floating point registers -const DNBRegisterInfo DNBArchMachARM::g_vfp_registers[] = { - {DEFINE_VFP_S_IDX(0), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_S_IDX(1), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_S_IDX(2), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_S_IDX(3), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_S_IDX(4), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_S_IDX(5), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_S_IDX(6), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_S_IDX(7), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_S_IDX(8), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_S_IDX(9), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_S_IDX(10), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_S_IDX(11), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_S_IDX(12), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_S_IDX(13), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_S_IDX(14), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_S_IDX(15), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_S_IDX(16), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_S_IDX(17), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_S_IDX(18), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_S_IDX(19), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_S_IDX(20), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_S_IDX(21), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_S_IDX(22), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_S_IDX(23), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_S_IDX(24), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_S_IDX(25), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_S_IDX(26), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_S_IDX(27), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_S_IDX(28), g_contained_q7, g_invalidate_q7}, - {DEFINE_VFP_S_IDX(29), g_contained_q7, g_invalidate_q7}, - {DEFINE_VFP_S_IDX(30), g_contained_q7, g_invalidate_q7}, - {DEFINE_VFP_S_IDX(31), g_contained_q7, g_invalidate_q7}, - - {DEFINE_VFP_D_IDX(0), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_D_IDX(1), g_contained_q0, g_invalidate_q0}, - {DEFINE_VFP_D_IDX(2), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_D_IDX(3), g_contained_q1, g_invalidate_q1}, - {DEFINE_VFP_D_IDX(4), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_D_IDX(5), g_contained_q2, g_invalidate_q2}, - {DEFINE_VFP_D_IDX(6), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_D_IDX(7), g_contained_q3, g_invalidate_q3}, - {DEFINE_VFP_D_IDX(8), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_D_IDX(9), g_contained_q4, g_invalidate_q4}, - {DEFINE_VFP_D_IDX(10), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_D_IDX(11), g_contained_q5, g_invalidate_q5}, - {DEFINE_VFP_D_IDX(12), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_D_IDX(13), g_contained_q6, g_invalidate_q6}, - {DEFINE_VFP_D_IDX(14), g_contained_q7, g_invalidate_q7}, - {DEFINE_VFP_D_IDX(15), g_contained_q7, g_invalidate_q7}, - {DEFINE_VFP_D_IDX(16), g_contained_q8, g_invalidate_q8}, - {DEFINE_VFP_D_IDX(17), g_contained_q8, g_invalidate_q8}, - {DEFINE_VFP_D_IDX(18), g_contained_q9, g_invalidate_q9}, - {DEFINE_VFP_D_IDX(19), g_contained_q9, g_invalidate_q9}, - {DEFINE_VFP_D_IDX(20), g_contained_q10, g_invalidate_q10}, - {DEFINE_VFP_D_IDX(21), g_contained_q10, g_invalidate_q10}, - {DEFINE_VFP_D_IDX(22), g_contained_q11, g_invalidate_q11}, - {DEFINE_VFP_D_IDX(23), g_contained_q11, g_invalidate_q11}, - {DEFINE_VFP_D_IDX(24), g_contained_q12, g_invalidate_q12}, - {DEFINE_VFP_D_IDX(25), g_contained_q12, g_invalidate_q12}, - {DEFINE_VFP_D_IDX(26), g_contained_q13, g_invalidate_q13}, - {DEFINE_VFP_D_IDX(27), g_contained_q13, g_invalidate_q13}, - {DEFINE_VFP_D_IDX(28), g_contained_q14, g_invalidate_q14}, - {DEFINE_VFP_D_IDX(29), g_contained_q14, g_invalidate_q14}, - {DEFINE_VFP_D_IDX(30), g_contained_q15, g_invalidate_q15}, - {DEFINE_VFP_D_IDX(31), g_contained_q15, g_invalidate_q15}, - - {DEFINE_VFP_Q_IDX(0), NULL, g_invalidate_q0}, - {DEFINE_VFP_Q_IDX(1), NULL, g_invalidate_q1}, - {DEFINE_VFP_Q_IDX(2), NULL, g_invalidate_q2}, - {DEFINE_VFP_Q_IDX(3), NULL, g_invalidate_q3}, - {DEFINE_VFP_Q_IDX(4), NULL, g_invalidate_q4}, - {DEFINE_VFP_Q_IDX(5), NULL, g_invalidate_q5}, - {DEFINE_VFP_Q_IDX(6), NULL, g_invalidate_q6}, - {DEFINE_VFP_Q_IDX(7), NULL, g_invalidate_q7}, - {DEFINE_VFP_Q_IDX(8), NULL, g_invalidate_q8}, - {DEFINE_VFP_Q_IDX(9), NULL, g_invalidate_q9}, - {DEFINE_VFP_Q_IDX(10), NULL, g_invalidate_q10}, - {DEFINE_VFP_Q_IDX(11), NULL, g_invalidate_q11}, - {DEFINE_VFP_Q_IDX(12), NULL, g_invalidate_q12}, - {DEFINE_VFP_Q_IDX(13), NULL, g_invalidate_q13}, - {DEFINE_VFP_Q_IDX(14), NULL, g_invalidate_q14}, - {DEFINE_VFP_Q_IDX(15), NULL, g_invalidate_q15}, - -#if defined(__arm64__) || defined(__aarch64__) - {e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpsr), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpcr), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL} -#else - {e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, - VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL} -#endif -}; - -// Exception registers - -const DNBRegisterInfo DNBArchMachARM::g_exc_registers[] = { - {e_regSetVFP, exc_exception, "exception", NULL, Uint, Hex, 4, - EXC_OFFSET(exception), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetVFP, exc_fsr, "fsr", NULL, Uint, Hex, 4, EXC_OFFSET(fsr), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetVFP, exc_far, "far", NULL, Uint, Hex, 4, EXC_OFFSET(far), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}}; - -// Number of registers in each register set -const size_t DNBArchMachARM::k_num_gpr_registers = - sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_vfp_registers = - sizeof(g_vfp_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_exc_registers = - sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_all_registers = - k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; - -// Register set definitions. The first definitions at register set index -// of zero is for all registers, followed by other registers sets. The -// register information for the all register set need not be filled in. -const DNBRegisterSetInfo DNBArchMachARM::g_reg_sets[] = { - {"ARM Registers", NULL, k_num_all_registers}, - {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, - {"Floating Point Registers", g_vfp_registers, k_num_vfp_registers}, - {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; -// Total number of register sets for this architecture -const size_t DNBArchMachARM::k_num_register_sets = - sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); - -const DNBRegisterSetInfo * -DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) { - *num_reg_sets = k_num_register_sets; - return g_reg_sets; -} - -bool DNBArchMachARM::GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) { - if (set == REGISTER_SET_GENERIC) { - switch (reg) { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_pc; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_sp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_r7; // is this the right reg? - break; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = gpr_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_cpsr; - break; - - default: - return false; - } - } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) { - value->info = *regInfo; - switch (set) { - case e_regSetGPR: - if (reg < k_num_gpr_registers) { - value->value.uint32 = m_state.context.gpr.__r[reg]; - return true; - } - break; - - case e_regSetVFP: - // "reg" is an index into the floating point register set at this point. - // We need to translate it up so entry 0 in the fp reg set is the same as - // vfp_s0 - // in the enumerated values for case statement below. - if (reg >= vfp_s0 && reg <= vfp_s31) { -#if defined(__arm64__) || defined(__aarch64__) - uint32_t *s_reg = - ((uint32_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_s0); - memcpy(&value->value.v_uint8, s_reg, 4); -#else - value->value.uint32 = m_state.context.vfp.__r[reg]; -#endif - return true; - } else if (reg >= vfp_d0 && reg <= vfp_d31) { -#if defined(__arm64__) || defined(__aarch64__) - uint64_t *d_reg = - ((uint64_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_d0); - memcpy(&value->value.v_uint8, d_reg, 8); -#else - uint32_t d_reg_idx = reg - vfp_d0; - uint32_t s_reg_idx = d_reg_idx * 2; - value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; - value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; -#endif - return true; - } else if (reg >= vfp_q0 && reg <= vfp_q15) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.v_uint8, - (uint8_t *)&m_state.context.vfp.__v[reg - vfp_q0], 16); -#else - uint32_t s_reg_idx = (reg - vfp_q0) * 4; - memcpy(&value->value.v_uint8, - (uint8_t *)&m_state.context.vfp.__r[s_reg_idx], 16); -#endif - return true; - } -#if defined(__arm64__) || defined(__aarch64__) - else if (reg == vfp_fpsr) { - value->value.uint32 = m_state.context.vfp.__fpsr; - return true; - } else if (reg == vfp_fpcr) { - value->value.uint32 = m_state.context.vfp.__fpcr; - return true; - } -#else - else if (reg == vfp_fpscr) { - value->value.uint32 = m_state.context.vfp.__fpscr; - return true; - } -#endif - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) { - value->value.uint32 = (&m_state.context.exc.__exception)[reg]; - return true; - } - break; - } - } - return false; -} - -bool DNBArchMachARM::SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) { - if (set == REGISTER_SET_GENERIC) { - switch (reg) { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_pc; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_sp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_r7; - break; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = gpr_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_cpsr; - break; - - default: - return false; - } - } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) { - switch (set) { - case e_regSetGPR: - if (reg < k_num_gpr_registers) { - m_state.context.gpr.__r[reg] = value->value.uint32; - success = true; - } - break; - - case e_regSetVFP: - // "reg" is an index into the floating point register set at this point. - // We need to translate it up so entry 0 in the fp reg set is the same as - // vfp_s0 - // in the enumerated values for case statement below. - if (reg >= vfp_s0 && reg <= vfp_s31) { -#if defined(__arm64__) || defined(__aarch64__) - uint32_t *s_reg = - ((uint32_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_s0); - memcpy(s_reg, &value->value.v_uint8, 4); -#else - m_state.context.vfp.__r[reg] = value->value.uint32; -#endif - success = true; - } else if (reg >= vfp_d0 && reg <= vfp_d31) { -#if defined(__arm64__) || defined(__aarch64__) - uint64_t *d_reg = - ((uint64_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_d0); - memcpy(d_reg, &value->value.v_uint8, 8); -#else - uint32_t d_reg_idx = reg - vfp_d0; - uint32_t s_reg_idx = d_reg_idx * 2; - m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; - m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; -#endif - success = true; - } else if (reg >= vfp_q0 && reg <= vfp_q15) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy((uint8_t *)&m_state.context.vfp.__v[reg - vfp_q0], - &value->value.v_uint8, 16); -#else - uint32_t s_reg_idx = (reg - vfp_q0) * 4; - memcpy((uint8_t *)&m_state.context.vfp.__r[s_reg_idx], - &value->value.v_uint8, 16); -#endif - success = true; - } -#if defined(__arm64__) || defined(__aarch64__) - else if (reg == vfp_fpsr) { - m_state.context.vfp.__fpsr = value->value.uint32; - success = true; - } else if (reg == vfp_fpcr) { - m_state.context.vfp.__fpcr = value->value.uint32; - success = true; - } -#else - else if (reg == vfp_fpscr) { - m_state.context.vfp.__fpscr = value->value.uint32; - success = true; - } -#endif - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) { - (&m_state.context.exc.__exception)[reg] = value->value.uint32; - success = true; - } - break; - } - } - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; -} - -kern_return_t DNBArchMachARM::GetRegisterState(int set, bool force) { - switch (set) { - case e_regSetALL: - return GetGPRState(force) | GetVFPState(force) | GetEXCState(force) | - GetDBGState(force); - case e_regSetGPR: - return GetGPRState(force); - case e_regSetVFP: - return GetVFPState(force); - case e_regSetEXC: - return GetEXCState(force); - case e_regSetDBG: - return GetDBGState(force); - default: - break; - } - return KERN_INVALID_ARGUMENT; -} - -kern_return_t DNBArchMachARM::SetRegisterState(int set) { - // Make sure we have a valid context to set. - kern_return_t err = GetRegisterState(set, false); - if (err != KERN_SUCCESS) - return err; - - switch (set) { - case e_regSetALL: - return SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false); - case e_regSetGPR: - return SetGPRState(); - case e_regSetVFP: - return SetVFPState(); - case e_regSetEXC: - return SetEXCState(); - case e_regSetDBG: - return SetDBGState(false); - default: - break; - } - return KERN_INVALID_ARGUMENT; -} - -bool DNBArchMachARM::RegisterSetStateIsValid(int set) const { - return m_state.RegsAreValid(set); -} - -nub_size_t DNBArchMachARM::GetRegisterContext(void *buf, nub_size_t buf_len) { - nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + - sizeof(m_state.context.exc); - - if (buf && buf_len) { - if (size > buf_len) - size = buf_len; - - bool force = false; - if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) - return 0; - - // Copy each struct individually to avoid any padding that might be between - // the structs in m_state.context - uint8_t *p = (uint8_t *)buf; - ::memcpy(p, &m_state.context.gpr, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy(p, &m_state.context.vfp, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy(p, &m_state.context.exc, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert(bytes_written == size); - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, - (uint64_t)buf_len, (uint64_t)size); - // Return the size of the register context even if NULL was passed in - return size; -} - -nub_size_t DNBArchMachARM::SetRegisterContext(const void *buf, - nub_size_t buf_len) { - nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + - sizeof(m_state.context.exc); - - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) { - if (size > buf_len) - size = buf_len; - - // Copy each struct individually to avoid any padding that might be between - // the structs in m_state.context - uint8_t *p = const_cast(reinterpret_cast(buf)); - ::memcpy(&m_state.context.gpr, p, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy(&m_state.context.vfp, p, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy(&m_state.context.exc, p, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - reinterpret_cast(buf); - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert(bytes_written == size); - - if (SetGPRState() | SetVFPState() | SetEXCState()) - return 0; - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, - (uint64_t)buf_len, (uint64_t)size); - return size; -} - -uint32_t DNBArchMachARM::SaveRegisterState() { - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf( - LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " - "(SetGPRState() for stop_count = %u)", - m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - // Always re-read the registers because above we call thread_abort_safely(); - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: " - "GPR regs failed to read: %u ", - kret); - } else if ((kret = GetVFPState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: " - "%s regs failed to read: %u", - "VFP", kret); - } else { - const uint32_t save_id = GetNextRegisterStateSaveID(); - m_saved_register_states[save_id] = m_state.context; - return save_id; - } - return UINT32_MAX; -} - -bool DNBArchMachARM::RestoreRegisterState(uint32_t save_id) { - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) { - m_state.context.gpr = pos->second.gpr; - m_state.context.vfp = pos->second.vfp; - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::RestoreRegisterState " - "(save_id = %u) error: GPR regs failed to " - "write: %u", - save_id, kret); - success = false; - } else if ((kret = SetVFPState()) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::RestoreRegisterState " - "(save_id = %u) error: %s regs failed to " - "write: %u", - save_id, "VFP", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; - } - return false; -} - -#endif // #if defined (__arm__) diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h deleted file mode 100644 index 9c27e988ea05..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ /dev/null @@ -1,275 +0,0 @@ -//===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H -#define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include "DNBArch.h" - -#include - -class MachThread; - -class DNBArchMachARM : public DNBArchProtocol { -public: - enum { kMaxNumThumbITBreakpoints = 4 }; - - DNBArchMachARM(MachThread *thread) - : m_thread(thread), m_state(), m_disabled_watchpoints(), - m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS), - m_last_decode_pc(INVALID_NUB_ADDRESS), m_watchpoint_hw_index(-1), - m_watchpoint_did_occur(false), - m_watchpoint_resume_single_step_enabled(false), - m_saved_register_states() { - m_disabled_watchpoints.resize(16); - memset(&m_dbg_save, 0, sizeof(m_dbg_save)); -#if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) - ThumbStaticsInit(&m_last_decode_thumb); -#endif - } - - virtual ~DNBArchMachARM() {} - - static void Initialize(); - static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); - - bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) override; - bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) override; - nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override; - nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override; - uint32_t SaveRegisterState() override; - bool RestoreRegisterState(uint32_t save_id) override; - - kern_return_t GetRegisterState(int set, bool force) override; - kern_return_t SetRegisterState(int set) override; - bool RegisterSetStateIsValid(int set) const override; - - uint64_t GetPC(uint64_t failValue) override; // Get program counter - kern_return_t SetPC(uint64_t value) override; - uint64_t GetSP(uint64_t failValue) override; // Get stack pointer - void ThreadWillResume() override; - bool ThreadDidStop() override; - bool NotifyException(MachException::Data &exc) override; - - static DNBArchProtocol *Create(MachThread *thread); - static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); - static uint32_t GetCPUType(); - - uint32_t NumSupportedHardwareBreakpoints() override; - uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, - bool also_set_on_task) override; - bool DisableHardwareBreakpoint(uint32_t hw_break_index, - bool also_set_on_task) override; - - uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read, - bool write, bool also_set_on_task) override; - bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task) override; - virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, - bool also_set_on_task); - virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); - virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); - - virtual bool StepNotComplete() override; - uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) override; - -#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) - typedef arm_debug_state32_t DBG; -#else - typedef arm_debug_state_t DBG; -#endif - -protected: - kern_return_t EnableHardwareSingleStep(bool enable); - kern_return_t SetSingleStepSoftwareBreakpoints(); - - bool ConditionPassed(uint8_t condition, uint32_t cpsr); -#if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) - bool ComputeNextPC(nub_addr_t currentPC, - arm_decoded_instruction_t decodedInstruction, - bool currentPCIsThumb, nub_addr_t *targetPC); - arm_error_t DecodeInstructionUsingDisassembler( - nub_addr_t curr_pc, uint32_t curr_cpsr, - arm_decoded_instruction_t *decodedInstruction, - thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc); - void DecodeITBlockInstructions(nub_addr_t curr_pc); -#endif - void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, - uint32_t cpsr, - bool currentPCIsThumb, - nub_addr_t *nextPC, - bool *nextPCIsThumb); - - enum RegisterSet { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, // ARM_THREAD_STATE - e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__) - e_regSetEXC, // ARM_EXCEPTION_STATE - e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__) - kNumRegisterSets - }; - - enum { Read = 0, Write = 1, kNumErrors = 2 }; - - typedef arm_thread_state_t GPR; -#if defined(__arm64__) || defined(__aarch64__) - typedef arm_neon_state_t FPU; -#else - typedef arm_vfp_state_t FPU; -#endif - typedef arm_exception_state_t EXC; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_vfp_registers[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets[]; - - static const size_t k_num_gpr_registers; - static const size_t k_num_vfp_registers; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers; - static const size_t k_num_register_sets; - - struct Context { - GPR gpr; - FPU vfp; - EXC exc; - }; - - struct State { - Context context; - DBG dbg; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t vfp_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - State() { - uint32_t i; - for (i = 0; i < kNumErrors; i++) { - gpr_errs[i] = -1; - vfp_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); } - kern_return_t GetError(int set, uint32_t err_idx) const { - if (err_idx < kNumErrors) { - switch (set) { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: - return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] | - dbg_errs[err_idx]; - case e_regSetGPR: - return gpr_errs[err_idx]; - case e_regSetVFP: - return vfp_errs[err_idx]; - case e_regSetEXC: - return exc_errs[err_idx]; - case e_regSetDBG: - return dbg_errs[err_idx]; - default: - break; - } - } - return -1; - } - bool SetError(int set, uint32_t err_idx, kern_return_t err) { - if (err_idx < kNumErrors) { - switch (set) { - case e_regSetALL: - gpr_errs[err_idx] = err; - vfp_errs[err_idx] = err; - dbg_errs[err_idx] = err; - exc_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetVFP: - vfp_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetDBG: - dbg_errs[err_idx] = err; - return true; - default: - break; - } - } - return false; - } - bool RegsAreValid(int set) const { - return GetError(set, Read) == KERN_SUCCESS; - } - }; - - kern_return_t GetGPRState(bool force); - kern_return_t GetVFPState(bool force); - kern_return_t GetEXCState(bool force); - kern_return_t GetDBGState(bool force); - - kern_return_t SetGPRState(); - kern_return_t SetVFPState(); - kern_return_t SetEXCState(); - kern_return_t SetDBGState(bool also_set_on_task); - - bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); - nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index); - nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - - class disabled_watchpoint { - public: - disabled_watchpoint() { - addr = 0; - control = 0; - } - nub_addr_t addr; - uint32_t control; - }; - -protected: - MachThread *m_thread; - State m_state; - DBG m_dbg_save; - - // armv8 doesn't keep the disabled watchpoint values in the debug register - // context like armv7; - // we need to save them aside when we disable them temporarily. - std::vector m_disabled_watchpoints; - - nub_addr_t m_hw_single_chained_step_addr; - nub_addr_t m_last_decode_pc; - - // The following member variables should be updated atomically. - int32_t m_watchpoint_hw_index; - bool m_watchpoint_did_occur; - bool m_watchpoint_resume_single_step_enabled; - - typedef std::map SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (__arm__) -#endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp deleted file mode 100644 index 2b1d360dcae5..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ /dev/null @@ -1,2532 +0,0 @@ -//===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__i386__) || defined(__x86_64__) - -#include - -#include "DNBLog.h" -#include "MacOSX/i386/DNBArchImplI386.h" -#include "MachProcess.h" -#include "MachThread.h" - -extern "C" bool CPUHasAVX(); // Defined over in DNBArchImplX86_64.cpp -extern "C" bool CPUHasAVX512f(); // Defined over in DNBArchImplX86_64.cpp -#if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG) -enum debugState { debugStateUnknown, debugStateOff, debugStateOn }; - -static debugState sFPUDebugState = debugStateUnknown; -static debugState sAVXForceState = debugStateUnknown; - -static bool DebugFPURegs() { - if (sFPUDebugState == debugStateUnknown) { - if (getenv("DNB_DEBUG_FPU_REGS")) - sFPUDebugState = debugStateOn; - else - sFPUDebugState = debugStateOff; - } - - return (sFPUDebugState == debugStateOn); -} - -static bool ForceAVXRegs() { - if (sFPUDebugState == debugStateUnknown) { - if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) - sAVXForceState = debugStateOn; - else - sAVXForceState = debugStateOff; - } - - return (sAVXForceState == debugStateOn); -} - -#define DEBUG_FPU_REGS (DebugFPURegs()) -#define FORCE_AVX_REGS (ForceAVXRegs()) -#else -#define DEBUG_FPU_REGS (0) -#define FORCE_AVX_REGS (0) -#endif - -enum { - gpr_eax = 0, - gpr_ebx = 1, - gpr_ecx = 2, - gpr_edx = 3, - gpr_edi = 4, - gpr_esi = 5, - gpr_ebp = 6, - gpr_esp = 7, - gpr_ss = 8, - gpr_eflags = 9, - gpr_eip = 10, - gpr_cs = 11, - gpr_ds = 12, - gpr_es = 13, - gpr_fs = 14, - gpr_gs = 15, - gpr_ax, - gpr_bx, - gpr_cx, - gpr_dx, - gpr_di, - gpr_si, - gpr_bp, - gpr_sp, - gpr_ah, - gpr_bh, - gpr_ch, - gpr_dh, - gpr_al, - gpr_bl, - gpr_cl, - gpr_dl, - gpr_dil, - gpr_sil, - gpr_bpl, - gpr_spl, - k_num_gpr_regs -}; - -enum { - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_ymm0, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - fpu_k0, - fpu_k1, - fpu_k2, - fpu_k3, - fpu_k4, - fpu_k5, - fpu_k6, - fpu_k7, - fpu_zmm0, - fpu_zmm1, - fpu_zmm2, - fpu_zmm3, - fpu_zmm4, - fpu_zmm5, - fpu_zmm6, - fpu_zmm7, - k_num_fpu_regs, - - // Aliases - fpu_fctrl = fpu_fcw, - fpu_fstat = fpu_fsw, - fpu_ftag = fpu_ftw, - fpu_fiseg = fpu_cs, - fpu_fioff = fpu_ip, - fpu_foseg = fpu_ds, - fpu_fooff = fpu_dp -}; - -enum { - exc_trapno, - exc_err, - exc_faultvaddr, - k_num_exc_regs, -}; - -enum { - ehframe_eax = 0, - ehframe_ecx, - ehframe_edx, - ehframe_ebx, - - // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed - // from DWARF. - // It's due to an ancient compiler bug in the output of the eh_frame. - // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp. - // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp. - ehframe_ebp, - ehframe_esp, - ehframe_esi, - ehframe_edi, - ehframe_eip, - ehframe_eflags -}; - -enum { - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7, - dwarf_ymm0 = dwarf_xmm0, - dwarf_ymm1 = dwarf_xmm1, - dwarf_ymm2 = dwarf_xmm2, - dwarf_ymm3 = dwarf_xmm3, - dwarf_ymm4 = dwarf_xmm4, - dwarf_ymm5 = dwarf_xmm5, - dwarf_ymm6 = dwarf_xmm6, - dwarf_ymm7 = dwarf_xmm7, - dwarf_zmm0 = dwarf_xmm0, - dwarf_zmm1 = dwarf_xmm1, - dwarf_zmm2 = dwarf_xmm2, - dwarf_zmm3 = dwarf_xmm3, - dwarf_zmm4 = dwarf_xmm4, - dwarf_zmm5 = dwarf_xmm5, - dwarf_zmm6 = dwarf_xmm6, - dwarf_zmm7 = dwarf_xmm7, - dwarf_k0 = 118, - dwarf_k1, - dwarf_k2, - dwarf_k3, - dwarf_k4, - dwarf_k5, - dwarf_k6, - dwarf_k7, -}; - -enum { - debugserver_eax = 0, - debugserver_ecx = 1, - debugserver_edx = 2, - debugserver_ebx = 3, - debugserver_esp = 4, - debugserver_ebp = 5, - debugserver_esi = 6, - debugserver_edi = 7, - debugserver_eip = 8, - debugserver_eflags = 9, - debugserver_cs = 10, - debugserver_ss = 11, - debugserver_ds = 12, - debugserver_es = 13, - debugserver_fs = 14, - debugserver_gs = 15, - debugserver_stmm0 = 16, - debugserver_stmm1 = 17, - debugserver_stmm2 = 18, - debugserver_stmm3 = 19, - debugserver_stmm4 = 20, - debugserver_stmm5 = 21, - debugserver_stmm6 = 22, - debugserver_stmm7 = 23, - debugserver_fctrl = 24, - debugserver_fcw = debugserver_fctrl, - debugserver_fstat = 25, - debugserver_fsw = debugserver_fstat, - debugserver_ftag = 26, - debugserver_ftw = debugserver_ftag, - debugserver_fiseg = 27, - debugserver_fpu_cs = debugserver_fiseg, - debugserver_fioff = 28, - debugserver_ip = debugserver_fioff, - debugserver_foseg = 29, - debugserver_fpu_ds = debugserver_foseg, - debugserver_fooff = 30, - debugserver_dp = debugserver_fooff, - debugserver_fop = 31, - debugserver_xmm0 = 32, - debugserver_xmm1 = 33, - debugserver_xmm2 = 34, - debugserver_xmm3 = 35, - debugserver_xmm4 = 36, - debugserver_xmm5 = 37, - debugserver_xmm6 = 38, - debugserver_xmm7 = 39, - debugserver_mxcsr = 40, - debugserver_mm0 = 41, - debugserver_mm1 = 42, - debugserver_mm2 = 43, - debugserver_mm3 = 44, - debugserver_mm4 = 45, - debugserver_mm5 = 46, - debugserver_mm6 = 47, - debugserver_mm7 = 48, - debugserver_ymm0 = debugserver_xmm0, - debugserver_ymm1 = debugserver_xmm1, - debugserver_ymm2 = debugserver_xmm2, - debugserver_ymm3 = debugserver_xmm3, - debugserver_ymm4 = debugserver_xmm4, - debugserver_ymm5 = debugserver_xmm5, - debugserver_ymm6 = debugserver_xmm6, - debugserver_ymm7 = debugserver_xmm7, - debugserver_zmm0 = debugserver_xmm0, - debugserver_zmm1 = debugserver_xmm1, - debugserver_zmm2 = debugserver_xmm2, - debugserver_zmm3 = debugserver_xmm3, - debugserver_zmm4 = debugserver_xmm4, - debugserver_zmm5 = debugserver_xmm5, - debugserver_zmm6 = debugserver_xmm6, - debugserver_zmm7 = debugserver_xmm7, - debugserver_k0 = 118, - debugserver_k1 = 119, - debugserver_k2 = 120, - debugserver_k3 = 121, - debugserver_k4 = 122, - debugserver_k5 = 123, - debugserver_k6 = 124, - debugserver_k7 = 125, -}; - -uint64_t DNBArchImplI386::GetPC(uint64_t failValue) { - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__eip; - return failValue; -} - -kern_return_t DNBArchImplI386::SetPC(uint64_t value) { - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) { - m_state.context.gpr.__eip = static_cast(value); - err = SetGPRState(); - } - return err == KERN_SUCCESS; -} - -uint64_t DNBArchImplI386::GetSP(uint64_t failValue) { - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__esp; - return failValue; -} - -// Uncomment the value below to verify the values in the debugger. -//#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED -//#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg - -kern_return_t DNBArchImplI386::GetGPRState(bool force) { - if (force || m_state.GetError(e_regSetGPR, Read)) { -#if DEBUG_GPR_VALUES - SET_GPR(eax); - SET_GPR(ebx); - SET_GPR(ecx); - SET_GPR(edx); - SET_GPR(edi); - SET_GPR(esi); - SET_GPR(ebp); - SET_GPR(esp); - SET_GPR(ss); - SET_GPR(eflags); - SET_GPR(eip); - SET_GPR(cs); - SET_GPR(ds); - SET_GPR(es); - SET_GPR(fs); - SET_GPR(gs); - m_state.SetError(e_regSetGPR, Read, 0); -#else - mach_msg_type_number_t count = e_regSetWordSizeGPR; - m_state.SetError( - e_regSetGPR, Read, - ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, &count)); -#endif - } - return m_state.GetError(e_regSetGPR, Read); -} - -// Uncomment the value below to verify the values in the debugger. -//#define DEBUG_FPU_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED - -kern_return_t DNBArchImplI386::GetFPUState(bool force) { - if (force || m_state.GetError(e_regSetFPU, Read)) { - if (DEBUG_FPU_REGS) { - - m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; - m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; - m_state.context.fpu.no_avx.__fpu_ftw = 1; - m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; - m_state.context.fpu.no_avx.__fpu_fop = 2; - m_state.context.fpu.no_avx.__fpu_ip = 3; - m_state.context.fpu.no_avx.__fpu_cs = 4; - m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; - m_state.context.fpu.no_avx.__fpu_dp = 6; - m_state.context.fpu.no_avx.__fpu_ds = 7; - m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; - m_state.context.fpu.no_avx.__fpu_mxcsr = 8; - m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; - for (int i = 0; i < 16; ++i) { - if (i < 10) { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; - } else { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; - } - - m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; - m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; - m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; - m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; - m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; - m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; - m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; - m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; - } - for (int i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i) - m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_reserved1 = -1; - - if (CPUHasAVX() || FORCE_AVX_REGS) { - for (int i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); - ++i) - m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; - - for (int i = 0; i < 16; ++i) { - m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0'; - m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1'; - m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2'; - m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3'; - m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4'; - m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5'; - m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6'; - m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7'; - } - } - if (CPUHasAVX512f() || FORCE_AVX_REGS) { - for (int i = 0; i < 8; ++i) { - m_state.context.fpu.avx512f.__fpu_k0.__opmask_reg[i] = '0'; - m_state.context.fpu.avx512f.__fpu_k1.__opmask_reg[i] = '1'; - m_state.context.fpu.avx512f.__fpu_k2.__opmask_reg[i] = '2'; - m_state.context.fpu.avx512f.__fpu_k3.__opmask_reg[i] = '3'; - m_state.context.fpu.avx512f.__fpu_k4.__opmask_reg[i] = '4'; - m_state.context.fpu.avx512f.__fpu_k5.__opmask_reg[i] = '5'; - m_state.context.fpu.avx512f.__fpu_k6.__opmask_reg[i] = '6'; - m_state.context.fpu.avx512f.__fpu_k7.__opmask_reg[i] = '7'; - } - - for (int i = 0; i < 32; ++i) { - m_state.context.fpu.avx512f.__fpu_zmmh0.__ymm_reg[i] = '0'; - m_state.context.fpu.avx512f.__fpu_zmmh1.__ymm_reg[i] = '1'; - m_state.context.fpu.avx512f.__fpu_zmmh2.__ymm_reg[i] = '2'; - m_state.context.fpu.avx512f.__fpu_zmmh3.__ymm_reg[i] = '3'; - m_state.context.fpu.avx512f.__fpu_zmmh4.__ymm_reg[i] = '4'; - m_state.context.fpu.avx512f.__fpu_zmmh5.__ymm_reg[i] = '5'; - m_state.context.fpu.avx512f.__fpu_zmmh6.__ymm_reg[i] = '6'; - m_state.context.fpu.avx512f.__fpu_zmmh7.__ymm_reg[i] = '7'; - } - } - m_state.SetError(e_regSetFPU, Read, 0); - } else { - mach_msg_type_number_t count = e_regSetWordSizeFPU; - int flavor = __i386_FLOAT_STATE; - - // On a machine with the AVX512 register set, a process only gets a - // full AVX512 register context after it uses the AVX512 registers; - // if the process has not yet triggered this change, trying to fetch - // the AVX512 registers will fail. Fall through to fetching the AVX - // registers. - if (CPUHasAVX512f() || FORCE_AVX_REGS) { - count = e_regSetWordSizeAVX512f; - flavor = __i386_AVX512F_STATE; - m_state.SetError(e_regSetFPU, Read, - ::thread_get_state(m_thread->MachPortNumber(), flavor, - (thread_state_t)&m_state.context.fpu, - &count)); - DNBLogThreadedIf(LOG_THREAD, - "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x", - m_thread->MachPortNumber(), flavor, (uint32_t)count, - m_state.GetError(e_regSetFPU, Read)); - if (m_state.GetError(e_regSetFPU, Read) == KERN_SUCCESS) - return m_state.GetError(e_regSetFPU, Read); - } - if (CPUHasAVX()) { - count = e_regSetWordSizeAVX; - flavor = __i386_AVX_STATE; - } - m_state.SetError(e_regSetFPU, Read, - ::thread_get_state(m_thread->MachPortNumber(), flavor, - (thread_state_t)&m_state.context.fpu, - &count)); - DNBLogThreadedIf(LOG_THREAD, - "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x", - m_thread->MachPortNumber(), flavor, (uint32_t)count, - m_state.GetError(e_regSetFPU, Read)); - } - } - return m_state.GetError(e_regSetFPU, Read); -} - -kern_return_t DNBArchImplI386::GetEXCState(bool force) { - if (force || m_state.GetError(e_regSetEXC, Read)) { - mach_msg_type_number_t count = e_regSetWordSizeEXC; - m_state.SetError( - e_regSetEXC, Read, - ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); -} - -kern_return_t DNBArchImplI386::SetGPRState() { - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf( - LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " - "(SetGPRState() for stop_count = %u)", - m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - m_state.SetError(e_regSetGPR, Write, - ::thread_set_state(m_thread->MachPortNumber(), - __i386_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, - e_regSetWordSizeGPR)); - return m_state.GetError(e_regSetGPR, Write); -} - -kern_return_t DNBArchImplI386::SetFPUState() { - if (DEBUG_FPU_REGS) { - m_state.SetError(e_regSetFPU, Write, 0); - return m_state.GetError(e_regSetFPU, Write); - } else { - int flavor = __i386_FLOAT_STATE; - mach_msg_type_number_t count = e_regSetWordSizeFPU; - if (CPUHasAVX512f() || FORCE_AVX_REGS) { - flavor = __i386_AVX512F_STATE; - count = e_regSetWordSizeAVX512f; - } else - if (CPUHasAVX()) { - flavor = __i386_AVX_STATE; - count = e_regSetWordSizeAVX; - } - - m_state.SetError(e_regSetFPU, Write, - ::thread_set_state(m_thread->MachPortNumber(), flavor, - (thread_state_t)&m_state.context.fpu, - count)); - return m_state.GetError(e_regSetFPU, Write); - } -} - -kern_return_t DNBArchImplI386::SetEXCState() { - m_state.SetError(e_regSetEXC, Write, - ::thread_set_state(m_thread->MachPortNumber(), - __i386_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, - e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); -} - -kern_return_t DNBArchImplI386::GetDBGState(bool force) { - if (force || m_state.GetError(e_regSetDBG, Read)) { - mach_msg_type_number_t count = e_regSetWordSizeDBG; - m_state.SetError( - e_regSetDBG, Read, - ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, - (thread_state_t)&m_state.context.dbg, &count)); - } - return m_state.GetError(e_regSetDBG, Read); -} - -kern_return_t DNBArchImplI386::SetDBGState(bool also_set_on_task) { - m_state.SetError(e_regSetDBG, Write, - ::thread_set_state(m_thread->MachPortNumber(), - __i386_DEBUG_STATE, - (thread_state_t)&m_state.context.dbg, - e_regSetWordSizeDBG)); - if (also_set_on_task) { - kern_return_t kret = ::task_set_state( - m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE, - (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); - if (kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed " - "to set debug control register state: " - "0x%8.8x.", - kret); - } - return m_state.GetError(e_regSetDBG, Write); -} - -void DNBArchImplI386::ThreadWillResume() { - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) { - // This is the primary thread, let the arch do anything it needs - EnableHardwareSingleStep(true); - } - - // Reset the debug status register, if necessary, before we resume. - kern_return_t kret = GetDBGState(false); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); - if (kret != KERN_SUCCESS) - return; - - DBG &debug_state = m_state.context.dbg; - bool need_reset = false; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - if (IsWatchpointHit(debug_state, i)) - need_reset = true; - - if (need_reset) { - ClearWatchpointHits(debug_state); - kret = SetDBGState(false); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret); - } -} - -bool DNBArchImplI386::ThreadDidStop() { - bool success = true; - - m_state.InvalidateAllRegisterStates(); - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) { - // This was the primary thread, we need to clear the trace - // bit if so. - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } else { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } - } - return success; -} - -bool DNBArchImplI386::NotifyException(MachException::Data &exc) { - switch (exc.exc_type) { - case EXC_BAD_ACCESS: - break; - case EXC_BAD_INSTRUCTION: - break; - case EXC_ARITHMETIC: - break; - case EXC_EMULATION: - break; - case EXC_SOFTWARE: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) { - // exc_code = EXC_I386_BPT - // - nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); - if (pc != INVALID_NUB_ADDRESS && pc > 0) { - pc -= 1; - // Check for a breakpoint at one byte prior to the current PC value - // since the PC will be just past the trap. - - DNBBreakpoint *bp = - m_thread->Process()->Breakpoints().FindByAddress(pc); - if (bp) { - // Backup the PC for i386 since the trap was taken and the PC - // is at the address following the single byte trap instruction. - if (m_state.context.gpr.__eip > 0) { - m_state.context.gpr.__eip = static_cast(pc); - // Write the new PC back out - SetGPRState(); - } - } - return true; - } - } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) { - // exc_code = EXC_I386_SGL - // - // Check whether this corresponds to a watchpoint hit event. - // If yes, set the exc_sub_code to the data break address. - nub_addr_t addr = 0; - uint32_t hw_index = GetHardwareWatchpointHit(addr); - if (hw_index != INVALID_NUB_HW_INDEX) { - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; - case EXC_SYSCALL: - break; - case EXC_MACH_SYSCALL: - break; - case EXC_RPC_ALERT: - break; - } - return false; -} - -uint32_t DNBArchImplI386::NumSupportedHardwareBreakpoints() { - // Available debug address registers: dr0, dr1, dr2, dr3. - return 4; -} - -uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() { - // Available debug address registers: dr0, dr1, dr2, dr3. - return 4; -} - -static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) { - uint32_t rw; - if (read) { - rw = 0x3; // READ or READ/WRITE - } else if (write) { - rw = 0x1; // WRITE - } else { - assert(0 && "read and write cannot both be false"); - } - - switch (size) { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - } - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - return 0; -} - -void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, - nub_addr_t addr, nub_size_t size, bool read, - bool write) { - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/gloabl enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io - // read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - debug_state.__dr7 |= - (1 << (2 * hw_index) | - size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); - uint32_t addr_32 = addr & 0xffffffff; - switch (hw_index) { - case 0: - debug_state.__dr0 = addr_32; - break; - case 1: - debug_state.__dr1 = addr_32; - break; - case 2: - debug_state.__dr2 = addr_32; - break; - case 3: - debug_state.__dr3 = addr_32; - break; - default: - assert(0 && - "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; -} - -void DNBArchImplI386::SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, - nub_addr_t addr, nub_size_t size) { - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/gloabl enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io - // read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index)); - uint32_t addr_32 = addr & 0xffffffff; - switch (hw_index) { - case 0: - debug_state.__dr0 = addr_32; - break; - case 1: - debug_state.__dr1 = addr_32; - break; - case 2: - debug_state.__dr2 = addr_32; - break; - case 3: - debug_state.__dr3 = addr_32; - break; - default: - assert(0 && - "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; -} - -uint32_t DNBArchImplI386::EnableHardwareBreakpoint(nub_addr_t addr, - nub_size_t size, - bool also_set_on_task) { - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchImplI386::EnableHardwareBreakpoint( addr = " - "0x%8.8llx, size = %llu )", - (uint64_t)addr, (uint64_t)size); - - const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); - // Read the debug state - kern_return_t kret = GetDBGState(false); - - if (kret != KERN_SUCCESS) { - return INVALID_NUB_HW_INDEX; - } - - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - DBG &debug_state = m_state.context.dbg; - for (i = 0; i < num_hw_breakpoints; ++i) { - if (IsWatchpointVacant(debug_state, i)) { - break; - } - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_breakpoints) { - DNBLogThreadedIf( - LOG_BREAKPOINTS, - "DNBArchImplI386::EnableHardwareBreakpoint( free slot = %u )", i); - - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - SetHardwareBreakpoint(debug_state, i, addr, size); - // Now set the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchImplI386::" - "EnableHardwareBreakpoint() " - "SetDBGState() => 0x%8.8x.", - kret); - - if (kret == KERN_SUCCESS) { - DNBLogThreadedIf( - LOG_BREAKPOINTS, - "DNBArchImplI386::EnableHardwareBreakpoint( enabled at slot = %u)", - i); - return i; - } - // Revert to the previous debug state voluntarily. The transaction - // coordinator knows that we have failed. - else { - m_state.context.dbg = GetDBGCheckpoint(); - } - } else { - DNBLogThreadedIf(LOG_BREAKPOINTS, - "DNBArchImplI386::EnableHardwareBreakpoint(addr = " - "0x%8.8llx, size = %llu) => all hardware breakpoint " - "resources are being used.", - (uint64_t)addr, (uint64_t)size); - } - - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchImplI386::DisableHardwareBreakpoint(uint32_t hw_index, - bool also_set_on_task) { - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); - if (kret == KERN_SUCCESS) { - DBG &debug_state = m_state.context.dbg; - if (hw_index < num_hw_points && - !IsWatchpointVacant(debug_state, hw_index)) { - - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - ClearWatchpoint(debug_state, hw_index); - // Now disable the watch point in the inferior. - kret = SetDBGState(true); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchImplI386::DisableHardwareBreakpoint( %u )", - hw_index); - - if (kret == KERN_SUCCESS) - return true; - else // Revert to the previous debug state voluntarily. The transaction - // coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } - } - return false; -} - -void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) { - debug_state.__dr7 &= ~(3 << (2 * hw_index)); - switch (hw_index) { - case 0: - debug_state.__dr0 = 0; - break; - case 1: - debug_state.__dr1 = 0; - break; - case 2: - debug_state.__dr2 = 0; - break; - case 3: - debug_state.__dr3 = 0; - break; - default: - assert(0 && - "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; -} - -bool DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state, - uint32_t hw_index) { - // Check dr7 (debug control register) for local/global enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0; -} - -// Resets local copy of debug status register to wait for the next debug -// exception. -void DNBArchImplI386::ClearWatchpointHits(DBG &debug_state) { - // See also IsWatchpointHit(). - debug_state.__dr6 = 0; - return; -} - -bool DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, - uint32_t hw_index) { - // Check dr6 (debug status register) whether a watchpoint hits: - // is watchpoint hit? - // | - // v - // dr0 -> bits{0} - // dr1 -> bits{1} - // dr2 -> bits{2} - // dr3 -> bits{3} - return (debug_state.__dr6 & (1 << hw_index)); -} - -nub_addr_t DNBArchImplI386::GetWatchAddress(const DBG &debug_state, - uint32_t hw_index) { - switch (hw_index) { - case 0: - return debug_state.__dr0; - case 1: - return debug_state.__dr1; - case 2: - return debug_state.__dr2; - case 3: - return debug_state.__dr3; - } - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - return 0; -} - -bool DNBArchImplI386::StartTransForHWP() { - if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) - DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d", - __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); - m_2pc_dbg_checkpoint = m_state.context.dbg; - m_2pc_trans_state = Trans_Pending; - return true; -} -bool DNBArchImplI386::RollbackTransForHWP() { - m_state.context.dbg = m_2pc_dbg_checkpoint; - if (m_2pc_trans_state != Trans_Pending) - DNBLogError("%s inconsistent state detected, expected %d, got: %d", - __FUNCTION__, Trans_Pending, m_2pc_trans_state); - m_2pc_trans_state = Trans_Rolled_Back; - kern_return_t kret = SetDBGState(false); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); - - return kret == KERN_SUCCESS; -} -bool DNBArchImplI386::FinishTransForHWP() { - m_2pc_trans_state = Trans_Done; - return true; -} -DNBArchImplI386::DBG DNBArchImplI386::GetDBGCheckpoint() { - return m_2pc_dbg_checkpoint; -} - -uint32_t DNBArchImplI386::EnableHardwareWatchpoint(nub_addr_t addr, - nub_size_t size, bool read, - bool write, - bool also_set_on_task) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(" - "addr = 0x%llx, size = %llu, read = %u, " - "write = %u)", - (uint64_t)addr, (uint64_t)size, read, write); - - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - // Can only watch 1, 2, 4, or 8 bytes. - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return INVALID_NUB_HW_INDEX; - - // We must watch for either read or write - if (!read && !write) - return INVALID_NUB_HW_INDEX; - - // Read the debug state - kern_return_t kret = GetDBGState(false); - - if (kret == KERN_SUCCESS) { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - DBG &debug_state = m_state.context.dbg; - for (i = 0; i < num_hw_watchpoints; ++i) { - if (IsWatchpointVacant(debug_state, i)) - break; - } - - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - SetWatchpoint(debug_state, i, addr, size, read, write); - // Now set the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" - "EnableHardwareWatchpoint() " - "SetDBGState() => 0x%8.8x.", - kret); - - if (kret == KERN_SUCCESS) - return i; - else // Revert to the previous debug state voluntarily. The transaction - // coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } else { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" - "EnableHardwareWatchpoint(): All " - "hardware resources (%u) are in use.", - num_hw_watchpoints); - } - } - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchImplI386::DisableHardwareWatchpoint(uint32_t hw_index, - bool also_set_on_task) { - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) { - DBG &debug_state = m_state.context.dbg; - if (hw_index < num_hw_points && - !IsWatchpointVacant(debug_state, hw_index)) { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - ClearWatchpoint(debug_state, hw_index); - // Now disable the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchImplI386::DisableHardwareWatchpoint( %u )", - hw_index); - - if (kret == KERN_SUCCESS) - return true; - else // Revert to the previous debug state voluntarily. The transaction - // coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } - } - return false; -} - -// Iterate through the debug status register; return the index of the first hit. -uint32_t DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) { - // Read the debug state - kern_return_t kret = GetDBGState(true); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", - kret); - if (kret == KERN_SUCCESS) { - DBG &debug_state = m_state.context.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) { - if (IsWatchpointHit(debug_state, i)) { - addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" - "GetHardwareWatchpointHit() found => " - "%u (addr = 0x%llx).", - i, (uint64_t)addr); - return i; - } - } - } - return INVALID_NUB_HW_INDEX; -} - -// Set the single step bit in the processor status register. -kern_return_t DNBArchImplI386::EnableHardwareSingleStep(bool enable) { - if (GetGPRState(false) == KERN_SUCCESS) { - const uint32_t trace_bit = 0x100u; - if (enable) - m_state.context.gpr.__eflags |= trace_bit; - else - m_state.context.gpr.__eflags &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); -} - -// Register information definitions - -#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ - { \ - e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 \ - } -#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ - { \ - e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - g_contained_##reg32, g_invalidate_##reg32 \ - } -#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ - { \ - e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - g_contained_##reg32, g_invalidate_##reg32 \ - } - -#define GPR_OFFSET(reg) (offsetof(DNBArchImplI386::GPR, __##reg)) -#define FPU_OFFSET(reg) \ - (offsetof(DNBArchImplI386::FPU, __fpu_##reg) + \ - offsetof(DNBArchImplI386::Context, fpu.no_avx)) -#define AVX_OFFSET(reg) \ - (offsetof(DNBArchImplI386::AVX, __fpu_##reg) + \ - offsetof(DNBArchImplI386::Context, fpu.avx)) -#define AVX512F_OFFSET(reg) \ - (offsetof(DNBArchImplI386::AVX512F, __fpu_##reg) + \ - offsetof(DNBArchImplI386::Context, fpu.avx512f)) -#define EXC_OFFSET(reg) \ - (offsetof(DNBArchImplI386::EXC, __##reg) + \ - offsetof(DNBArchImplI386::Context, exc)) - -#define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg)) -#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg)) -#define FPU_SIZE_MMST(reg) \ - (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg)) -#define FPU_SIZE_XMM(reg) \ - (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg)) -#define FPU_SIZE_YMM(reg) (32) -#define FPU_SIZE_ZMM(reg) (64) -#define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg)) - -// This does not accurately identify the location of ymm0...7 in -// Context.fpu.avx. That is because there is a bunch of padding -// in Context.fpu.avx that we don't need. Offset macros lay out -// the register state that Debugserver transmits to the debugger -// -- not to interpret the thread_get_state info. -#define AVX_OFFSET_YMM(n) (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n)) - -// TODO: Test this and come back. -#define AVX512F_OFFSET_ZMM(n) (AVX_OFFSET_YMM(7) + FPU_SIZE_XMM(xmm7) + (64 * n)) - -// These macros will auto define the register name, alt name, register size, -// register offset, encoding, format and native register. This ensures that -// the register state structures are defined correctly and have the correct -// sizes and offsets. - -const char *g_contained_eax[] = {"eax", NULL}; -const char *g_contained_ebx[] = {"ebx", NULL}; -const char *g_contained_ecx[] = {"ecx", NULL}; -const char *g_contained_edx[] = {"edx", NULL}; -const char *g_contained_edi[] = {"edi", NULL}; -const char *g_contained_esi[] = {"esi", NULL}; -const char *g_contained_ebp[] = {"ebp", NULL}; -const char *g_contained_esp[] = {"esp", NULL}; - -const char *g_invalidate_eax[] = {"eax", "ax", "ah", "al", NULL}; -const char *g_invalidate_ebx[] = {"ebx", "bx", "bh", "bl", NULL}; -const char *g_invalidate_ecx[] = {"ecx", "cx", "ch", "cl", NULL}; -const char *g_invalidate_edx[] = {"edx", "dx", "dh", "dl", NULL}; -const char *g_invalidate_edi[] = {"edi", "di", "dil", NULL}; -const char *g_invalidate_esi[] = {"esi", "si", "sil", NULL}; -const char *g_invalidate_ebp[] = {"ebp", "bp", "bpl", NULL}; -const char *g_invalidate_esp[] = {"esp", "sp", "spl", NULL}; - -// General purpose registers for 64 bit -const DNBRegisterInfo DNBArchImplI386::g_gpr_registers[] = { - {e_regSetGPR, gpr_eax, "eax", NULL, Uint, Hex, GPR_SIZE(eax), - GPR_OFFSET(eax), ehframe_eax, dwarf_eax, INVALID_NUB_REGNUM, - debugserver_eax, NULL, g_invalidate_eax}, - {e_regSetGPR, gpr_ebx, "ebx", NULL, Uint, Hex, GPR_SIZE(ebx), - GPR_OFFSET(ebx), ehframe_ebx, dwarf_ebx, INVALID_NUB_REGNUM, - debugserver_ebx, NULL, g_invalidate_ebx}, - {e_regSetGPR, gpr_ecx, "ecx", NULL, Uint, Hex, GPR_SIZE(ecx), - GPR_OFFSET(ecx), ehframe_ecx, dwarf_ecx, INVALID_NUB_REGNUM, - debugserver_ecx, NULL, g_invalidate_ecx}, - {e_regSetGPR, gpr_edx, "edx", NULL, Uint, Hex, GPR_SIZE(edx), - GPR_OFFSET(edx), ehframe_edx, dwarf_edx, INVALID_NUB_REGNUM, - debugserver_edx, NULL, g_invalidate_edx}, - {e_regSetGPR, gpr_edi, "edi", NULL, Uint, Hex, GPR_SIZE(edi), - GPR_OFFSET(edi), ehframe_edi, dwarf_edi, INVALID_NUB_REGNUM, - debugserver_edi, NULL, g_invalidate_edi}, - {e_regSetGPR, gpr_esi, "esi", NULL, Uint, Hex, GPR_SIZE(esi), - GPR_OFFSET(esi), ehframe_esi, dwarf_esi, INVALID_NUB_REGNUM, - debugserver_esi, NULL, g_invalidate_esi}, - {e_regSetGPR, gpr_ebp, "ebp", "fp", Uint, Hex, GPR_SIZE(ebp), - GPR_OFFSET(ebp), ehframe_ebp, dwarf_ebp, GENERIC_REGNUM_FP, - debugserver_ebp, NULL, g_invalidate_ebp}, - {e_regSetGPR, gpr_esp, "esp", "sp", Uint, Hex, GPR_SIZE(esp), - GPR_OFFSET(esp), ehframe_esp, dwarf_esp, GENERIC_REGNUM_SP, - debugserver_esp, NULL, g_invalidate_esp}, - {e_regSetGPR, gpr_ss, "ss", NULL, Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ss, - NULL, NULL}, - {e_regSetGPR, gpr_eflags, "eflags", "flags", Uint, Hex, GPR_SIZE(eflags), - GPR_OFFSET(eflags), ehframe_eflags, dwarf_eflags, GENERIC_REGNUM_FLAGS, - debugserver_eflags, NULL, NULL}, - {e_regSetGPR, gpr_eip, "eip", "pc", Uint, Hex, GPR_SIZE(eip), - GPR_OFFSET(eip), ehframe_eip, dwarf_eip, GENERIC_REGNUM_PC, - debugserver_eip, NULL, NULL}, - {e_regSetGPR, gpr_cs, "cs", NULL, Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_cs, - NULL, NULL}, - {e_regSetGPR, gpr_ds, "ds", NULL, Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ds, - NULL, NULL}, - {e_regSetGPR, gpr_es, "es", NULL, Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_es, - NULL, NULL}, - {e_regSetGPR, gpr_fs, "fs", NULL, Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_fs, - NULL, NULL}, - {e_regSetGPR, gpr_gs, "gs", NULL, Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_gs, - NULL, NULL}, - DEFINE_GPR_PSEUDO_16(ax, eax), - DEFINE_GPR_PSEUDO_16(bx, ebx), - DEFINE_GPR_PSEUDO_16(cx, ecx), - DEFINE_GPR_PSEUDO_16(dx, edx), - DEFINE_GPR_PSEUDO_16(di, edi), - DEFINE_GPR_PSEUDO_16(si, esi), - DEFINE_GPR_PSEUDO_16(bp, ebp), - DEFINE_GPR_PSEUDO_16(sp, esp), - DEFINE_GPR_PSEUDO_8H(ah, eax), - DEFINE_GPR_PSEUDO_8H(bh, ebx), - DEFINE_GPR_PSEUDO_8H(ch, ecx), - DEFINE_GPR_PSEUDO_8H(dh, edx), - DEFINE_GPR_PSEUDO_8L(al, eax), - DEFINE_GPR_PSEUDO_8L(bl, ebx), - DEFINE_GPR_PSEUDO_8L(cl, ecx), - DEFINE_GPR_PSEUDO_8L(dl, edx), - DEFINE_GPR_PSEUDO_8L(dil, edi), - DEFINE_GPR_PSEUDO_8L(sil, esi), - DEFINE_GPR_PSEUDO_8L(bpl, ebp), - DEFINE_GPR_PSEUDO_8L(spl, esp)}; - -const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_no_avx[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - FPU_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - FPU_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - FPU_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - FPU_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - FPU_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - FPU_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - FPU_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - FPU_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, - INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, - INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, - INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, - INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, - INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, - INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, - INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, - INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL}, - - {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0, - INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL}, - {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1, - INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL}, - {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2, - INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL}, - {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3, - INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL}, - {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4, - INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL}, - {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5, - INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL}, - {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6, - INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL}, - {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7, - INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL}}; - -static const char *g_contained_ymm0[] = {"ymm0", NULL}; -static const char *g_contained_ymm1[] = {"ymm1", NULL}; -static const char *g_contained_ymm2[] = {"ymm2", NULL}; -static const char *g_contained_ymm3[] = {"ymm3", NULL}; -static const char *g_contained_ymm4[] = {"ymm4", NULL}; -static const char *g_contained_ymm5[] = {"ymm5", NULL}; -static const char *g_contained_ymm6[] = {"ymm6", NULL}; -static const char *g_contained_ymm7[] = {"ymm7", NULL}; - -const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - AVX_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, - INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, - INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, - INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, - INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, - INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, - INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, - INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, - INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL}, - - {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0, - INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL}, - {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1, - INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL}, - {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2, - INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL}, - {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3, - INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL}, - {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4, - INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL}, - {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5, - INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL}, - {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6, - INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL}, - {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7, - INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL}, - - {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, - debugserver_xmm0, g_contained_ymm0, NULL}, - {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, - debugserver_xmm1, g_contained_ymm1, NULL}, - {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, - debugserver_xmm2, g_contained_ymm2, NULL}, - {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, - debugserver_xmm3, g_contained_ymm3, NULL}, - {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, - debugserver_xmm4, g_contained_ymm4, NULL}, - {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, - debugserver_xmm5, g_contained_ymm5, NULL}, - {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, - debugserver_xmm6, g_contained_ymm6, NULL}, - {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, - debugserver_xmm7, g_contained_ymm7, NULL}, - -}; - - -#define STR(s) #s - -#define ZMM_REG_DEF(reg) \ - { \ - e_regSetFPU, fpu_zmm##reg, STR(zmm##reg), NULL, Vector, VectorOfUInt8, \ - FPU_SIZE_ZMM(zmm##reg), AVX512F_OFFSET_ZMM(reg), INVALID_NUB_REGNUM, \ - dwarf_zmm##reg, INVALID_NUB_REGNUM, debugserver_zmm##reg, NULL, NULL \ - } - -#define YMM_REG_ALIAS(reg) \ - { \ - e_regSetFPU, fpu_ymm##reg, STR(ymm##reg), NULL, Vector, VectorOfUInt8, \ - FPU_SIZE_YMM(ymm##reg), 0, INVALID_NUB_REGNUM, dwarf_ymm##reg, \ - INVALID_NUB_REGNUM, debugserver_ymm##reg, g_contained_zmm##reg, NULL \ - } - -#define XMM_REG_ALIAS(reg) \ - { \ - e_regSetFPU, fpu_xmm##reg, STR(xmm##reg), NULL, Vector, VectorOfUInt8, \ - FPU_SIZE_XMM(xmm##reg), 0, INVALID_NUB_REGNUM, dwarf_xmm##reg, \ - INVALID_NUB_REGNUM, debugserver_xmm##reg, g_contained_zmm##reg, NULL \ - } - -#define AVX512_K_REG_DEF(reg) \ - { \ - e_regSetFPU, fpu_k##reg, STR(k##reg), NULL, Vector, VectorOfUInt8, 8, \ - AVX512F_OFFSET(k##reg), dwarf_k##reg, dwarf_k##reg, -1U, \ - debugserver_k##reg, NULL, NULL \ - } - -static const char *g_contained_zmm0[] = {"zmm0", NULL}; -static const char *g_contained_zmm1[] = {"zmm1", NULL}; -static const char *g_contained_zmm2[] = {"zmm2", NULL}; -static const char *g_contained_zmm3[] = {"zmm3", NULL}; -static const char *g_contained_zmm4[] = {"zmm4", NULL}; -static const char *g_contained_zmm5[] = {"zmm5", NULL}; -static const char *g_contained_zmm6[] = {"zmm6", NULL}; -static const char *g_contained_zmm7[] = {"zmm7", NULL}; - -const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx512f[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, - INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, - INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, - INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, - INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, - INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, - INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, - INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, - INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL}, - - AVX512_K_REG_DEF(0), - AVX512_K_REG_DEF(1), - AVX512_K_REG_DEF(2), - AVX512_K_REG_DEF(3), - AVX512_K_REG_DEF(4), - AVX512_K_REG_DEF(5), - AVX512_K_REG_DEF(6), - AVX512_K_REG_DEF(7), - - ZMM_REG_DEF(0), - ZMM_REG_DEF(1), - ZMM_REG_DEF(2), - ZMM_REG_DEF(3), - ZMM_REG_DEF(4), - ZMM_REG_DEF(5), - ZMM_REG_DEF(6), - ZMM_REG_DEF(7), - - YMM_REG_ALIAS(0), - YMM_REG_ALIAS(1), - YMM_REG_ALIAS(2), - YMM_REG_ALIAS(3), - YMM_REG_ALIAS(4), - YMM_REG_ALIAS(5), - YMM_REG_ALIAS(6), - YMM_REG_ALIAS(7), - - XMM_REG_ALIAS(0), - XMM_REG_ALIAS(1), - XMM_REG_ALIAS(2), - XMM_REG_ALIAS(3), - XMM_REG_ALIAS(4), - XMM_REG_ALIAS(5), - XMM_REG_ALIAS(6), - XMM_REG_ALIAS(7) - -}; - -const DNBRegisterInfo DNBArchImplI386::g_exc_registers[] = { - {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno), - EXC_OFFSET(trapno), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err), - EXC_OFFSET(err), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, - EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}}; - -// Number of registers in each register set -const size_t DNBArchImplI386::k_num_gpr_registers = - sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_fpu_registers_no_avx = - sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_fpu_registers_avx = - sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_fpu_registers_avx512f = - sizeof(g_fpu_registers_avx512f) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_exc_registers = - sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_all_registers_no_avx = - k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; -const size_t DNBArchImplI386::k_num_all_registers_avx = - k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; -const size_t DNBArchImplI386::k_num_all_registers_avx512f = - k_num_gpr_registers + k_num_fpu_registers_avx512f + k_num_exc_registers; - -// Register set definitions. The first definitions at register set index -// of zero is for all registers, followed by other registers sets. The -// register information for the all register set need not be filled in. -const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_no_avx[] = { - {"i386 Registers", NULL, k_num_all_registers_no_avx}, - {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, - {"Floating Point Registers", g_fpu_registers_no_avx, - k_num_fpu_registers_no_avx}, - {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; - -const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx[] = { - {"i386 Registers", NULL, k_num_all_registers_avx}, - {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, - {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx}, - {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; - -const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx512f[] = { - {"i386 Registers", NULL, k_num_all_registers_avx512f}, - {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, - {"Floating Point Registers", g_fpu_registers_avx512f, - k_num_fpu_registers_avx512f}, - {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; - -// Total number of register sets for this architecture -const size_t DNBArchImplI386::k_num_register_sets = - sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo); - -DNBArchProtocol *DNBArchImplI386::Create(MachThread *thread) { - DNBArchImplI386 *obj = new DNBArchImplI386(thread); - return obj; -} - -const uint8_t *DNBArchImplI386::SoftwareBreakpointOpcode(nub_size_t byte_size) { - static const uint8_t g_breakpoint_opcode[] = {0xCC}; - if (byte_size == 1) - return g_breakpoint_opcode; - return NULL; -} - -const DNBRegisterSetInfo * -DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) { - *num_reg_sets = k_num_register_sets; - if (CPUHasAVX512f() || FORCE_AVX_REGS) - return g_reg_sets_avx512f; - if (CPUHasAVX()) - return g_reg_sets_avx; - else - return g_reg_sets_no_avx; -} - -void DNBArchImplI386::Initialize() { - DNBArchPluginInfo arch_plugin_info = { - CPU_TYPE_I386, DNBArchImplI386::Create, - DNBArchImplI386::GetRegisterSetInfo, - DNBArchImplI386::SoftwareBreakpointOpcode}; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); -} - -bool DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) { - if (set == REGISTER_SET_GENERIC) { - switch (reg) { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_eip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_esp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_ebp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_eflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; - } - } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) { - value->info = *regInfo; - switch (set) { - case e_regSetGPR: - if (reg < k_num_gpr_registers) { - value->value.uint32 = ((uint32_t *)(&m_state.context.gpr))[reg]; - return true; - } - break; - - case e_regSetFPU: - if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS)) - return false; - if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS)) - return false; - switch (reg) { - case fpu_fcw: - value->value.uint16 = - *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); - return true; - case fpu_fsw: - value->value.uint16 = - *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); - return true; - case fpu_ftw: - memcpy (&value->value.uint16, &m_state.context.fpu.no_avx.__fpu_ftw, 2); - return true; - case fpu_fop: - value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; - return true; - case fpu_ip: - value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; - return true; - case fpu_cs: - value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; - return true; - case fpu_dp: - value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; - return true; - case fpu_ds: - value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; - return true; - case fpu_mxcsr: - value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; - return true; - case fpu_mxcsrmask: - value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; - return true; - - case fpu_stmm0: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10); - return true; - case fpu_stmm1: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10); - return true; - case fpu_stmm2: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10); - return true; - case fpu_stmm3: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10); - return true; - case fpu_stmm4: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10); - return true; - case fpu_stmm5: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10); - return true; - case fpu_stmm6: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10); - return true; - case fpu_stmm7: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10); - return true; - - case fpu_xmm0: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16); - return true; - case fpu_xmm1: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16); - return true; - case fpu_xmm2: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16); - return true; - case fpu_xmm3: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16); - return true; - case fpu_xmm4: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16); - return true; - case fpu_xmm5: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16); - return true; - case fpu_xmm6: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16); - return true; - case fpu_xmm7: - memcpy(&value->value.uint8, - m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16); - return true; - -#define MEMCPY_YMM(n) \ - memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, \ - 16); \ - memcpy((&value->value.uint8) + 16, \ - m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16); - case fpu_ymm0: - MEMCPY_YMM(0); - return true; - case fpu_ymm1: - MEMCPY_YMM(1); - return true; - case fpu_ymm2: - MEMCPY_YMM(2); - return true; - case fpu_ymm3: - MEMCPY_YMM(3); - return true; - case fpu_ymm4: - MEMCPY_YMM(4); - return true; - case fpu_ymm5: - MEMCPY_YMM(5); - return true; - case fpu_ymm6: - MEMCPY_YMM(6); - return true; - case fpu_ymm7: - MEMCPY_YMM(7); - return true; -#undef MEMCPY_YMM - - case fpu_k0: - case fpu_k1: - case fpu_k2: - case fpu_k3: - case fpu_k4: - case fpu_k5: - case fpu_k6: - case fpu_k7: - memcpy((&value->value.uint8), - &m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0), 8); - return true; - case fpu_zmm0: - case fpu_zmm1: - case fpu_zmm2: - case fpu_zmm3: - case fpu_zmm4: - case fpu_zmm5: - case fpu_zmm6: - case fpu_zmm7: - memcpy(&value->value.uint8, - &m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0), 16); - memcpy(&value->value.uint8 + 16, - &m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0), 16); - memcpy(&value->value.uint8 + 32, - &m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0), 32); - return true; - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) { - value->value.uint32 = (&m_state.context.exc.__trapno)[reg]; - return true; - } - break; - } - } - return false; -} - -bool DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) { - if (set == REGISTER_SET_GENERIC) { - switch (reg) { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_eip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_esp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_ebp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_eflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; - } - } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) { - switch (set) { - case e_regSetGPR: - if (reg < k_num_gpr_registers) { - ((uint32_t *)(&m_state.context.gpr))[reg] = value->value.uint32; - success = true; - } - break; - - case e_regSetFPU: - if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS)) - return false; - if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS)) - return false; - switch (reg) { - case fpu_fcw: - *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = - value->value.uint16; - success = true; - break; - case fpu_fsw: - *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = - value->value.uint16; - success = true; - break; - case fpu_ftw: - memcpy (&m_state.context.fpu.no_avx.__fpu_ftw, &value->value.uint16, 2); - success = true; - break; - case fpu_fop: - m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; - success = true; - break; - case fpu_ip: - m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; - success = true; - break; - case fpu_cs: - m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; - success = true; - break; - case fpu_dp: - m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; - success = true; - break; - case fpu_ds: - m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; - success = true; - break; - case fpu_mxcsr: - m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; - success = true; - break; - case fpu_mxcsrmask: - m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; - success = true; - break; - - case fpu_stmm0: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm1: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm2: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm3: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm4: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm5: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm6: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - case fpu_stmm7: - memcpy(m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, - &value->value.uint8, 10); - success = true; - break; - - case fpu_xmm0: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm1: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm2: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm3: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm4: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm5: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm6: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - case fpu_xmm7: - memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, - &value->value.uint8, 16); - success = true; - break; - -#define MEMCPY_YMM(n) \ - memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, \ - 16); \ - memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, \ - (&value->value.uint8) + 16, 16); - case fpu_ymm0: - MEMCPY_YMM(0); - return true; - case fpu_ymm1: - MEMCPY_YMM(1); - return true; - case fpu_ymm2: - MEMCPY_YMM(2); - return true; - case fpu_ymm3: - MEMCPY_YMM(3); - return true; - case fpu_ymm4: - MEMCPY_YMM(4); - return true; - case fpu_ymm5: - MEMCPY_YMM(5); - return true; - case fpu_ymm6: - MEMCPY_YMM(6); - return true; - case fpu_ymm7: - MEMCPY_YMM(7); - return true; -#undef MEMCPY_YMM - - case fpu_k0: - case fpu_k1: - case fpu_k2: - case fpu_k3: - case fpu_k4: - case fpu_k5: - case fpu_k6: - case fpu_k7: - memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0), - &value->value.uint8, 8); - return true; - case fpu_zmm0: - case fpu_zmm1: - case fpu_zmm2: - case fpu_zmm3: - case fpu_zmm4: - case fpu_zmm5: - case fpu_zmm6: - case fpu_zmm7: - memcpy(&m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0), - &value->value.uint8, 16); - memcpy(&m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0), - &value->value.uint8 + 16, 16); - memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0), - &value->value.uint8 + 32, 32); - return true; - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) { - (&m_state.context.exc.__trapno)[reg] = value->value.uint32; - success = true; - } - break; - } - } - - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; -} - -uint32_t DNBArchImplI386::GetRegisterContextSize() { - static uint32_t g_cached_size = 0; - if (g_cached_size == 0) { - if(CPUHasAVX512f() || FORCE_AVX_REGS) { - for (size_t i = 0; i < k_num_fpu_registers_avx512f; ++i) { - if (g_fpu_registers_avx512f[i].value_regs == NULL) - g_cached_size += g_fpu_registers_avx512f[i].size; - } - } else - if (CPUHasAVX()) { - for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) { - if (g_fpu_registers_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_avx[i].size; - } - } else { - for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) { - if (g_fpu_registers_no_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_no_avx[i].size; - } - } - DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, " - "FPU = %u, EXC = %zu", - sizeof(GPR), g_cached_size, sizeof(EXC)); - g_cached_size += sizeof(GPR); - g_cached_size += sizeof(EXC); - DNBLogThreaded( - "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", - g_cached_size); - } - return g_cached_size; -} - -nub_size_t DNBArchImplI386::GetRegisterContext(void *buf, nub_size_t buf_len) { - uint32_t size = GetRegisterContextSize(); - - if (buf && buf_len) { - if (size > buf_len) - size = static_cast(buf_len); - - bool force = false; - kern_return_t kret; - if ((kret = GetGPRState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = " - "%p, len = %llu) error: GPR regs failed to " - "read: %u ", - buf, (uint64_t)buf_len, kret); - size = 0; - } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf( - LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = " - "%llu) error: %s regs failed to read: %u", - buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - size = 0; - } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = " - "%p, len = %llu) error: EXC regs failed to " - "read: %u", - buf, (uint64_t)buf_len, kret); - size = 0; - } else { - uint8_t *p = (uint8_t *)buf; - // Copy the GPR registers - memcpy(p, &m_state.context.gpr, sizeof(GPR)); - p += sizeof(GPR); - - // Walk around the gaps in the FPU regs - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); - p += 5; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); - p += 8; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); - p += 6; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i = 0; i < 8; ++i) { - memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); - p += 10; - } - - if (CPUHasAVX512f() || FORCE_AVX_REGS) { - for (size_t i = 0; i < 8; ++i) { - memcpy(p, &m_state.context.fpu.avx512f.__fpu_k0 + i, 8); - p += 8; - } - } - - if (CPUHasAVX() || FORCE_AVX_REGS) { - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i = 0; i < 8; ++i) { - memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); - p += 16; - memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); - p += 16; - } - if(CPUHasAVX512f() || FORCE_AVX_REGS) { - for (size_t i = 0; i < 8; ++i) { - memcpy(p, &m_state.context.fpu.avx512f.__fpu_zmmh0 + i, 32); - p += 32; - } - } - } else { - // Copy the XMM registers in a single block - memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16); - p += 8 * 16; - } - - // Copy the exception registers - memcpy(p, &m_state.context.exc, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert(bytes_written == size); - } - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, - (uint64_t)buf_len, (uint64_t)size); - // Return the size of the register context even if NULL was passed in - return size; -} - -nub_size_t DNBArchImplI386::SetRegisterContext(const void *buf, - nub_size_t buf_len) { - nub_size_t size = sizeof(m_state.context); - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) { - if (size > buf_len) - size = buf_len; - - const uint8_t *p = (const uint8_t *)buf; - // Copy the GPR registers - memcpy(&m_state.context.gpr, p, sizeof(GPR)); - p += sizeof(GPR); - - // Copy fcw through mxcsrmask as there is no padding - memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); - p += 5; - memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); - p += 8; - memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); - p += 6; - memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i = 0; i < 8; ++i) { - memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); - p += 10; - } - - if(CPUHasAVX512f() || FORCE_AVX_REGS) { - for (size_t i = 0; i < 8; ++i) { - memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + i, p, 8); - p += 8; - } - } - - if (CPUHasAVX() || FORCE_AVX_REGS) { - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i = 0; i < 8; ++i) { - memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); - p += 16; - memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); - p += 16; - } - - if(CPUHasAVX512f() || FORCE_AVX_REGS) { - for (size_t i = 0; i < 8; ++i) { - memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + i, p, 32); - p += 32; - } - } - } else { - // Copy the XMM registers in a single block - memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16); - p += 8 * 16; - } - - // Copy the exception registers - memcpy(&m_state.context.exc, p, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (const uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert(bytes_written == size); - kern_return_t kret; - if ((kret = SetGPRState()) != KERN_SUCCESS) - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = " - "%p, len = %llu) error: GPR regs failed to " - "write: %u", - buf, (uint64_t)buf_len, kret); - if ((kret = SetFPUState()) != KERN_SUCCESS) - DNBLogThreadedIf( - LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = " - "%llu) error: %s regs failed to write: %u", - buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - if ((kret = SetEXCState()) != KERN_SUCCESS) - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = " - "%p, len = %llu) error: EXP regs failed to " - "write: %u", - buf, (uint64_t)buf_len, kret); - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, - (uint64_t)buf_len, (uint64_t)size); - return size; -} - -uint32_t DNBArchImplI386::SaveRegisterState() { - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf( - LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " - "(SetGPRState() for stop_count = %u)", - m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: " - "GPR regs failed to read: %u ", - kret); - } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: " - "%s regs failed to read: %u", - CPUHasAVX() ? "AVX" : "FPU", kret); - } else { - const uint32_t save_id = GetNextRegisterStateSaveID(); - m_saved_register_states[save_id] = m_state.context; - return save_id; - } - return 0; -} -bool DNBArchImplI386::RestoreRegisterState(uint32_t save_id) { - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) { - m_state.context.gpr = pos->second.gpr; - m_state.context.fpu = pos->second.fpu; - m_state.context.exc = pos->second.exc; - m_state.SetError(e_regSetGPR, Read, 0); - m_state.SetError(e_regSetFPU, Read, 0); - m_state.SetError(e_regSetEXC, Read, 0); - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState " - "(save_id = %u) error: GPR regs failed to " - "write: %u", - save_id, kret); - success = false; - } else if ((kret = SetFPUState()) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState " - "(save_id = %u) error: %s regs failed to " - "write: %u", - save_id, CPUHasAVX() ? "AVX" : "FPU", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; - } - return false; -} - -kern_return_t DNBArchImplI386::GetRegisterState(int set, bool force) { - switch (set) { - case e_regSetALL: - return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); - case e_regSetGPR: - return GetGPRState(force); - case e_regSetFPU: - return GetFPUState(force); - case e_regSetEXC: - return GetEXCState(force); - default: - break; - } - return KERN_INVALID_ARGUMENT; -} - -kern_return_t DNBArchImplI386::SetRegisterState(int set) { - // Make sure we have a valid context to set. - if (RegisterSetStateIsValid(set)) { - switch (set) { - case e_regSetALL: - return SetGPRState() | SetFPUState() | SetEXCState(); - case e_regSetGPR: - return SetGPRState(); - case e_regSetFPU: - return SetFPUState(); - case e_regSetEXC: - return SetEXCState(); - default: - break; - } - } - return KERN_INVALID_ARGUMENT; -} - -bool DNBArchImplI386::RegisterSetStateIsValid(int set) const { - return m_state.RegsAreValid(set); -} - -#endif // #if defined (__i386__) diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h deleted file mode 100644 index a702ea52e853..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ /dev/null @@ -1,246 +0,0 @@ -//===-- DNBArchImplI386.h ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_DNBARCHIMPLI386_H -#define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_DNBARCHIMPLI386_H - -#if defined(__i386__) || defined(__x86_64__) - -#include "DNBArch.h" -#include "MachRegisterStatesI386.h" - -#include - -class MachThread; - -class DNBArchImplI386 : public DNBArchProtocol { -public: - DNBArchImplI386(MachThread *thread) - : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done), m_saved_register_states() {} - virtual ~DNBArchImplI386() {} - - static void Initialize(); - - bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) override; - bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) override; - nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override; - nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override; - uint32_t SaveRegisterState() override; - bool RestoreRegisterState(uint32_t save_id) override; - - kern_return_t GetRegisterState(int set, bool force) override; - kern_return_t SetRegisterState(int set) override; - bool RegisterSetStateIsValid(int set) const override; - - uint64_t GetPC(uint64_t failValue) override; // Get program counter - kern_return_t SetPC(uint64_t value) override; - uint64_t GetSP(uint64_t failValue) override; // Get stack pointer - void ThreadWillResume() override; - bool ThreadDidStop() override; - bool NotifyException(MachException::Data &exc) override; - - uint32_t NumSupportedHardwareBreakpoints() override; - uint32_t NumSupportedHardwareWatchpoints() override; - uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, - bool also_set_on_task) override; - bool DisableHardwareBreakpoint(uint32_t hw_index, - bool also_set_on_task) override; - uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task) override; - bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task) override; - uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) override; - -protected: - kern_return_t EnableHardwareSingleStep(bool enable); - - typedef __i386_thread_state_t GPR; - typedef __i386_float_state_t FPU; - typedef __i386_exception_state_t EXC; - typedef __i386_avx_state_t AVX; - typedef __i386_debug_state_t DBG; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_fpu_registers_no_avx[]; - static const DNBRegisterInfo g_fpu_registers_avx[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets_no_avx[]; - static const DNBRegisterSetInfo g_reg_sets_avx[]; - static const size_t k_num_gpr_registers; - static const size_t k_num_fpu_registers_no_avx; - static const size_t k_num_fpu_registers_avx; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers_no_avx; - static const size_t k_num_all_registers_avx; - static const size_t k_num_register_sets; - - typedef __i386_avx512f_state_t AVX512F; - static const DNBRegisterInfo g_fpu_registers_avx512f[]; - static const DNBRegisterSetInfo g_reg_sets_avx512f[]; - static const size_t k_num_fpu_registers_avx512f; - static const size_t k_num_all_registers_avx512f; - - enum RegisterSet { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPU, - e_regSetEXC, - e_regSetDBG, - kNumRegisterSets - }; - - enum RegisterSetWordSize { - e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), - e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), - e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), - e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), - e_regSetWordSizeAVX512f = sizeof(AVX512F) / sizeof(int), - e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) - }; - - enum { Read = 0, Write = 1, kNumErrors = 2 }; - - struct Context { - GPR gpr; - union { - FPU no_avx; - AVX avx; - AVX512F avx512f; - } fpu; - EXC exc; - DBG dbg; - }; - - struct State { - Context context; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t fpu_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - - State() { - uint32_t i; - for (i = 0; i < kNumErrors; i++) { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } - kern_return_t GetError(int flavor, uint32_t err_idx) const { - if (err_idx < kNumErrors) { - switch (flavor) { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: - return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; - case e_regSetGPR: - return gpr_errs[err_idx]; - case e_regSetFPU: - return fpu_errs[err_idx]; - case e_regSetEXC: - return exc_errs[err_idx]; - case e_regSetDBG: - return dbg_errs[err_idx]; - default: - break; - } - } - return -1; - } - bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { - if (err_idx < kNumErrors) { - switch (flavor) { - case e_regSetALL: - gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = - dbg_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetFPU: - fpu_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetDBG: - dbg_errs[err_idx] = err; - return true; - - default: - break; - } - } - return false; - } - bool RegsAreValid(int flavor) const { - return GetError(flavor, Read) == KERN_SUCCESS; - } - }; - - kern_return_t GetGPRState(bool force); - kern_return_t GetFPUState(bool force); - kern_return_t GetEXCState(bool force); - kern_return_t GetDBGState(bool force); - - kern_return_t SetGPRState(); - kern_return_t SetFPUState(); - kern_return_t SetEXCState(); - kern_return_t SetDBGState(bool also_set_on_task); - - static DNBArchProtocol *Create(MachThread *thread); - - static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); - - static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); - - static uint32_t GetRegisterContextSize(); - - static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, - nub_addr_t addr, nub_size_t size); - - // Helper functions for watchpoint manipulations. - static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, - nub_addr_t addr, nub_size_t size, bool read, - bool write); - static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); - static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); - static void ClearWatchpointHits(DBG &debug_state); - static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); - static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - - bool StartTransForHWP() override; - bool RollbackTransForHWP() override; - bool FinishTransForHWP() override; - DBG GetDBGCheckpoint(); - - MachThread *m_thread; - State m_state; - DBG m_2pc_dbg_checkpoint; - uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning - // (0), Done (1), or Rolled Back (2)? - typedef std::map SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (__i386__) || defined (__x86_64__) -#endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_DNBARCHIMPLI386_H diff --git a/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h b/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h deleted file mode 100644 index ba76925369c5..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h +++ /dev/null @@ -1,241 +0,0 @@ -//===-- MachRegisterStatesI386.h --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Created by Sean Callanan on 3/16/11. -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_MACHREGISTERSTATESI386_H -#define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_MACHREGISTERSTATESI386_H - -#include - -#define __i386_THREAD_STATE 1 -#define __i386_FLOAT_STATE 2 -#define __i386_EXCEPTION_STATE 3 -#define __i386_DEBUG_STATE 10 -#define __i386_AVX_STATE 16 -#define __i386_AVX512F_STATE 19 - -typedef struct { - uint32_t __eax; - uint32_t __ebx; - uint32_t __ecx; - uint32_t __edx; - uint32_t __edi; - uint32_t __esi; - uint32_t __ebp; - uint32_t __esp; - uint32_t __ss; - uint32_t __eflags; - uint32_t __eip; - uint32_t __cs; - uint32_t __ds; - uint32_t __es; - uint32_t __fs; - uint32_t __gs; -} __i386_thread_state_t; - -typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __PAD1 : 2; - uint16_t __pc : 2; - uint16_t __rc : 2; - uint16_t __PAD2 : 1; - uint16_t __PAD3 : 3; -} __i386_fp_control_t; - -typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __stkflt : 1; - uint16_t __errsumm : 1; - uint16_t __c0 : 1; - uint16_t __c1 : 1; - uint16_t __c2 : 1; - uint16_t __tos : 3; - uint16_t __c3 : 1; - uint16_t __busy : 1; -} __i386_fp_status_t; - -typedef struct { - uint8_t __mmst_reg[10]; - uint8_t __mmst_rsrv[6]; -} __i386_mmst_reg; - -typedef struct { uint8_t __xmm_reg[16]; } __i386_xmm_reg; - -typedef struct { - uint32_t __fpu_reserved[2]; - __i386_fp_control_t __fpu_fcw; - __i386_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __i386_mmst_reg __fpu_stmm0; - __i386_mmst_reg __fpu_stmm1; - __i386_mmst_reg __fpu_stmm2; - __i386_mmst_reg __fpu_stmm3; - __i386_mmst_reg __fpu_stmm4; - __i386_mmst_reg __fpu_stmm5; - __i386_mmst_reg __fpu_stmm6; - __i386_mmst_reg __fpu_stmm7; - __i386_xmm_reg __fpu_xmm0; - __i386_xmm_reg __fpu_xmm1; - __i386_xmm_reg __fpu_xmm2; - __i386_xmm_reg __fpu_xmm3; - __i386_xmm_reg __fpu_xmm4; - __i386_xmm_reg __fpu_xmm5; - __i386_xmm_reg __fpu_xmm6; - __i386_xmm_reg __fpu_xmm7; - uint8_t __fpu_rsrv4[14 * 16]; - uint32_t __fpu_reserved1; -} __i386_float_state_t; - -typedef struct { - uint32_t __fpu_reserved[2]; - __i386_fp_control_t __fpu_fcw; - __i386_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __i386_mmst_reg __fpu_stmm0; - __i386_mmst_reg __fpu_stmm1; - __i386_mmst_reg __fpu_stmm2; - __i386_mmst_reg __fpu_stmm3; - __i386_mmst_reg __fpu_stmm4; - __i386_mmst_reg __fpu_stmm5; - __i386_mmst_reg __fpu_stmm6; - __i386_mmst_reg __fpu_stmm7; - __i386_xmm_reg __fpu_xmm0; - __i386_xmm_reg __fpu_xmm1; - __i386_xmm_reg __fpu_xmm2; - __i386_xmm_reg __fpu_xmm3; - __i386_xmm_reg __fpu_xmm4; - __i386_xmm_reg __fpu_xmm5; - __i386_xmm_reg __fpu_xmm6; - __i386_xmm_reg __fpu_xmm7; - uint8_t __fpu_rsrv4[14 * 16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __i386_xmm_reg __fpu_ymmh0; - __i386_xmm_reg __fpu_ymmh1; - __i386_xmm_reg __fpu_ymmh2; - __i386_xmm_reg __fpu_ymmh3; - __i386_xmm_reg __fpu_ymmh4; - __i386_xmm_reg __fpu_ymmh5; - __i386_xmm_reg __fpu_ymmh6; - __i386_xmm_reg __fpu_ymmh7; -} __i386_avx_state_t; - -typedef struct { uint8_t __ymm_reg[32]; } __i386_ymm_reg; -typedef struct { uint8_t __opmask_reg[8]; } __i386_opmask_reg; - -typedef struct { - uint32_t __fpu_reserved[2]; - __i386_fp_control_t __fpu_fcw; - __i386_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __i386_mmst_reg __fpu_stmm0; - __i386_mmst_reg __fpu_stmm1; - __i386_mmst_reg __fpu_stmm2; - __i386_mmst_reg __fpu_stmm3; - __i386_mmst_reg __fpu_stmm4; - __i386_mmst_reg __fpu_stmm5; - __i386_mmst_reg __fpu_stmm6; - __i386_mmst_reg __fpu_stmm7; - __i386_xmm_reg __fpu_xmm0; - __i386_xmm_reg __fpu_xmm1; - __i386_xmm_reg __fpu_xmm2; - __i386_xmm_reg __fpu_xmm3; - __i386_xmm_reg __fpu_xmm4; - __i386_xmm_reg __fpu_xmm5; - __i386_xmm_reg __fpu_xmm6; - __i386_xmm_reg __fpu_xmm7; - uint8_t __fpu_rsrv4[14 * 16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __i386_xmm_reg __fpu_ymmh0; - __i386_xmm_reg __fpu_ymmh1; - __i386_xmm_reg __fpu_ymmh2; - __i386_xmm_reg __fpu_ymmh3; - __i386_xmm_reg __fpu_ymmh4; - __i386_xmm_reg __fpu_ymmh5; - __i386_xmm_reg __fpu_ymmh6; - __i386_xmm_reg __fpu_ymmh7; - __i386_opmask_reg __fpu_k0; - __i386_opmask_reg __fpu_k1; - __i386_opmask_reg __fpu_k2; - __i386_opmask_reg __fpu_k3; - __i386_opmask_reg __fpu_k4; - __i386_opmask_reg __fpu_k5; - __i386_opmask_reg __fpu_k6; - __i386_opmask_reg __fpu_k7; - __i386_ymm_reg __fpu_zmmh0; - __i386_ymm_reg __fpu_zmmh1; - __i386_ymm_reg __fpu_zmmh2; - __i386_ymm_reg __fpu_zmmh3; - __i386_ymm_reg __fpu_zmmh4; - __i386_ymm_reg __fpu_zmmh5; - __i386_ymm_reg __fpu_zmmh6; - __i386_ymm_reg __fpu_zmmh7; -} __i386_avx512f_state_t; - -typedef struct { - uint32_t __trapno; - uint32_t __err; - uint32_t __faultvaddr; -} __i386_exception_state_t; - -typedef struct { - uint32_t __dr0; - uint32_t __dr1; - uint32_t __dr2; - uint32_t __dr3; - uint32_t __dr4; - uint32_t __dr5; - uint32_t __dr6; - uint32_t __dr7; -} __i386_debug_state_t; - -#endif