diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
commit | 88c643b6fec27eec436c8d138fee6346e92337d6 (patch) | |
tree | 82cd13b2f3cde1c9e5f79689ba4e6ba67694843f /tools/debugserver | |
parent | 94994d372d014ce4c8758b9605d63fae651bd8aa (diff) |
Notes
Diffstat (limited to 'tools/debugserver')
127 files changed, 0 insertions, 44811 deletions
diff --git a/tools/debugserver/CMakeLists.txt b/tools/debugserver/CMakeLists.txt deleted file mode 100644 index 1dc32434ba40..000000000000 --- a/tools/debugserver/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -cmake_minimum_required(VERSION 3.4.3) - -project(Debugserver LANGUAGES C CXX ASM-ATT) - -if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - "${CMAKE_SOURCE_DIR}/../../cmake" - "${CMAKE_SOURCE_DIR}/../../cmake/modules" - ) - - include(LLDBStandalone) - include(debugserverConfig) - include(AddLLDB) - - set(LLDB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../../") - include_directories(${LLDB_SOURCE_DIR}/include) -endif() - -add_subdirectory(source) diff --git a/tools/debugserver/debugnub-exports b/tools/debugserver/debugnub-exports deleted file mode 100644 index 662bf9308a6f..000000000000 --- a/tools/debugserver/debugnub-exports +++ /dev/null @@ -1,2 +0,0 @@ -_DNB* -__DNB* diff --git a/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/tools/debugserver/debugserver.xcodeproj/project.pbxproj deleted file mode 100644 index f4267b7633a2..000000000000 --- a/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1901 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 23562ED61D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */; }; - 23562ED71D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */; }; - 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; - 456F67641AD46CE9002850C2 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; - 26CE05C3115C36580022F371 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; - 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; - 26CE05CF115C36F70022F371 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; - 456F676B1AD46CE9002850C2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; - 26CE05B7115C363B0022F371 /* DNB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637D60C71334A0024798E /* DNB.cpp */; }; - 456F67551AD46CE9002850C2 /* DNB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637D60C71334A0024798E /* DNB.cpp */; }; - 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; }; - 456F67671AD46CE9002850C2 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; }; - 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; - 26CE05C2115C36550022F371 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */; }; - 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; - 456F67611AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */; }; - 266B5ED11460A68200E43F0A /* DNBArchImplARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */; }; - 456F67691AD46CE9002850C2 /* DNBArchImplARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */; }; - 26CE05C0115C364F0022F371 /* DNBArchImplI386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */; }; - 456F675F1AD46CE9002850C2 /* DNBArchImplI386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */; }; - 26CE05BF115C364D0022F371 /* DNBArchImplX86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */; }; - 456F675E1AD46CE9002850C2 /* DNBArchImplX86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */; }; - 26CE05B8115C363C0022F371 /* DNBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637D90C71334A0024798E /* DNBBreakpoint.cpp */; }; - 456F67571AD46CE9002850C2 /* DNBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637D90C71334A0024798E /* DNBBreakpoint.cpp */; }; - 26CE05B9115C363D0022F371 /* DNBDataRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DB0C71334A0024798E /* DNBDataRef.cpp */; }; - 456F67581AD46CE9002850C2 /* DNBDataRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DB0C71334A0024798E /* DNBDataRef.cpp */; }; - 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DE0C71334A0024798E /* DNBError.cpp */; }; - 456F67461AD46CE9002850C2 /* DNBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DE0C71334A0024798E /* DNBError.cpp */; }; - 26CE05BA115C363E0022F371 /* DNBLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E00C71334A0024798E /* DNBLog.cpp */; }; - 456F67591AD46CE9002850C2 /* DNBLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E00C71334A0024798E /* DNBLog.cpp */; }; - 26CE05BB115C363F0022F371 /* DNBRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */; }; - 456F675A1AD46CE9002850C2 /* DNBRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */; }; - 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */; }; - 456F67471AD46CE9002850C2 /* DNBThreadResumeActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */; }; - 23AE72E41D25DECF00945BCE /* DarwinLogCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */; }; - 23AE72E51D25DEE100945BCE /* DarwinLogCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */; }; - 49D404621E39260F00570CDC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49D404611E39260F00570CDC /* Foundation.framework */; }; - AFA3FCA11E39984900218D5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49D404611E39260F00570CDC /* Foundation.framework */; }; - 456F67561AD46CE9002850C2 /* Genealogy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */; }; - AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */; }; - 23043C9D1D35DBEC00FC25CA /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA51D2DB54300E98261 /* JSON.cpp */; }; - 233B4EA71D2DB54300E98261 /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA51D2DB54300E98261 /* JSON.cpp */; }; - 23AC04C61D2F41A00072351D /* LogFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C41D2F41A00072351D /* LogFilter.cpp */; }; - 23AC04C71D2F41A00072351D /* LogFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C41D2F41A00072351D /* LogFilter.cpp */; }; - 23AC04CA1D2F42250072351D /* LogFilterChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C81D2F42250072351D /* LogFilterChain.cpp */; }; - 23AC04CB1D2F42250072351D /* LogFilterChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C81D2F42250072351D /* LogFilterChain.cpp */; }; - 2307CCCB1D4A5D630016ABC0 /* LogFilterExactMatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */; }; - 237821B01D4917D20028B7A1 /* LogFilterExactMatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */; }; - 23AC04CF1D2F58AF0072351D /* LogFilterRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */; }; - 23AC04D01D2F58AF0072351D /* LogFilterRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */; }; - 23562ED91D342B0000AB2BD4 /* LogMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */; }; - 23562EDA1D342B0000AB2BD4 /* LogMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */; }; - 23562ED21D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */; }; - 23562ED31D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */; }; - 26CE05B0115C36340022F371 /* MachException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EE0C71334A0024798E /* MachException.cpp */; }; - 456F674E1AD46CE9002850C2 /* MachException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637EE0C71334A0024798E /* MachException.cpp */; }; - 26CE05B1115C36350022F371 /* MachProcess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F00C71334A0024798E /* MachProcess.mm */; }; - 456F674F1AD46CE9002850C2 /* MachProcess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F00C71334A0024798E /* MachProcess.mm */; }; - 26CE05B6115C36390022F371 /* MachTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26B67DE10EE9BC30006C8BC0 /* MachTask.mm */; }; - 456F67541AD46CE9002850C2 /* MachTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26B67DE10EE9BC30006C8BC0 /* MachTask.mm */; }; - 26CE05B2115C36360022F371 /* MachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F20C71334A0024798E /* MachThread.cpp */; }; - 456F67501AD46CE9002850C2 /* MachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F20C71334A0024798E /* MachThread.cpp */; }; - 26CE05B3115C36370022F371 /* MachThreadList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F40C71334A0024798E /* MachThreadList.cpp */; }; - 456F67511AD46CE9002850C2 /* MachThreadList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F40C71334A0024798E /* MachThreadList.cpp */; }; - 26CE05B4115C36380022F371 /* MachVMMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F60C71334A0024798E /* MachVMMemory.cpp */; }; - 456F67521AD46CE9002850C2 /* MachVMMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F60C71334A0024798E /* MachVMMemory.cpp */; }; - 26CE05B5115C36380022F371 /* MachVMRegion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F80C71334A0024798E /* MachVMRegion.cpp */; }; - 456F67531AD46CE9002850C2 /* MachVMRegion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637F80C71334A0024798E /* MachVMRegion.cpp */; }; - 23D1B0291D497E8B00FF831B /* OsLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D1B0271D497E8B00FF831B /* OsLogger.cpp */; }; - 23D1B02A1D497E8B00FF831B /* OsLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D1B0271D497E8B00FF831B /* OsLogger.cpp */; }; - 26CE05BC115C36420022F371 /* PThreadEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FE0C71334A0024798E /* PThreadEvent.cpp */; }; - 456F675B1AD46CE9002850C2 /* PThreadEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FE0C71334A0024798E /* PThreadEvent.cpp */; }; - 26CE05BD115C36430022F371 /* PThreadMutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */; }; - 456F675C1AD46CE9002850C2 /* PThreadMutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */; }; - 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; - 456F67651AD46CE9002850C2 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; - 26CE05AA115C36260022F371 /* RNBContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68F7E0D104EC800665A9E /* RNBContext.cpp */; }; - 456F67491AD46CE9002850C2 /* RNBContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68F7E0D104EC800665A9E /* RNBContext.cpp */; }; - 26CE05AD115C36280022F371 /* RNBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68FD60D10574500665A9E /* RNBRemote.cpp */; }; - 456F674C1AD46CE9002850C2 /* RNBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68FD60D10574500665A9E /* RNBRemote.cpp */; }; - 26CE05AB115C36270022F371 /* RNBServices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EF8878A00D9C797C001831DA /* RNBServices.cpp */; }; - 456F674A1AD46CE9002850C2 /* RNBServices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EF8878A00D9C797C001831DA /* RNBServices.cpp */; }; - 26CE05AC115C36280022F371 /* RNBSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68FB00D1054DA00665A9E /* RNBSocket.cpp */; }; - 456F674B1AD46CE9002850C2 /* RNBSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A68FB00D1054DA00665A9E /* RNBSocket.cpp */; }; - AF588449206077BD00A0CB5A /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */; }; - D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */; }; - AF48558C1D75126800D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; }; - AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; }; - 23043C9E1D35DBFA00FC25CA /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */; }; - 233B4EA91D2DB96A00E98261 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */; }; - 26CE05BE115C36440022F371 /* SysSignal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C638010C71334A0024798E /* SysSignal.cpp */; }; - 456F675D1AD46CE9002850C2 /* SysSignal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C638010C71334A0024798E /* SysSignal.cpp */; }; - 26CE05AE115C36320022F371 /* dbgnub-mig.defs in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E80C71334A0024798E /* dbgnub-mig.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; - 456F674D1AD46CE9002850C2 /* dbgnub-mig.defs in Sources */ = {isa = PBXBuildFile; fileRef = 26C637E80C71334A0024798E /* dbgnub-mig.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; - 26CE05A9115C36250022F371 /* debugserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A02918114AB9240029C479 /* debugserver.cpp */; }; - 456F67481AD46CE9002850C2 /* debugserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A02918114AB9240029C479 /* debugserver.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActivityStore.cpp; sourceTree = "<group>"; }; - 23562ED41D3426DD00AB2BD4 /* ActivityStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityStore.h; sourceTree = "<group>"; }; - 23AE72E61D25DEFB00945BCE /* ActivityStreamSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityStreamSPI.h; sourceTree = "<group>"; }; - 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFBundle.cpp; sourceTree = "<group>"; }; - 2695DD920D3EBFF6007E4CA2 /* CFBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFBundle.h; sourceTree = "<group>"; }; - 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFString.cpp; sourceTree = "<group>"; }; - 2695DD9A0D3EC160007E4CA2 /* CFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFString.h; sourceTree = "<group>"; }; - 26C637E70C71334A0024798E /* CFUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CFUtils.h; sourceTree = "<group>"; }; - 2307CCCC1D4A5DAE0016ABC0 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; - 237821AD1D4917D20028B7A1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; - 26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; - 26ACA3340D3E956300A2120B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 26C637D60C71334A0024798E /* DNB.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNB.cpp; sourceTree = "<group>"; }; - 26C637D70C71334A0024798E /* DNB.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNB.h; sourceTree = "<group>"; }; - 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = "<group>"; }; - 26C637D80C71334A0024798E /* DNBArch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArch.h; sourceTree = "<group>"; }; - 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DNBArchImpl.cpp; path = arm/DNBArchImpl.cpp; sourceTree = "<group>"; }; - 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImpl.cpp; sourceTree = "<group>"; }; - 2675D4230CCEB705000F49AF /* DNBArchImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DNBArchImpl.h; path = arm/DNBArchImpl.h; sourceTree = "<group>"; }; - 26C637FC0C71334A0024798E /* DNBArchImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArchImpl.h; sourceTree = "<group>"; }; - 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplARM64.cpp; sourceTree = "<group>"; }; - 266B5ED01460A68200E43F0A /* DNBArchImplARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBArchImplARM64.h; sourceTree = "<group>"; }; - 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplI386.cpp; sourceTree = "<group>"; }; - 26C637EB0C71334A0024798E /* DNBArchImplI386.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArchImplI386.h; sourceTree = "<group>"; }; - 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplX86_64.cpp; sourceTree = "<group>"; }; - 26CF99A31142EB7400011AAB /* DNBArchImplX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBArchImplX86_64.h; sourceTree = "<group>"; }; - 26C637D90C71334A0024798E /* DNBBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBBreakpoint.cpp; sourceTree = "<group>"; }; - 26C637DA0C71334A0024798E /* DNBBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBBreakpoint.h; sourceTree = "<group>"; }; - 26C637DB0C71334A0024798E /* DNBDataRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBDataRef.cpp; sourceTree = "<group>"; }; - 26C637DC0C71334A0024798E /* DNBDataRef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBDataRef.h; sourceTree = "<group>"; }; - 26C637DD0C71334A0024798E /* DNBDefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = DNBDefs.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 26C637DE0C71334A0024798E /* DNBError.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBError.cpp; sourceTree = "<group>"; }; - 26C637DF0C71334A0024798E /* DNBError.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBError.h; sourceTree = "<group>"; }; - 26C637E00C71334A0024798E /* DNBLog.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBLog.cpp; sourceTree = "<group>"; }; - 26C637E10C71334A0024798E /* DNBLog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBLog.h; sourceTree = "<group>"; }; - 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBRegisterInfo.cpp; sourceTree = "<group>"; }; - 26C637E30C71334A0024798E /* DNBRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBRegisterInfo.h; sourceTree = "<group>"; }; - 260828DE0CBAF7F400F95054 /* DNBRuntimeAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBRuntimeAction.h; sourceTree = "<group>"; }; - 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBThreadResumeActions.cpp; sourceTree = "<group>"; }; - 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBThreadResumeActions.h; sourceTree = "<group>"; }; - 26A8FE1E0D11A77B00203048 /* DNBTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBTimer.h; sourceTree = "<group>"; }; - 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DarwinLogCollector.cpp; sourceTree = "<group>"; }; - 23AE72E31D25DECF00945BCE /* DarwinLogCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DarwinLogCollector.h; sourceTree = "<group>"; }; - 23CF6F5E1D28A3760088ADC9 /* DarwinLogEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogEvent.h; sourceTree = "<group>"; }; - 23AC04CC1D2F42F10072351D /* DarwinLogInterfaces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogInterfaces.h; sourceTree = "<group>"; }; - 23562ECF1D34110D00AB2BD4 /* DarwinLogTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogTypes.h; sourceTree = "<group>"; }; - 49D404611E39260F00570CDC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Genealogy.cpp; sourceTree = "<group>"; }; - AF0934BA18E12B92005A11FD /* Genealogy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Genealogy.h; sourceTree = "<group>"; }; - AF0934BB18E12B92005A11FD /* GenealogySPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenealogySPI.h; sourceTree = "<group>"; }; - 233B4EA51D2DB54300E98261 /* JSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSON.cpp; sourceTree = "<group>"; }; - 233B4EA61D2DB54300E98261 /* JSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSON.h; sourceTree = "<group>"; }; - 264F679A1B2F9EB200140093 /* JSONGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONGenerator.h; sourceTree = "<group>"; }; - 23AC04C41D2F41A00072351D /* LogFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilter.cpp; sourceTree = "<group>"; }; - 23AC04C51D2F41A00072351D /* LogFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilter.h; sourceTree = "<group>"; }; - 23AC04C81D2F42250072351D /* LogFilterChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterChain.cpp; sourceTree = "<group>"; }; - 23AC04C91D2F42250072351D /* LogFilterChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterChain.h; sourceTree = "<group>"; }; - 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterExactMatch.cpp; sourceTree = "<group>"; }; - 237821AF1D4917D20028B7A1 /* LogFilterExactMatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterExactMatch.h; sourceTree = "<group>"; }; - 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterRegex.cpp; sourceTree = "<group>"; }; - 23AC04CE1D2F58AF0072351D /* LogFilterRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterRegex.h; sourceTree = "<group>"; }; - 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogMessage.cpp; sourceTree = "<group>"; }; - 23AC04D11D2F60130072351D /* LogMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogMessage.h; sourceTree = "<group>"; }; - 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogMessageOsLog.cpp; sourceTree = "<group>"; }; - 23562ED11D3424DF00AB2BD4 /* LogMessageOsLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogMessageOsLog.h; sourceTree = "<group>"; }; - 26C637EE0C71334A0024798E /* MachException.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachException.cpp; sourceTree = "<group>"; }; - 26C637EF0C71334A0024798E /* MachException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachException.h; sourceTree = "<group>"; }; - 26C637F10C71334A0024798E /* MachProcess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachProcess.h; sourceTree = "<group>"; }; - 26C637F00C71334A0024798E /* MachProcess.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = MachProcess.mm; sourceTree = "<group>"; }; - 49F530111331519C008956F6 /* MachRegisterStatesI386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesI386.h; sourceTree = "<group>"; }; - 49F5301213316D7F008956F6 /* MachRegisterStatesX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesX86_64.h; sourceTree = "<group>"; }; - 26B67DE00EE9BC30006C8BC0 /* MachTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachTask.h; sourceTree = "<group>"; }; - 26B67DE10EE9BC30006C8BC0 /* MachTask.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MachTask.mm; sourceTree = "<group>"; }; - 26C637F20C71334A0024798E /* MachThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachThread.cpp; sourceTree = "<group>"; }; - 26C637F30C71334A0024798E /* MachThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachThread.h; sourceTree = "<group>"; }; - 26C637F40C71334A0024798E /* MachThreadList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachThreadList.cpp; sourceTree = "<group>"; }; - 26C637F50C71334A0024798E /* MachThreadList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachThreadList.h; sourceTree = "<group>"; }; - 26C637F60C71334A0024798E /* MachVMMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachVMMemory.cpp; sourceTree = "<group>"; }; - 26C637F70C71334A0024798E /* MachVMMemory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachVMMemory.h; sourceTree = "<group>"; }; - 26C637F80C71334A0024798E /* MachVMRegion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachVMRegion.cpp; sourceTree = "<group>"; }; - 26C637F90C71334A0024798E /* MachVMRegion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachVMRegion.h; sourceTree = "<group>"; }; - 23D1B0271D497E8B00FF831B /* OsLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OsLogger.cpp; sourceTree = "<group>"; }; - 23D1B0281D497E8B00FF831B /* OsLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OsLogger.h; sourceTree = "<group>"; }; - 26C637FD0C71334A0024798E /* PThreadCondition.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PThreadCondition.h; sourceTree = "<group>"; }; - 26C637FE0C71334A0024798E /* PThreadEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PThreadEvent.cpp; sourceTree = "<group>"; }; - 26C637FF0C71334A0024798E /* PThreadEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PThreadEvent.h; sourceTree = "<group>"; }; - 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PThreadMutex.cpp; sourceTree = "<group>"; }; - 26C638000C71334A0024798E /* PThreadMutex.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PThreadMutex.h; sourceTree = "<group>"; }; - AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoTerminal.cpp; sourceTree = "<group>"; }; - AF67AC000D34604D0022D128 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoTerminal.h; sourceTree = "<group>"; }; - 26A68F7E0D104EC800665A9E /* RNBContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RNBContext.cpp; sourceTree = "<group>"; }; - 26A68F7D0D104EC800665A9E /* RNBContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBContext.h; sourceTree = "<group>"; }; - 26E6B9DA0D1329010037ECDD /* RNBDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBDefs.h; sourceTree = "<group>"; }; - 26A68FD60D10574500665A9E /* RNBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RNBRemote.cpp; sourceTree = "<group>"; }; - 26A68FD50D10574500665A9E /* RNBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBRemote.h; sourceTree = "<group>"; }; - EF8878A00D9C797C001831DA /* RNBServices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RNBServices.cpp; sourceTree = "<group>"; }; - EF88789F0D9C797C001831DA /* RNBServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBServices.h; sourceTree = "<group>"; }; - 26A68FB00D1054DA00665A9E /* RNBSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RNBSocket.cpp; sourceTree = "<group>"; }; - 26A68FAF0D1054DA00665A9E /* RNBSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBSocket.h; sourceTree = "<group>"; }; - D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddress.cpp; path = ../../source/Host/common/SocketAddress.cpp; sourceTree = "<group>"; }; - AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdStringExtractor.cpp; sourceTree = "<group>"; }; - 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringConvert.cpp; path = ../../../source/Host/common/StringConvert.cpp; sourceTree = "<group>"; }; - 26C638010C71334A0024798E /* SysSignal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SysSignal.cpp; sourceTree = "<group>"; }; - 26C638020C71334A0024798E /* SysSignal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SysSignal.h; sourceTree = "<group>"; }; - 26C638050C71334A0024798E /* TTYState.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TTYState.cpp; sourceTree = "<group>"; }; - 26C638060C71334A0024798E /* TTYState.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TTYState.h; sourceTree = "<group>"; }; - 26203D1C1641EFB200A662F7 /* com.apple.debugserver.applist.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.applist.internal.plist; sourceTree = "<group>"; }; - EF88788B0D9C7558001831DA /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.applist.plist; sourceTree = "<group>"; }; - 26203D1D1641EFB200A662F7 /* com.apple.debugserver.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.internal.plist; sourceTree = "<group>"; }; - 26A4BAED0D498B7D00A9BEAB /* com.apple.debugserver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.plist; sourceTree = "<group>"; }; - 269E8DF8164B2ED200AD65F6 /* com.apple.debugserver.posix.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.posix.plist; sourceTree = "<group>"; }; - AF949ED620605DC2002A91F9 /* com.apple.internal.xpc.remote.debugserver.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.internal.xpc.remote.debugserver.plist; sourceTree = "<group>"; }; - 26C637E80C71334A0024798E /* dbgnub-mig.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 30; path = "dbgnub-mig.defs"; sourceTree = "<group>"; }; - 260FC7320E5B290400043FC9 /* debugnub-exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "debugnub-exports"; sourceTree = SOURCE_ROOT; }; - 26CE0594115C31C20022F371 /* debugserver */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = debugserver; sourceTree = BUILT_PRODUCTS_DIR; }; - 26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "debugserver-entitlements.plist"; sourceTree = "<group>"; }; - AF61C60418F75ABC00B48D9D /* debugserver-macosx-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "debugserver-macosx-entitlements.plist"; sourceTree = "<group>"; }; - 456F67721AD46CE9002850C2 /* debugserver-nonui */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "debugserver-nonui"; sourceTree = BUILT_PRODUCTS_DIR; }; - 26A02918114AB9240029C479 /* debugserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debugserver.cpp; sourceTree = "<group>"; }; - 9457ECF61419864100DFE7D8 /* stack_logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stack_logging.h; sourceTree = "<group>"; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 26CE0592115C31C20022F371 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 49D404621E39260F00570CDC /* Foundation.framework in Frameworks */, - 26CE05CF115C36F70022F371 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 456F676A1AD46CE9002850C2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 456F676B1AD46CE9002850C2 /* CoreFoundation.framework in Frameworks */, - AFA3FCA11E39984900218D5E /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 08FB7794FE84155DC02AAC07 /* dbgnub */ = { - isa = PBXGroup; - children = ( - D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */, - 26ACA3330D3E94F200A2120B /* Framework */, - 26C637D50C71334A0024798E /* source */, - 1AB674ADFE9D54B511CA2CBB /* Products */, - 49D404601E39260F00570CDC /* Frameworks */, - ); - name = dbgnub; - sourceTree = "<group>"; - }; - 1AB674ADFE9D54B511CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 26CE0594115C31C20022F371 /* debugserver */, - 456F67721AD46CE9002850C2 /* debugserver-nonui */, - ); - name = Products; - sourceTree = "<group>"; - }; - 23AC04C31D2F3E9A0072351D /* DarwinLog */ = { - isa = PBXGroup; - children = ( - 237821AD1D4917D20028B7A1 /* CMakeLists.txt */, - 23562ED41D3426DD00AB2BD4 /* ActivityStore.h */, - 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */, - 23AE72E61D25DEFB00945BCE /* ActivityStreamSPI.h */, - 23AE72E31D25DECF00945BCE /* DarwinLogCollector.h */, - 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */, - 23CF6F5E1D28A3760088ADC9 /* DarwinLogEvent.h */, - 23AC04CC1D2F42F10072351D /* DarwinLogInterfaces.h */, - 23562ECF1D34110D00AB2BD4 /* DarwinLogTypes.h */, - 23AC04C51D2F41A00072351D /* LogFilter.h */, - 23AC04C41D2F41A00072351D /* LogFilter.cpp */, - 23AC04C91D2F42250072351D /* LogFilterChain.h */, - 23AC04C81D2F42250072351D /* LogFilterChain.cpp */, - 237821AF1D4917D20028B7A1 /* LogFilterExactMatch.h */, - 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */, - 23AC04CE1D2F58AF0072351D /* LogFilterRegex.h */, - 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */, - 23AC04D11D2F60130072351D /* LogMessage.h */, - 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */, - 23562ED11D3424DF00AB2BD4 /* LogMessageOsLog.h */, - 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */, - ); - path = DarwinLog; - sourceTree = "<group>"; - }; - 266B5ECE1460A68200E43F0A /* arm64 */ = { - isa = PBXGroup; - children = ( - 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */, - 266B5ED01460A68200E43F0A /* DNBArchImplARM64.h */, - ); - path = arm64; - sourceTree = "<group>"; - }; - 2675D41C0CCEB6CF000F49AF /* arm */ = { - isa = PBXGroup; - children = ( - 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */, - 2675D4230CCEB705000F49AF /* DNBArchImpl.h */, - ); - name = arm; - sourceTree = "<group>"; - }; - 26A028FE114AB6A60029C479 /* Resources */ = { - isa = PBXGroup; - children = ( - 26A4BAED0D498B7D00A9BEAB /* com.apple.debugserver.plist */, - EF88788B0D9C7558001831DA /* com.apple.debugserver.applist.plist */, - 269E8DF8164B2ED200AD65F6 /* com.apple.debugserver.posix.plist */, - 26203D1C1641EFB200A662F7 /* com.apple.debugserver.applist.internal.plist */, - 26203D1D1641EFB200A662F7 /* com.apple.debugserver.internal.plist */, - AF949ED620605DC2002A91F9 /* com.apple.internal.xpc.remote.debugserver.plist */, - 260FC7320E5B290400043FC9 /* debugnub-exports */, - 26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */, - AF61C60418F75ABC00B48D9D /* debugserver-macosx-entitlements.plist */, - ); - name = Resources; - sourceTree = "<group>"; - }; - 26A028FF114AB6BB0029C479 /* libdebugnub */ = { - isa = PBXGroup; - children = ( - 26C637E60C71334A0024798E /* MacOSX */, - 260828DE0CBAF7F400F95054 /* DNBRuntimeAction.h */, - 26A8FE1E0D11A77B00203048 /* DNBTimer.h */, - 26C637D70C71334A0024798E /* DNB.h */, - 26C637D60C71334A0024798E /* DNB.cpp */, - 26C637D80C71334A0024798E /* DNBArch.h */, - 264D5D571293835600ED4C01 /* DNBArch.cpp */, - 26C637DA0C71334A0024798E /* DNBBreakpoint.h */, - 26C637D90C71334A0024798E /* DNBBreakpoint.cpp */, - 26C637DC0C71334A0024798E /* DNBDataRef.h */, - 26C637DB0C71334A0024798E /* DNBDataRef.cpp */, - 26C637DD0C71334A0024798E /* DNBDefs.h */, - 26C637DF0C71334A0024798E /* DNBError.h */, - 26C637DE0C71334A0024798E /* DNBError.cpp */, - 26C637E10C71334A0024798E /* DNBLog.h */, - 26C637E00C71334A0024798E /* DNBLog.cpp */, - 26C637E30C71334A0024798E /* DNBRegisterInfo.h */, - 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */, - 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */, - 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */, - 233B4EA61D2DB54300E98261 /* JSON.h */, - 233B4EA51D2DB54300E98261 /* JSON.cpp */, - 264F679A1B2F9EB200140093 /* JSONGenerator.h */, - AF67AC000D34604D0022D128 /* PseudoTerminal.h */, - AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */, - 26C637FD0C71334A0024798E /* PThreadCondition.h */, - 26C637FF0C71334A0024798E /* PThreadEvent.h */, - 26C637FE0C71334A0024798E /* PThreadEvent.cpp */, - 26C638000C71334A0024798E /* PThreadMutex.h */, - 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */, - 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */, - 26C638020C71334A0024798E /* SysSignal.h */, - 26C638010C71334A0024798E /* SysSignal.cpp */, - 26C638060C71334A0024798E /* TTYState.h */, - 26C638050C71334A0024798E /* TTYState.cpp */, - ); - name = libdebugnub; - sourceTree = "<group>"; - }; - 26ACA3330D3E94F200A2120B /* Framework */ = { - isa = PBXGroup; - children = ( - 26ACA3340D3E956300A2120B /* CoreFoundation.framework */, - ); - name = Framework; - sourceTree = "<group>"; - }; - 26C637D50C71334A0024798E /* source */ = { - isa = PBXGroup; - children = ( - 26593A060D4931CC001C9FE3 /* ChangeLog */, - 26DEFD6C0D104C23008A5A07 /* debugserver */, - 26A028FF114AB6BB0029C479 /* libdebugnub */, - ); - indentWidth = 4; - path = source; - sourceTree = "<group>"; - tabWidth = 4; - usesTabs = 0; - }; - 26C637E60C71334A0024798E /* MacOSX */ = { - isa = PBXGroup; - children = ( - 23AC04C31D2F3E9A0072351D /* DarwinLog */, - 2695DD920D3EBFF6007E4CA2 /* CFBundle.h */, - 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */, - 2695DD9A0D3EC160007E4CA2 /* CFString.h */, - 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */, - 26C637E70C71334A0024798E /* CFUtils.h */, - 2307CCCC1D4A5DAE0016ABC0 /* CMakeLists.txt */, - 2675D41C0CCEB6CF000F49AF /* arm */, - 266B5ECE1460A68200E43F0A /* arm64 */, - 26C637E90C71334A0024798E /* i386 */, - 26C637FA0C71334A0024798E /* ppc */, - 26CF99A11142EB7400011AAB /* x86_64 */, - 26C637E80C71334A0024798E /* dbgnub-mig.defs */, - AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */, - AF0934BA18E12B92005A11FD /* Genealogy.h */, - AF0934BB18E12B92005A11FD /* GenealogySPI.h */, - 26C637EF0C71334A0024798E /* MachException.h */, - 26C637EE0C71334A0024798E /* MachException.cpp */, - 26C637F10C71334A0024798E /* MachProcess.h */, - 26C637F00C71334A0024798E /* MachProcess.mm */, - 26C637F30C71334A0024798E /* MachThread.h */, - 26C637F20C71334A0024798E /* MachThread.cpp */, - 26C637F50C71334A0024798E /* MachThreadList.h */, - 26C637F40C71334A0024798E /* MachThreadList.cpp */, - 26C637F70C71334A0024798E /* MachVMMemory.h */, - 26C637F60C71334A0024798E /* MachVMMemory.cpp */, - 26C637F90C71334A0024798E /* MachVMRegion.h */, - 26C637F80C71334A0024798E /* MachVMRegion.cpp */, - 26B67DE00EE9BC30006C8BC0 /* MachTask.h */, - 26B67DE10EE9BC30006C8BC0 /* MachTask.mm */, - 23D1B0281D497E8B00FF831B /* OsLogger.h */, - 23D1B0271D497E8B00FF831B /* OsLogger.cpp */, - 9457ECF61419864100DFE7D8 /* stack_logging.h */, - ); - path = MacOSX; - sourceTree = "<group>"; - }; - 26C637E90C71334A0024798E /* i386 */ = { - isa = PBXGroup; - children = ( - 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */, - 26C637EB0C71334A0024798E /* DNBArchImplI386.h */, - 49F530111331519C008956F6 /* MachRegisterStatesI386.h */, - ); - path = i386; - sourceTree = "<group>"; - }; - 26C637FA0C71334A0024798E /* ppc */ = { - isa = PBXGroup; - children = ( - 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */, - 26C637FC0C71334A0024798E /* DNBArchImpl.h */, - ); - path = ppc; - sourceTree = "<group>"; - }; - 26CF99A11142EB7400011AAB /* x86_64 */ = { - isa = PBXGroup; - children = ( - 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */, - 26CF99A31142EB7400011AAB /* DNBArchImplX86_64.h */, - 49F5301213316D7F008956F6 /* MachRegisterStatesX86_64.h */, - ); - path = x86_64; - sourceTree = "<group>"; - }; - 26DEFD6C0D104C23008A5A07 /* debugserver */ = { - isa = PBXGroup; - children = ( - 26A02918114AB9240029C479 /* debugserver.cpp */, - 26A028FE114AB6A60029C479 /* Resources */, - 26A68F7D0D104EC800665A9E /* RNBContext.h */, - 26A68F7E0D104EC800665A9E /* RNBContext.cpp */, - EF88789F0D9C797C001831DA /* RNBServices.h */, - EF8878A00D9C797C001831DA /* RNBServices.cpp */, - 26A68FAF0D1054DA00665A9E /* RNBSocket.h */, - 26A68FB00D1054DA00665A9E /* RNBSocket.cpp */, - 26A68FD50D10574500665A9E /* RNBRemote.h */, - 26A68FD60D10574500665A9E /* RNBRemote.cpp */, - 26E6B9DA0D1329010037ECDD /* RNBDefs.h */, - AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */, - ); - name = debugserver; - sourceTree = "<group>"; - usesTabs = 0; - }; - 49D404601E39260F00570CDC /* Frameworks */ = { - isa = PBXGroup; - children = ( - 49D404611E39260F00570CDC /* Foundation.framework */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 26CE0593115C31C20022F371 /* debugserver */ = { - isa = PBXNativeTarget; - buildConfigurationList = 26CE05A4115C31ED0022F371 /* Build configuration list for PBXNativeTarget "debugserver" */; - buildPhases = ( - 26CE0591115C31C20022F371 /* Sources */, - 26CE0592115C31C20022F371 /* Frameworks */, - 4C3326CB18B2A2F600EB5DD7 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = debugserver; - productName = "lldb-debugserver"; - productReference = 26CE0594115C31C20022F371 /* debugserver */; - productType = "com.apple.product-type.tool"; - }; - 456F67431AD46CE9002850C2 /* debugserver-mini */ = { - isa = PBXNativeTarget; - buildConfigurationList = 456F676D1AD46CE9002850C2 /* Build configuration list for PBXNativeTarget "debugserver-mini" */; - buildPhases = ( - 456F67451AD46CE9002850C2 /* Sources */, - 456F676A1AD46CE9002850C2 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "debugserver-mini"; - productName = "lldb-debugserver"; - productReference = 456F67721AD46CE9002850C2 /* debugserver-nonui */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 08FB7793FE84155DC02AAC07 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0720; - }; - buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "debugserver" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 08FB7794FE84155DC02AAC07 /* dbgnub */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 26CE0593115C31C20022F371 /* debugserver */, - 456F67431AD46CE9002850C2 /* debugserver-mini */, - ); - }; -/* 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; - buildActionMask = 2147483647; - files = ( - D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */, - 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */, - 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */, - 26CE05A9115C36250022F371 /* debugserver.cpp in Sources */, - AF48558C1D75126800D19C07 /* StdStringExtractor.cpp in Sources */, - 26CE05AA115C36260022F371 /* RNBContext.cpp in Sources */, - 26CE05AB115C36270022F371 /* RNBServices.cpp in Sources */, - 23D1B0291D497E8B00FF831B /* OsLogger.cpp in Sources */, - 26CE05AC115C36280022F371 /* RNBSocket.cpp in Sources */, - 26CE05AD115C36280022F371 /* RNBRemote.cpp in Sources */, - 26CE05AE115C36320022F371 /* dbgnub-mig.defs in Sources */, - 26CE05B0115C36340022F371 /* MachException.cpp in Sources */, - 26CE05B1115C36350022F371 /* MachProcess.mm in Sources */, - 26CE05B2115C36360022F371 /* MachThread.cpp in Sources */, - 233B4EA71D2DB54300E98261 /* JSON.cpp in Sources */, - 26CE05B3115C36370022F371 /* MachThreadList.cpp in Sources */, - 26CE05B4115C36380022F371 /* MachVMMemory.cpp in Sources */, - 26CE05B5115C36380022F371 /* MachVMRegion.cpp in Sources */, - 26CE05B6115C36390022F371 /* MachTask.mm in Sources */, - 26CE05B7115C363B0022F371 /* DNB.cpp in Sources */, - AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */, - 23AC04CF1D2F58AF0072351D /* LogFilterRegex.cpp in Sources */, - 233B4EA91D2DB96A00E98261 /* StringConvert.cpp in Sources */, - 23562ED21D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */, - 26CE05B8115C363C0022F371 /* DNBBreakpoint.cpp in Sources */, - 26CE05B9115C363D0022F371 /* DNBDataRef.cpp in Sources */, - 23AC04CA1D2F42250072351D /* LogFilterChain.cpp in Sources */, - 23562ED61D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */, - 26CE05BA115C363E0022F371 /* DNBLog.cpp in Sources */, - 23AC04C61D2F41A00072351D /* LogFilter.cpp in Sources */, - 26CE05BB115C363F0022F371 /* DNBRegisterInfo.cpp in Sources */, - 26CE05BC115C36420022F371 /* PThreadEvent.cpp in Sources */, - 26CE05BD115C36430022F371 /* PThreadMutex.cpp in Sources */, - 26CE05BE115C36440022F371 /* SysSignal.cpp in Sources */, - 23AE72E41D25DECF00945BCE /* DarwinLogCollector.cpp in Sources */, - 26CE05BF115C364D0022F371 /* DNBArchImplX86_64.cpp in Sources */, - 26CE05C0115C364F0022F371 /* DNBArchImplI386.cpp in Sources */, - 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */, - 26CE05C2115C36550022F371 /* DNBArchImpl.cpp in Sources */, - 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */, - 26CE05C3115C36580022F371 /* CFString.cpp in Sources */, - 23562ED91D342B0000AB2BD4 /* LogMessage.cpp in Sources */, - 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */, - 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */, - 237821B01D4917D20028B7A1 /* LogFilterExactMatch.cpp in Sources */, - 266B5ED11460A68200E43F0A /* DNBArchImplARM64.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 456F67451AD46CE9002850C2 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 456F67461AD46CE9002850C2 /* DNBError.cpp in Sources */, - 456F67471AD46CE9002850C2 /* DNBThreadResumeActions.cpp in Sources */, - 456F67481AD46CE9002850C2 /* debugserver.cpp in Sources */, - 23043C9D1D35DBEC00FC25CA /* JSON.cpp in Sources */, - 456F67491AD46CE9002850C2 /* RNBContext.cpp in Sources */, - 23D1B02A1D497E8B00FF831B /* OsLogger.cpp in Sources */, - 456F674A1AD46CE9002850C2 /* RNBServices.cpp in Sources */, - 456F674B1AD46CE9002850C2 /* RNBSocket.cpp in Sources */, - 456F674C1AD46CE9002850C2 /* RNBRemote.cpp in Sources */, - 456F674D1AD46CE9002850C2 /* dbgnub-mig.defs in Sources */, - 456F674E1AD46CE9002850C2 /* MachException.cpp in Sources */, - 456F674F1AD46CE9002850C2 /* MachProcess.mm in Sources */, - 2307CCCB1D4A5D630016ABC0 /* LogFilterExactMatch.cpp in Sources */, - 456F67501AD46CE9002850C2 /* MachThread.cpp in Sources */, - 456F67511AD46CE9002850C2 /* MachThreadList.cpp in Sources */, - 456F67521AD46CE9002850C2 /* MachVMMemory.cpp in Sources */, - 456F67531AD46CE9002850C2 /* MachVMRegion.cpp in Sources */, - 23562ED71D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */, - 456F67541AD46CE9002850C2 /* MachTask.mm in Sources */, - 456F67551AD46CE9002850C2 /* DNB.cpp in Sources */, - 456F67561AD46CE9002850C2 /* Genealogy.cpp in Sources */, - 456F67571AD46CE9002850C2 /* DNBBreakpoint.cpp in Sources */, - 456F67581AD46CE9002850C2 /* DNBDataRef.cpp in Sources */, - 456F67591AD46CE9002850C2 /* DNBLog.cpp in Sources */, - 23562ED31D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */, - 456F675A1AD46CE9002850C2 /* DNBRegisterInfo.cpp in Sources */, - 456F675B1AD46CE9002850C2 /* PThreadEvent.cpp in Sources */, - 456F675C1AD46CE9002850C2 /* PThreadMutex.cpp in Sources */, - 456F675D1AD46CE9002850C2 /* SysSignal.cpp in Sources */, - 23AE72E51D25DEE100945BCE /* DarwinLogCollector.cpp in Sources */, - 456F675E1AD46CE9002850C2 /* DNBArchImplX86_64.cpp in Sources */, - 23562EDA1D342B0000AB2BD4 /* LogMessage.cpp in Sources */, - 456F675F1AD46CE9002850C2 /* DNBArchImplI386.cpp in Sources */, - 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */, - 23AC04C71D2F41A00072351D /* LogFilter.cpp in Sources */, - 23043C9E1D35DBFA00FC25CA /* StringConvert.cpp in Sources */, - 456F67611AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */, - AF588449206077BD00A0CB5A /* SocketAddress.cpp in Sources */, - 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */, - 23AC04CB1D2F42250072351D /* LogFilterChain.cpp in Sources */, - AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */, - 456F67641AD46CE9002850C2 /* CFBundle.cpp in Sources */, - 456F67651AD46CE9002850C2 /* PseudoTerminal.cpp in Sources */, - 456F67671AD46CE9002850C2 /* DNBArch.cpp in Sources */, - 23AC04D01D2F58AF0072351D /* LogFilterRegex.cpp in Sources */, - 456F67691AD46CE9002850C2 /* DNBArchImplARM64.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 1DEB914F08733D8E0010E9CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 360.99.0; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ""; - STRIP_INSTALLED_PRODUCT = NO; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = Debug; - }; - 1DEB915008733D8E0010E9CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEAD_CODE_STRIPPING = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ""; - STRIPFLAGS = "-x"; - STRIP_STYLE = debugging; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = Release; - }; - 262419A11198A93E00067686 /* BuildAndIntegration */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEAD_CODE_STRIPPING = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 1; - OTHER_CFLAGS = ""; - STRIPFLAGS = "-x"; - STRIP_STYLE = debugging; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = BuildAndIntegration; - }; - 262419A21198A93E00067686 /* BuildAndIntegration */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = "-"; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_BUILDANDINTEGRATION; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; - INSTALL_PATH = /usr/bin; - "INSTALL_PATH[sdk=iphoneos*]" = /Developer/usr/bin/; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "$(LLDB_ENERGY_CFLAGS)", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_FBS", - "-DWITH_BKS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - SDKROOT = macosx; - SKIP_INSTALL = YES; - "SKIP_INSTALL[sdk=iphoneos*]" = NO; - STRIP_INSTALLED_PRODUCT = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = BuildAndIntegration; - }; - 26CE0596115C31C30022F371 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_BKS", - "-DWITH_FBS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = Debug; - }; - 26CE0597115C31C30022F371 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_RELEASE; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_FBS", - "-DWITH_BKS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = Release; - }; - 456F676E1AD46CE9002850C2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - 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[sdk=macosx*]" = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 360.99.0; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INSTALL_PATH = /usr/local/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DOS_OBJECT_USE_OBJC=0", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - Foundation, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = "debugserver-nonui"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - ZERO_LINK = NO; - }; - name = Debug; - }; - 456F676F1AD46CE9002850C2 /* DebugClang */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "$(LLDB_ENERGY_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DOS_OBJECT_USE_OBJC=0", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - Foundation, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = "debugserver-nonui"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = DebugClang; - }; - 456F67701AD46CE9002850C2 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_RELEASE; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; - INSTALL_PATH = /usr/local/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "$(LLDB_ENERGY_CFLAGS)", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DOS_OBJECT_USE_OBJC=0", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - Foundation, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = "debugserver-nonui"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = Release; - }; - 456F67711AD46CE9002850C2 /* BuildAndIntegration */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = "-"; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_BUILDANDINTEGRATION; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; - INSTALL_PATH = /usr/local/bin; - "INSTALL_PATH[sdk=iphoneos*]" = /usr/local/bin; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "$(LLDB_ENERGY_CFLAGS)", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*]" = ( - "-Wparentheses", - "-DOS_OBJECT_USE_OBJC=0", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - Foundation, - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = "debugserver-nonui"; - SDKROOT = macosx; - SKIP_INSTALL = YES; - "SKIP_INSTALL[sdk=iphoneos*]" = NO; - STRIP_INSTALLED_PRODUCT = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = BuildAndIntegration; - }; - 4968B7A916657FAE00741ABB /* DebugClang */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 360.99.0; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - STRIP_INSTALLED_PRODUCT = NO; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = DebugClang; - }; - 4968B7AA16657FAE00741ABB /* DebugClang */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_FBS", - "-DWITH_BKS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = DebugClang; - }; - 940AD5251B1FE3B10051E88F /* DebugPresubmission */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 360.99.0; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - STRIP_INSTALLED_PRODUCT = NO; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = DebugPresubmission; - }; - 940AD5261B1FE3B10051E88F /* DebugPresubmission */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_FBS", - "-DWITH_BKS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = DebugPresubmission; - }; - 940AD5271B1FE3B10051E88F /* DebugPresubmission */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/local/bin; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "$(LLDB_ENERGY_CFLAGS)", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DOS_OBJECT_USE_OBJC=0", - "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - Foundation, - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = "debugserver-nonui"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = DebugPresubmission; - }; - 94BA9B361B1A7C5700035A23 /* CustomSwift-Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "lldb-debugserver-nonui"; - }; - name = "CustomSwift-Debug"; - }; - 94BA9B371B1A7C5700035A23 /* CustomSwift-Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "lldb-debugserver-nonui"; - }; - name = "CustomSwift-Release"; - }; - 94D72C871ADF10AA00A3F718 /* CustomSwift-Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 360.99.0; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - STRIP_INSTALLED_PRODUCT = NO; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = "CustomSwift-Debug"; - }; - 94D72C881ADF10AA00A3F718 /* CustomSwift-Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_BKS", - "-DWITH_FBS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ""; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = "CustomSwift-Debug"; - }; - 94D72C891ADF10B000A3F718 /* CustomSwift-Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = arm64; - "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEAD_CODE_STRIPPING = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; - LLDB_USE_OS_LOG = 0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - STRIPFLAGS = "-x"; - STRIP_STYLE = debugging; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_BUILDER = "$(USER)"; - }; - name = "CustomSwift-Release"; - }; - 94D72C8A1ADF10B000A3F718 /* CustomSwift-Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - 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*]" = ""; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 360.99.0; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; - "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)/Developer/Library/PrivateFrameworks", - ); - "FRAMEWORK_SEARCH_PATHS[sdk=macosx*][arch=*]" = "$(SDKROOT)/System/Library/PrivateFrameworks"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_RELEASE; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; - INSTALL_PATH = /usr/bin; - LLDB_COMPRESSION_LDFLAGS = "-lcompression"; - LLDB_DEBUGSERVER = 1; - LLDB_ENERGY_CFLAGS = ""; - "LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY"; - LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample"; - OTHER_CFLAGS = ( - "-Wparentheses", - "-DDT_VARIANT_$(DT_VARIANT)", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - ); - "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( - "-Wparentheses", - "-DWITH_LOCKDOWN", - "-DWITH_FBS", - "-DWITH_BKS", - "-DOS_OBJECT_USE_OBJC=0", - "$(LLDB_ENERGY_CFLAGS)", - "$(LLDB_OS_LOG_CFLAGS)", - "-isystem", - "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", - ); - "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "-framework", - SpringBoardServices, - "-framework", - BackBoardServices, - "-llockdown", - "-framework", - FrontBoardServices, - "-framework", - MobileCoreServices, - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-sectcreate", - __TEXT, - __info_plist, - "$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist", - "$(LLDB_ENERGY_LDFLAGS)", - "$(LLDB_COMPRESSION_LDFLAGS)", - ); - OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)"; - PRODUCT_NAME = debugserver; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - "PROVISIONING_PROFILE[sdk=macosx*]" = ""; - SDKROOT = macosx; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR) ../../include"; - ZERO_LINK = NO; - }; - name = "CustomSwift-Release"; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "debugserver" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB914F08733D8E0010E9CD /* Debug */, - 94D72C871ADF10AA00A3F718 /* CustomSwift-Debug */, - 4968B7A916657FAE00741ABB /* DebugClang */, - 940AD5251B1FE3B10051E88F /* DebugPresubmission */, - 1DEB915008733D8E0010E9CD /* Release */, - 94D72C891ADF10B000A3F718 /* CustomSwift-Release */, - 262419A11198A93E00067686 /* BuildAndIntegration */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = BuildAndIntegration; - }; - 26CE05A4115C31ED0022F371 /* Build configuration list for PBXNativeTarget "debugserver" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 26CE0596115C31C30022F371 /* Debug */, - 94D72C881ADF10AA00A3F718 /* CustomSwift-Debug */, - 4968B7AA16657FAE00741ABB /* DebugClang */, - 940AD5261B1FE3B10051E88F /* DebugPresubmission */, - 26CE0597115C31C30022F371 /* Release */, - 94D72C8A1ADF10B000A3F718 /* CustomSwift-Release */, - 262419A21198A93E00067686 /* BuildAndIntegration */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = BuildAndIntegration; - }; - 456F676D1AD46CE9002850C2 /* Build configuration list for PBXNativeTarget "debugserver-mini" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 456F676E1AD46CE9002850C2 /* Debug */, - 456F676F1AD46CE9002850C2 /* DebugClang */, - 940AD5271B1FE3B10051E88F /* DebugPresubmission */, - 456F67701AD46CE9002850C2 /* Release */, - 456F67711AD46CE9002850C2 /* BuildAndIntegration */, - 94BA9B361B1A7C5700035A23 /* CustomSwift-Debug */, - 94BA9B371B1A7C5700035A23 /* CustomSwift-Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = BuildAndIntegration; - }; -/* End XCConfigurationList section */ - }; - rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; -} diff --git a/tools/debugserver/debugserver.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/tools/debugserver/debugserver.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index c24931480d46..000000000000 --- a/tools/debugserver/debugserver.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Workspace - version = "1.0"> - <FileRef - location = "self:debugserver.xcodeproj"> - </FileRef> -</Workspace> diff --git a/tools/debugserver/debugserver.xcodeproj/xcshareddata/xcschemes/debugserver.xcscheme b/tools/debugserver/debugserver.xcodeproj/xcshareddata/xcschemes/debugserver.xcscheme deleted file mode 100644 index 2f27b5e4eff5..000000000000 --- a/tools/debugserver/debugserver.xcodeproj/xcshareddata/xcschemes/debugserver.xcscheme +++ /dev/null @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Scheme - LastUpgradeVersion = "0720" - version = "1.8"> - <BuildAction - parallelizeBuildables = "NO" - buildImplicitDependencies = "YES"> - <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "26CE0593115C31C20022F371" - BuildableName = "debugserver" - BlueprintName = "debugserver" - ReferencedContainer = "container:debugserver.xcodeproj"> - </BuildableReference> - </BuildActionEntry> - </BuildActionEntries> - </BuildAction> - <TestAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB" - shouldUseLaunchSchemeArgsEnv = "YES"> - <Testables> - </Testables> - <MacroExpansion> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "26CE0593115C31C20022F371" - BuildableName = "debugserver" - BlueprintName = "debugserver" - ReferencedContainer = "container:debugserver.xcodeproj"> - </BuildableReference> - </MacroExpansion> - <EnvironmentVariables> - <EnvironmentVariable - key = "UBBY" - value = "" - isEnabled = "YES"> - </EnvironmentVariable> - </EnvironmentVariables> - <AdditionalOptions> - </AdditionalOptions> - </TestAction> - <LaunchAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" - selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - displayScaleIsEnabled = "NO" - displayScale = "1.00" - launchStyle = "0" - useCustomWorkingDirectory = "NO" - ignoresPersistentStateOnLaunch = "NO" - debugDocumentVersioning = "YES" - debugServiceExtension = "internal" - allowLocationSimulation = "YES" - queueDebuggingEnabled = "No"> - <BuildableProductRunnable - runnableDebuggingMode = "0"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "26CE0593115C31C20022F371" - BuildableName = "debugserver" - BlueprintName = "debugserver" - ReferencedContainer = "container:debugserver.xcodeproj"> - </BuildableReference> - </BuildableProductRunnable> - <AdditionalOptions> - </AdditionalOptions> - </LaunchAction> - <ProfileAction - displayScaleIsEnabled = "NO" - displayScale = "1.00" - buildConfiguration = "Release" - shouldUseLaunchSchemeArgsEnv = "YES" - savedToolIdentifier = "" - useCustomWorkingDirectory = "NO" - debugDocumentVersioning = "YES"> - <BuildableProductRunnable - runnableDebuggingMode = "0"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "26CE0593115C31C20022F371" - BuildableName = "debugserver" - BlueprintName = "debugserver" - ReferencedContainer = "container:debugserver.xcodeproj"> - </BuildableReference> - </BuildableProductRunnable> - <EnvironmentVariables> - <EnvironmentVariable - key = "UBBY" - value = "" - isEnabled = "YES"> - </EnvironmentVariable> - </EnvironmentVariables> - </ProfileAction> - <AnalyzeAction - buildConfiguration = "Debug"> - </AnalyzeAction> - <ArchiveAction - buildConfiguration = "Release" - revealArchiveInOrganizer = "YES"> - </ArchiveAction> -</Scheme> diff --git a/tools/debugserver/resources/lldb-debugserver-Info.plist b/tools/debugserver/resources/lldb-debugserver-Info.plist deleted file mode 100644 index 343325c2765c..000000000000 --- a/tools/debugserver/resources/lldb-debugserver-Info.plist +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>English</string> - <key>CFBundleIdentifier</key> - <string>com.apple.debugserver</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>debugserver</string> - <key>CFBundleVersion</key> - <string>2</string> - <key>SecTaskAccess</key> - <array> - <string>allowed</string> - <string>debug</string> - </array> -</dict> -</plist> diff --git a/tools/debugserver/scripts/diagnose-termination.d b/tools/debugserver/scripts/diagnose-termination.d deleted file mode 100644 index d216c9750033..000000000000 --- a/tools/debugserver/scripts/diagnose-termination.d +++ /dev/null @@ -1,18 +0,0 @@ -fbt::exception_deliver:entry -{ - printf("pid %d got an exception of type %d\n", pid, arg1); - stack(); - ustack(); -} - -syscall::kill:entry -{ - printf("pid %d called kill(%d, %d)\n", pid, arg0, arg1); - ustack(); -} - -syscall::__pthread_kill:entry -{ - printf("pid %d called pthread_kill(%p, %d)\n", pid, arg0, arg1); - ustack(); -} diff --git a/tools/debugserver/source/ARM_DWARF_Registers.h b/tools/debugserver/source/ARM_DWARF_Registers.h deleted file mode 100644 index 037d28bf1304..000000000000 --- a/tools/debugserver/source/ARM_DWARF_Registers.h +++ /dev/null @@ -1,206 +0,0 @@ -//===-- ARM_DWARF_Registers.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ARM_DWARF_Registers_h_ -#define ARM_DWARF_Registers_h_ - -enum { - dwarf_r0 = 0, - dwarf_r1, - dwarf_r2, - dwarf_r3, - dwarf_r4, - dwarf_r5, - dwarf_r6, - dwarf_r7, - dwarf_r8, - dwarf_r9, - dwarf_r10, - dwarf_r11, - dwarf_r12, - dwarf_sp, - dwarf_lr, - dwarf_pc, - dwarf_cpsr, - - dwarf_s0 = 64, - dwarf_s1, - dwarf_s2, - dwarf_s3, - dwarf_s4, - dwarf_s5, - dwarf_s6, - dwarf_s7, - dwarf_s8, - dwarf_s9, - dwarf_s10, - dwarf_s11, - dwarf_s12, - dwarf_s13, - dwarf_s14, - dwarf_s15, - dwarf_s16, - dwarf_s17, - dwarf_s18, - dwarf_s19, - dwarf_s20, - dwarf_s21, - dwarf_s22, - dwarf_s23, - dwarf_s24, - dwarf_s25, - dwarf_s26, - dwarf_s27, - dwarf_s28, - dwarf_s29, - dwarf_s30, - dwarf_s31, - - // FPA Registers 0-7 - dwarf_f0 = 96, - dwarf_f1, - dwarf_f2, - dwarf_f3, - dwarf_f4, - dwarf_f5, - dwarf_f6, - dwarf_f7, - - // Intel wireless MMX general purpose registers 0 - 7 - dwarf_wCGR0 = 104, - dwarf_wCGR1, - dwarf_wCGR2, - dwarf_wCGR3, - dwarf_wCGR4, - dwarf_wCGR5, - dwarf_wCGR6, - dwarf_wCGR7, - - // XScale accumulator register 0–7 (they do overlap with wCGR0 - wCGR7) - dwarf_ACC0 = 104, - dwarf_ACC1, - dwarf_ACC2, - dwarf_ACC3, - dwarf_ACC4, - dwarf_ACC5, - dwarf_ACC6, - dwarf_ACC7, - - // Intel wireless MMX data registers 0 - 15 - dwarf_wR0 = 112, - dwarf_wR1, - dwarf_wR2, - dwarf_wR3, - dwarf_wR4, - dwarf_wR5, - dwarf_wR6, - dwarf_wR7, - dwarf_wR8, - dwarf_wR9, - dwarf_wR10, - dwarf_wR11, - dwarf_wR12, - dwarf_wR13, - dwarf_wR14, - dwarf_wR15, - - dwarf_spsr = 128, - dwarf_spsr_fiq, - dwarf_spsr_irq, - dwarf_spsr_abt, - dwarf_spsr_und, - dwarf_spsr_svc, - - dwarf_r8_usr = 144, - dwarf_r9_usr, - dwarf_r10_usr, - dwarf_r11_usr, - dwarf_r12_usr, - dwarf_r13_usr, - dwarf_r14_usr, - dwarf_r8_fiq, - dwarf_r9_fiq, - dwarf_r10_fiq, - dwarf_r11_fiq, - dwarf_r12_fiq, - dwarf_r13_fiq, - dwarf_r14_fiq, - dwarf_r13_irq, - dwarf_r14_irq, - dwarf_r13_abt, - dwarf_r14_abt, - dwarf_r13_und, - dwarf_r14_und, - dwarf_r13_svc, - dwarf_r14_svc, - - // Intel wireless MMX control register in co-processor 0 - 7 - dwarf_wC0 = 192, - dwarf_wC1, - dwarf_wC2, - dwarf_wC3, - dwarf_wC4, - dwarf_wC5, - dwarf_wC6, - dwarf_wC7, - - // VFP-v3/Neon - dwarf_d0 = 256, - dwarf_d1, - dwarf_d2, - dwarf_d3, - dwarf_d4, - dwarf_d5, - dwarf_d6, - dwarf_d7, - dwarf_d8, - dwarf_d9, - dwarf_d10, - dwarf_d11, - dwarf_d12, - dwarf_d13, - dwarf_d14, - dwarf_d15, - dwarf_d16, - dwarf_d17, - dwarf_d18, - dwarf_d19, - dwarf_d20, - dwarf_d21, - dwarf_d22, - dwarf_d23, - dwarf_d24, - dwarf_d25, - dwarf_d26, - dwarf_d27, - dwarf_d28, - dwarf_d29, - dwarf_d30, - dwarf_d31, - - // Neon quadword registers - dwarf_q0 = 288, - dwarf_q1, - dwarf_q2, - dwarf_q3, - dwarf_q4, - dwarf_q5, - dwarf_q6, - dwarf_q7, - dwarf_q8, - dwarf_q9, - dwarf_q10, - dwarf_q11, - dwarf_q12, - dwarf_q13, - dwarf_q14, - dwarf_q15 -}; - -#endif // ARM_DWARF_Registers_h_ diff --git a/tools/debugserver/source/ARM_ehframe_Registers.h b/tools/debugserver/source/ARM_ehframe_Registers.h deleted file mode 100644 index 9d644b7dc50b..000000000000 --- a/tools/debugserver/source/ARM_ehframe_Registers.h +++ /dev/null @@ -1,34 +0,0 @@ -//===-- ARM_ehframe_Registers.h -------------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef utility_ARM_ehframe_Registers_h_ -#define utility_ARM_ehframe_Registers_h_ - -enum { - ehframe_r0 = 0, - ehframe_r1, - ehframe_r2, - ehframe_r3, - ehframe_r4, - ehframe_r5, - ehframe_r6, - ehframe_r7, - ehframe_r8, - ehframe_r9, - ehframe_r10, - ehframe_r11, - ehframe_r12, - ehframe_sp, - ehframe_lr, - ehframe_pc, - ehframe_cpsr -}; - -#endif // utility_ARM_ehframe_Registers_h_ diff --git a/tools/debugserver/source/CMakeLists.txt b/tools/debugserver/source/CMakeLists.txt deleted file mode 100644 index 860a0289d22c..000000000000 --- a/tools/debugserver/source/CMakeLists.txt +++ /dev/null @@ -1,310 +0,0 @@ -include(CheckCXXCompilerFlag) -include(CheckLibraryExists) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) -include_directories(${LLDB_SOURCE_DIR}/source) -include_directories(MacOSX/DarwinLog) - -include_directories(MacOSX) - -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/../resources/lldb-debugserver-Info.plist") - -check_cxx_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" - CXX_SUPPORTS_NO_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS) -if (CXX_SUPPORTS_NO_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments") -endif () - -check_cxx_compiler_flag("-Wno-zero-length-array" - CXX_SUPPORTS_NO_ZERO_LENGTH_ARRAY) -if (CXX_SUPPORTS_NO_ZERO_LENGTH_ARRAY) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-zero-length-array") -endif () - -check_cxx_compiler_flag("-Wno-extended-offsetof" - CXX_SUPPORTS_NO_EXTENDED_OFFSETOF) -if (CXX_SUPPORTS_NO_EXTENDED_OFFSETOF) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-extended-offsetof") -endif () - -check_library_exists(compression compression_encode_buffer "" HAVE_LIBCOMPRESSION) - -add_subdirectory(MacOSX) - -set(generated_mach_interfaces - ${CMAKE_CURRENT_BINARY_DIR}/mach_exc.h - ${CMAKE_CURRENT_BINARY_DIR}/mach_excServer.c - ${CMAKE_CURRENT_BINARY_DIR}/mach_excUser.c - ) -add_custom_command(OUTPUT ${generated_mach_interfaces} - COMMAND mig ${CMAKE_CURRENT_SOURCE_DIR}/MacOSX/dbgnub-mig.defs - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MacOSX/dbgnub-mig.defs - ) - -set(DEBUGSERVER_VERS_GENERATED_FILE ${CMAKE_CURRENT_BINARY_DIR}/debugserver_vers.c) -set_source_files_properties(${DEBUGSERVER_VERS_GENERATED_FILE} PROPERTIES GENERATED 1) - -add_custom_command(OUTPUT ${DEBUGSERVER_VERS_GENERATED_FILE} - COMMAND ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl - ${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj debugserver - > ${DEBUGSERVER_VERS_GENERATED_FILE} - DEPENDS ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl - ${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj - ) - -set(lldbDebugserverCommonSources - DNBArch.cpp - DNBBreakpoint.cpp - DNB.cpp - DNBDataRef.cpp - DNBError.cpp - DNBLog.cpp - DNBRegisterInfo.cpp - DNBThreadResumeActions.cpp - JSON.cpp - StdStringExtractor.cpp - # JSON reader depends on the following LLDB-common files - ${LLDB_SOURCE_DIR}/source/Host/common/StringConvert.cpp - ${LLDB_SOURCE_DIR}/source/Host/common/SocketAddress.cpp - # end JSON reader dependencies - libdebugserver.cpp - PseudoTerminal.cpp - PThreadEvent.cpp - PThreadMutex.cpp - RNBContext.cpp - RNBRemote.cpp - RNBServices.cpp - RNBSocket.cpp - SysSignal.cpp - TTYState.cpp - - MacOSX/CFBundle.cpp - MacOSX/CFString.cpp - MacOSX/Genealogy.cpp - MacOSX/MachException.cpp - MacOSX/MachProcess.mm - MacOSX/MachTask.mm - MacOSX/MachThread.cpp - MacOSX/MachThreadList.cpp - MacOSX/MachVMMemory.cpp - MacOSX/MachVMRegion.cpp - MacOSX/OsLogger.cpp - ${generated_mach_interfaces} - ${DEBUGSERVER_VERS_GENERATED_FILE}) - -add_library(lldbDebugserverCommon ${lldbDebugserverCommonSources}) - -# LLDB-specific identity, currently used for code signing debugserver. -set(LLDB_CODESIGN_IDENTITY "" CACHE STRING - "Override code sign identity for debugserver and for use in tests; falls back to LLVM_CODESIGNING_IDENTITY if set or lldb_codesign otherwise (Darwin only)") - -# Determine which identity to use and store it in the separate cache entry. -# We will query it later for LLDB_TEST_COMMON_ARGS. -if(LLDB_CODESIGN_IDENTITY) - set(LLDB_CODESIGN_IDENTITY_USED ${LLDB_CODESIGN_IDENTITY} CACHE INTERNAL "" FORCE) -elseif(LLVM_CODESIGNING_IDENTITY) - set(LLDB_CODESIGN_IDENTITY_USED ${LLVM_CODESIGNING_IDENTITY} CACHE INTERNAL "" FORCE) -else() - set(LLDB_CODESIGN_IDENTITY_USED lldb_codesign CACHE INTERNAL "" FORCE) -endif() - -# Override locally, so the identity is used for targets created in this scope. -set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY_USED}) - -option(LLDB_NO_DEBUGSERVER "Disable the debugserver target" OFF) -option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver instead of building it from source (Darwin only)." OFF) - -# Incompatible options -if(LLDB_NO_DEBUGSERVER AND LLDB_USE_SYSTEM_DEBUGSERVER) - message(FATAL_ERROR "Inconsistent options: LLDB_NO_DEBUGSERVER and LLDB_USE_SYSTEM_DEBUGSERVER") -endif() - -# Try to locate the system debugserver. -# Subsequent feasibility checks depend on it. -if(APPLE AND CMAKE_HOST_APPLE) - execute_process( - COMMAND xcode-select -p - OUTPUT_VARIABLE xcode_dev_dir) - string(STRIP ${xcode_dev_dir} xcode_dev_dir) - - set(debugserver_rel_path "LLDB.framework/Resources/debugserver") - set(debugserver_shared "${xcode_dev_dir}/../SharedFrameworks/${debugserver_rel_path}") - set(debugserver_private "${xcode_dev_dir}/Library/PrivateFrameworks/${debugserver_rel_path}") - - if(EXISTS ${debugserver_shared}) - set(system_debugserver ${debugserver_shared}) - elseif(EXISTS ${debugserver_private}) - set(system_debugserver ${debugserver_private}) - endif() -endif() - -# Handle unavailability -if(LLDB_USE_SYSTEM_DEBUGSERVER) - if(system_debugserver) - set(use_system_debugserver ON) - elseif(APPLE AND CMAKE_HOST_APPLE) - # Binary not found on system. Keep cached variable, to try again on reconfigure. - message(SEND_ERROR - "LLDB_USE_SYSTEM_DEBUGSERVER option set, but no debugserver found in:\ - ${debugserver_shared}\ - ${debugserver_private}") - else() - # Non-Apple target platform or non-Darwin host. Reset invalid cached variable. - message(WARNING "Reverting invalid option LLDB_USE_SYSTEM_DEBUGSERVER (Darwin only)") - set(LLDB_USE_SYSTEM_DEBUGSERVER OFF CACHE BOOL "" FORCE) - endif() -elseif(NOT LLDB_NO_DEBUGSERVER) - # Default case: on Darwin we need the right code signing ID. - # See lldb/docs/code-signing.txt for details. - if(CMAKE_HOST_APPLE AND NOT LLVM_CODESIGNING_IDENTITY STREQUAL "lldb_codesign") - set(problem "Cannot code sign debugserver with LLVM_CODESIGNING_IDENTITY '${LLVM_CODESIGNING_IDENTITY}'.") - set(advice "Pass -DLLDB_CODESIGN_IDENTITY=lldb_codesign to override the LLVM value for debugserver.") - if(system_debugserver) - set(effect "Will fall back to system's debugserver.") - set(use_system_debugserver ON) - else() - set(effect "debugserver will not be available.") - endif() - message(WARNING "${problem} ${effect} ${advice}") - else() - set(build_and_sign_debugserver ON) - endif() -endif() - -# TODO: We don't use the $<TARGET_FILE:debugserver> generator expression here, -# because the value of DEBUGSERVER_PATH is used to build LLDB_DOTEST_ARGS, -# which is used for configuring lldb-dotest.in, which does not have a generator -# step at the moment. -set(default_debugserver_path "${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX}") - -# Remember where debugserver binary goes and whether or not we have to test it. -set(DEBUGSERVER_PATH "" CACHE FILEPATH "Path to debugserver") -set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "Building the in-tree debugserver was skipped") - -# Reset values in all cases in order to correctly support reconfigurations. -if(use_system_debugserver) - add_custom_target(debugserver - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${system_debugserver} ${LLVM_RUNTIME_OUTPUT_INTDIR} - COMMENT "Copying the system debugserver to LLDB's binaries directory.") - - # Don't test debugserver itself. - # Tests that require debugserver will use the copy. - set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE) - - message(STATUS "Copy system debugserver from: ${system_debugserver}") -elseif(build_and_sign_debugserver) - # Build, sign and test debugserver (below) - set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "" FORCE) - - message(STATUS "lldb debugserver: ${DEBUGSERVER_PATH}") -else() - # No tests for debugserver, no tests that require it. - set(DEBUGSERVER_PATH "" CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE) - - message(STATUS "lldb debugserver will not be available.") -endif() - -if(APPLE) - if(IOS) - find_library(BACKBOARD_LIBRARY BackBoardServices - PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks) - find_library(FRONTBOARD_LIBRARY FrontBoardServices - PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks) - find_library(SPRINGBOARD_LIBRARY SpringBoardServices - PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks) - find_library(MOBILESERVICES_LIBRARY MobileCoreServices - PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks) - find_library(LOCKDOWN_LIBRARY lockdown) - - if(NOT BACKBOARD_LIBRARY) - set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE) - endif() - else() - find_library(COCOA_LIBRARY Cocoa) - endif() -endif() - -if(HAVE_LIBCOMPRESSION) - set(LIBCOMPRESSION compression) -endif() - -if(LLDB_USE_ENTITLEMENTS) - if(IOS) - set(entitlements ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-entitlements.plist) - else() - # Same entitlements file as used for lldb-server - set(entitlements ${LLDB_SOURCE_DIR}/resources/debugserver-macosx-entitlements.plist) - endif() -endif() - -if(build_and_sign_debugserver) - target_link_libraries(lldbDebugserverCommon - INTERFACE ${COCOA_LIBRARY} - ${CORE_FOUNDATION_LIBRARY} - ${FOUNDATION_LIBRARY} - ${BACKBOARD_LIBRARY} - ${FRONTBOARD_LIBRARY} - ${SPRINGBOARD_LIBRARY} - ${MOBILESERVICES_LIBRARY} - ${LOCKDOWN_LIBRARY} - lldbDebugserverArchSupport - lldbDebugserverDarwin_DarwinLog - ${LIBCOMPRESSION}) - if(HAVE_LIBCOMPRESSION) - set_property(TARGET lldbDebugserverCommon APPEND PROPERTY - COMPILE_DEFINITIONS HAVE_LIBCOMPRESSION) - endif() - set(LLVM_OPTIONAL_SOURCES ${lldbDebugserverCommonSources}) - add_lldb_tool(debugserver - debugserver.cpp - - LINK_LIBS - lldbDebugserverCommon - - ENTITLEMENTS - ${entitlements} - ) - if(IOS) - set_property(TARGET lldbDebugserverCommon APPEND PROPERTY COMPILE_DEFINITIONS - WITH_LOCKDOWN - WITH_FBS - WITH_BKS - ) - set_property(TARGET debugserver APPEND PROPERTY COMPILE_DEFINITIONS - WITH_LOCKDOWN - WITH_FBS - WITH_BKS - ) - set_property(TARGET lldbDebugserverCommon APPEND PROPERTY COMPILE_FLAGS - -F${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks - ) - endif() -endif() - -if(IOS) - add_library(lldbDebugserverCommon_NonUI ${lldbDebugserverCommonSources}) - target_link_libraries(lldbDebugserverCommon_NonUI - INTERFACE ${COCOA_LIBRARY} - ${CORE_FOUNDATION_LIBRARY} - ${FOUNDATION_LIBRARY} - lldbDebugserverArchSupport - lldbDebugserverDarwin_DarwinLog - ${LIBCOMPRESSION}) - if(HAVE_LIBCOMPRESSION) - set_property(TARGET lldbDebugserverCommon_NonUI APPEND PROPERTY - COMPILE_DEFINITIONS HAVE_LIBCOMPRESSION) - endif() - - add_lldb_tool(debugserver-nonui - debugserver.cpp - - LINK_LIBS - lldbDebugserverCommon_NonUI - - ENTITLEMENTS - ${entitlements} - ) -endif() diff --git a/tools/debugserver/source/ChangeLog b/tools/debugserver/source/ChangeLog deleted file mode 100644 index 898f2fba7b04..000000000000 --- a/tools/debugserver/source/ChangeLog +++ /dev/null @@ -1,1515 +0,0 @@ -2010-01-29 Greg Clayton <gclayton@apple.com> - - * MachProcess.cpp (MachProcess::PrepareForAttach): No longer use the - SBSLaunchApplication macro from the SpringBoard.framework, use the actual - function name SBSLaunchApplicationForDebugging. - (MachProcess::CleanupAfterAttach): Ditto. - (MachProcess::SBForkChildForPTraceDebugging): Ditto. - (debugserver-entitlements.plist): Added the "seatbelt-profiles" entitlement - so debugserver can be sandboxed. - -2009-07-06 Greg Clayton <gclayton@apple.com> - - * MachTask.cpp (MachTask::GetDYLDAllImageInfosAddress): Hack around bad - kernel code that renamed the first member of the TASK_DYLD_INFO without - any way to detect it has changed. - -2009-06-29 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (GetAllInfosMatchingName): Correctly truncate process name string - to MAXCOMLEN when searching kinfo_proc structs for process matches by name. - * MachProcess.cpp (MachProcess::PrepareForAttach): Added logging when - attaching to a program by name. - -2009-06-25 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (DNBProcessLaunch): Added a stat on the incoming path that we are - about to launch to make sure the file exists. If the file doesn't, then an - appropriate error string is returned. Also if we fail to get the task for - our process ID, we return an error string right away instead of letting the - debug session go for a little bit and then later failing after a few more - packets. - -2009-04-07 Jim Ingham <jingham@apple.com> - - * RNBRemote.h: Add vAttachWait - * RNBRemote.cpp (RNBRemote::CreatePacketTable): Add vattachwait. - (RNBRemoteShouldCancelCallback): New function. - (RNBRemote::HandlePacket_v): Handle vattachwait. - * RNBSocket.cpp (RNBSocket::Read): Mark the connection as closed when the - port goes away. - * DNB.cpp (DNBProcessAttachByName): New function. - (DNBProcessAttach): Make this handle catching the attach when done and - dealing with timeout & return conditions. - (GetAllInfos): New function. - (GetAlInfosMatchingName): New function. - (DNBProcessAttachWait): New function. - DNB.h: Declare DNBProcessAttachByName, DNBProcessAttachWait, change - signature of DNBProcessAttach. - * MachProcess.cpp (MachProcess::PrepareForAttach): New function. - (MachProcess::CheckForProcess): New function. - (MachProcess::CleanupAfterAttach): New function. - (CopyBundleIDForPath): New function. - (MachProcess::SBForkChildForPTraceDebugging): Convert to using - CopyBundleIDForPath. - * MachProcess.h: Declare PrepareForAttach, CleanupAfterAttach and - CheckForProcess. - * DNBTimer.h (TimeOfDayLaterThan): New function. - * test-remotenub.cpp (RNBRunLoopGetStartModeFromRemote): Rename from - RNBRunLoopGetArgsFromRemote, and handle vattachwait. - (RNBRunLoopLaunchAttaching): Code was moved from here into DNBProcessAttach. - (StartListening): New function. - (GetAllProcessInfos, GetAllProcessInfosMatchingName): Moved to - DNBProcess.cpp. - (main): Handle attach waitfor, and make debugserver with only a host and - port wait on commands from gdb. - -2009-04-03 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (PacketEnum): Added enum for qShlibInfoAddr. - * RNBRemote.cpp (RNBRemote::CreatePacketTable) Added the qShlibInfoAddr - packet definition to m_packets. - (RNBRemote::GetPacket): Log when we run into an unimplemented packet. - (RNBRemote::HandleReceivedPacket): Only log the packet when logging - LOG_RNB_REMOTE. - (RNBRemote::HandlePacket_q): Add support for the new qShlibInfoAddr packet. - * DNB.h (DNBProcessGetSharedLibraryInfoAddress): New prototype. - * DNB.cpp (DNBProcessGetSharedLibraryInfoAddress): New function. - * MachTask.h (MachProcess::GetDYLDAllImageInfosAddress): New prototype. - * MachTask.cpp (MachProcess::GetDYLDAllImageInfosAddress): New function. - -2009-04-01 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (main): Display the detailed error message if any when - attaching fails. - -2009-03-25 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (RNBRunLoopGetArgsFromRemote): Cleaned up logging and - removed time deltas form the messages. - (RNBRunLoopLaunchAttaching): Ditto. - (RNBRunLoopLaunchInferior): Ditto and also use new DNBProcessLaunch that - takes an error string pointer. - * RNBContext.h (class RNBContext): Removed the m_timer member. - * RNBContext.cpp (RNBContext::StartProcessStatusThread): Cleaned up logging - and removed time deltas form the messages. - (RNBContext::ThreadFunctionProcessStatus): Ditto. - * RNBSocket.h (class RNBSocket): Removed unused m_last_errno member and - accessor functions. - * RNBSocket.cpp (RNBSocket::Listen): Cleaned up logging and - removed time deltas form the messages. - (RNBSocket::ConnectToService): Ditto. - (RNBSocket::Read): Ditto. - (RNBSocket::Write): Ditto. - (RNBSocket::SaveErrno): Removed. - (RNBSocket::ClosePort): Don't call RNBSocket::SaveErrno(). - * RNBRemote.cpp (RNBRemote::RNBRemote): Cleaned up logging and - removed time deltas form the messages. - (RNBRemote::~RNBRemote): Ditto. - (RNBRemote::SendPacket): Ditto. - (RNBRemote::GetPacketPayload): Ditto. - (RNBRemote::GetPacket): Ditto): Ditto. - (RNBRemote::HandleAsyncPacket): Ditto. - (RNBRemote::HandleReceivedPacket): Ditto. - (RNBRemote::CommDataReceived): Ditto. - * DNB.cpp (DNBProcessLaunch): Changed to take a eror string pointer with - size for more desciptive error reporting (instead of a uint32_t pointer). - * DNB.h (DNBProcessLaunch): Ditto. - * DNBError.cpp (DNBError::AsString): Now returns NULL if there is no error. - * DNBError.h (DNBError::SetErrorString): New accessor to allow custom error - strings. - * arm/DNBArchImpl.cpp (DNBArchMachARM::GetGPRState): Improved logging. - * MachProcess.cpp (MachProcess::SBForkChildForPTraceDebugging): Improved - error messages when a file doesn't exist, or when unable to extract the - CFBundleIdentifier. - * PThreadEvent.cpp (class PThreadEvent): Commented out all logging calls. - -2009-03-07 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (GetAllProcessInfosMatchingName): New function that - returns matching kinfo_proc structs given a process name. - (main): Enhanced the --attach option to be able to take a PROCNAME or - a PID. Changed the --waitfor=PROCNAME option to ignore any existing - processes with PROCNAME so we only catch new process invocations. - -2009-03-07 Greg Clayton <gclayton@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_p): Use the correct get current - thread function call so we get the correct thread registers. - -2009-03-03 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (g_isatty): New global that gets set to non-zero if - STDOUT is a TTY in the beginning of main. - (RNBLogSTDOUT): New macro that logs to STDOUT if g_isatty is non-zero, else - it logs to asl. - (RNBLogSTDERR): New macro that logs to STDERR if g_isatty is non-zero, else - it logs to asl. - (RNBRunLoopGetArgsFromRemote): Use new RNBLogSTDOUT/RNBLogSTDERR macros. - (GetAllProcessInfos): Get all process info structs for everything on the - system. - (main): Implemented new --waitfor=NAME option to allow waiting for a process - to run by polling the system processes. The new --waitfor-interval=N option - allows fine control over the polling interval where N is the number of mirco - seconds (usec) to wait between polls (defaults to 1000). The new - --waitfor-duration=N allows a timeout in seconds to be specified when - waiting for a process (defaults to infinite). - -2009-03-02 Greg Clayton <gclayton@apple.com> - - * DNBArchImpl.cpp (DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup): - Take care of a case where no instructions execute in a Thumb IT block and - the last of which is a branch. - -2009-02-10 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (PacketEnum): Added 'detach' enumeration. - (RNBRemote::HandlePacket_D): New member function prototype. - * RNBRemote.cpp (RNBRemote::CreatePacketTable): Added detach support. - (RNBRemote::HandlePacket_D): New function for detach support. - -2009-02-10 Greg Clayton <gclayton@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_UNIMPLEMENTED): Log this - packet with the packet that is unimplemented. - (RNBRemote::GetPacket): Call RNBRemote::HandlePacket_UNIMPLEMENTED() - when we don't recognize a packet. - (RNBRemote::HandleReceivedPacket): Don't reply to packets we don't - recognize with unimplemented in this function as that should have - already been done for us in RNBRemote::GetPacket(). - -2009-02-10 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (PacketEnum): Added query_step_packet_supported. - * RNBRemot.cpp (RNBRemote::CreatePacketTable): Added new - qStepPacketSupported packet. - (RNBRemote::HandlePacket_q): Added support for the new - "qStepPacketSupported" packet. - (RNBRemote::HandlePacket_G): Some cleanup when reading registers - to avoid spurious console logging. - -2009-01-30 Greg Clayton <gclayton@apple.com> - - * debugserver-entitlements.plist: Changed the entitlement - "run-invalid-allow" to "run-unsigned-code". - -2009-01-23 Greg Clayton <gclayton@apple.com> - - * DNBArchImpl.cpp (DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup): - Merged Yusuf's changes to make software single stepping work. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Call new - DNBResolveExecutablePath function to resolve executable paths. - * DNB.h (DNBResolveExecutablePath): New function prototype. - * DNB.cpp (DNBResolveExecutablePath): New function that will resolve - relative paths and also executable paths for executables that aren't relative - but yet are in the shell PATH environment variable. - -2009-01-22 Greg Clayton <gclayton@apple.com> - - * DNBArchImpl.h (class DBNArchMachARM): Renamed member variable - m_chained_hw_single_step_addr to m_hw_single_chained_step_addr. Added - new member variables: m_sw_single_step_itblock_break_id, m_last_decode_pc, - and m_sw_single_step_itblock_break_count. Renamed m_thumbStaticData to - m_last_decode_thumb, and renamed m_decodedInstruction to m_last_decode_arm. - (DBNArchMachARM::DecodeITBlockInstructions): New prototype. - (DBNArchMachARM::DecodeInstructionUsingDisassembler): New prototype. - (DBNArchMachARM::BreakpointHit): New prototype. - * DNBArchImpl.cpp (DNBArchMachARM::ThreadDidStop): Disable any of the - many software single step breakpoints if any are set. - (DNBArchMachARM::StepNotComplete): Changed renamed member accesses. - (DNBArchMachARM::DecodeITBlockInstructions): New function for software - single stepping through Thumb IT blocks. - (DNBArchMachARM::EnableHardwareSingleStep): Cleaned up logging. - (DNBArchMachARM::ComputeNextPC): Ditto. - (DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup): Now - properly handles Thumb IT software single stepping. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints): Ditto. - (DNBArchMachARM::DecodeInstructionUsingDisassembler): New function. - (DNBArchMachARM::BreakpointHit): New breakpoint callback function. - -2009-01-21 Greg Clayton <gclayton@apple.com> - - * MachProcess.cpp (MachProcess::PrivateResume): Set the process state before - we actually resume so we are sure to get the events in the correct order. - -2009-01-16 Greg Clayton <gclayton@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_last_signal): Include only - registers which are to be expedited in the T packets. - (RNBRemote::HandlePacket_p): Enable for all targets. - (struct register_map_entry): Added an expedite member so we know which - registers need to be sent up to the host with each stop reply packet. - (register_map): Updated each array members' expedite member with an - appropriate value. - -2009-01-16 Greg Clayton <gclayton@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_s): Enabled the step command ("s" - packet) for ARM now that libdebugnub.dylib can do both hardware and software - single stepping. - -2009-01-13 Greg Clayton <gclayton@apple.com> - - *DNBArchImpl.cpp (bit): New function. - (bits): New function. - (DNBArchMachARM::ConditionPassed): Use new "bit" function. - (DNBArchMachARM::ComputeNextPC): Use new "bit" function, remove inline - assembly for "RSC" instruction so this compiles for armv7 (which defaults - to thumb) - (DNBArchMachARM::NumSupportedHardwareBreakpoints): Use new "bits" function. - (DNBArchMachARM::NumSupportedHardwareWatchpoints): Use new "bits" function. - -2009-01-12 Greg Clayton <gclayton@apple.com> - - * DNBArch.h (DNBArchProtocol::NumSupportedHardwareBreakpoints()): Removed - the "const" qualifier to allow arches to auto detect how many hardware - breakpoints they have. - (DNBArchProtocol::NumSupportedHardwareWatchpoints()): Removed the "const" - qualifier to allow arches to auto detect how many hardware watchpoints they - have. - * DNBArchImpl.h (DNBArchMachARM::NumSupportedHardwareBreakpoints()): Auto - detect how many BRP pairs are avialable and disable for armv7 for the time - being (rdar://problem/6372672). - (DNBArchMachARM::NumSupportedHardwareWatchpoints()): Auto detect how many - WRP pairs are avialable and disable for armv7 for the time being - (rdar://problem/6372672). - -2009-01-09 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (main): Filled in short argument versions for - --applist (-t) and --lockdown (-k) options. - * DNBArchImpl.h (DNBArchMachARM::ConditionPassed): New protected - member function. - (DNBArchMachARM::ComputeNextPC): New protected member function. - (DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup): New - protected member function. - (DNBArchMachARM::m_thumbStaticData): New protected member variable. - (DNBArchMachARM::m_decodedInstruction): New protected member variable. - * DNBArchImpl.cpp (DNBArchMachARM::ThreadDidStop): Added extra code that - will log and exit when we are verifying software single stepping (a - compile time option). - (DNBArchMachARM::ConditionPassed): New function. - (DNBArchMachARM::ComputeNextPC): New function. - (DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup): New - function. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints): Added the guts of the - software single stepping. - (DNBArchMachARM::NumSupportedHardwareBreakpoints): Prepared for adding - auto detection code. - (DNBArchMachARM::NumSupportedHardwareWatchpoints): Prepared for adding - auto detection code. - -2008-12-11 Greg Clayton <gclayton@apple.com> - - * DNB.h (DNBProcessWaitForEvent): Renamed to DNBProcessWaitForEvents. - (DNBProcessSetEvents): Removed (deprecated). - (DNBProcessGetWaitForResetMask): Removed (unused). - (DNBProcessSetWaitForResetMask): Removed (unused). - (DNBProcessInterruptEvents): New function prototype. - * DNB.cpp (DNBProcessWaitForEvent): Renamed to DNBProcessWaitForEvents. - (DNBProcessSetEvents): Removed (deprecated). - (DNBProcessGetWaitForResetMask): Removed (unused). - (DNBProcessSetWaitForResetMask): Removed (unused). - (DNBProcessInterruptEvents): New function that can be used to - asynchronously interrupt infinite wait for events calls. - RNBRemote.cpp (RNBRemote::HandlePacket_v): Call DNBProcessWaitForEvents. - RNBContext.cpp (RNBContext::ThreadFunctionProcessStatus): Ditto. - test-remotenub.cpp (RNBRunLoopLaunchInferior): Ditto. - (RNBRunLoopLaunchAttaching): Ditto. - -2008-12-11 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (GetProcessMap): Use new PTHREAD_MUTEX_LOCKER macro to ease - debugging of deadlocks. - (DNBProcessLaunch): Improved logging. - (DNBProcessMemoryRead): Call MachProcess::ReadMemory so breakpoint - opcodes can be removed from memory. - (DNBProcessMemoryWrite): Call MachProcess::WriteMemory so that we work - around enabled software breakpoint traps. - * DNBLog.cpp (GetLogThreadedMutex): New function. - (_DNBLogThreaded): Use new PTHREAD_MUTEX_LOCKER macro to ease - debugging of deadlocks. - (_DNBLogThreadedIf): Ditto. - * DNBBreakpoint.h (DNBBreakpoint::IntersectsRange): New function. - * DNBBreakpoint.cpp (DNBBreakpointList::FindIDByAddress): Improved - logging. - * MacOSX/MachThread.cpp (MachThread::MachThread): Improved logging. - (MachThread::~MachThread): Ditto. - (MachThread::Suspend): Ditto. - (MachThread::Resume): Ditto. - (MachThread::RestoreSuspendCount): Ditto. - (MachThread::GetState): Use new PTHREAD_MUTEX_LOCKER macro to ease - debugging of deadlocks. - (MachThread::SetState): Ditto. - * MacOSX/MachVMMemory.cpp (MachVMMemory::Read): Improved logging. - (MachVMMemory::Write): Ditto. - (MachVMMemory::WriteRegion): Ditto. - * MacOSX/MachProcess.cpp (MachProcess::GetState): Use new - PTHREAD_MUTEX_LOCKER macro to ease debugging of deadlocks. - (MachProcess::SetState): Ditto. - (MachProcess::Clear): Ditto. - (MachProcess::PrivateResume): Ditto. - (MachProcess::ReplyToAllExceptions): Ditto. - (MachProcess::ExceptionMessageReceived): Ditto. - (MachProcess::AppendSTDOUT): Ditto. - (MachProcess::GetAvailableSTDOUT): Ditto. - (MachProcess::ThreadFunctionSTDIO): Renamed from to - MachProcess::STDIOThread. - (MachProcess::StartSTDIOThread): Improved logging. - (MachProcess::CreateBreakpoint): Ditto. - (MachProcess::CreateWatchpoint): Ditto. - (MachProcess::DisableAllBreakpoints): Ditto. - (MachProcess::DisableBreakpoint): Ditto. - (MachProcess::DisableWatchpoint): Ditto. - (MachProcess::EnableBreakpoint): Ditto. - (MachProcess::EnableWatchpoint): Ditto. - (MachProcess::LaunchForDebug): Ditto. - (MachProcess::PosixSpawnChildForPTraceDebugging): Ditto. - (MachProcess::Detach): Reset the running event bit after resuming prior - to issuing the SIGSTOP to avoid a pause. - (MachProcess::RemoveTrapsFromBuffer): New function that removes - breakpoint traps from a memory buffer. - (MachProcess::ReadMemory): Read memory from the task, then removes any - breakpoint traps prior to returning the buffer. - (MachProcess::WriteMemory): Write memory and any needed data to the - breakpoint saved opcodes for any software breakpoint traps that are - enabled. - * MacOSX/MachProcess.h (MachProcess::ThreadFunctionException): Removed. - (MachProcess::ThreadFunctionSTDIO): Renamed to MachProcess::STDIOThread(). - (MachProcess::RemoveTrapsFromBuffer): New function. - * MacOSX/MachVMRegion.cpp (MachVMRegion::SetProtections): Improved - logging. - (MachVMRegion::RestoreProtections): Ditto. - (MachVMRegion::GetRegionForAddress): Ditto. - * MacOSX/MachException.cpp (catch_mach_exception_raise_state): Improved - logging. - (catch_mach_exception_raise_state_identity): Ditto. - (catch_mach_exception_raise): Ditto. - (MachException::Message::Dump): Ditto. - (MachException::Data::GetStopInfo): Ditto. - (MachException::Message::Receive): Ditto. - (MachException::Message::Reply): Ditto. - (MachException::Data::Dump): Ditto. - (MachException::PortInfo::Save): Ditto. - (MachException::PortInfo::Restore): Ditto. - * MacOSX/MachTask.cpp (MachTask::Suspend): Improved logging. - (MachTask::Resume): Ditto. - (MachTask::ReadMemory): Ditto. - (MachTask::WriteMemory): Ditto. - (MachTask::TaskPortForProcessID): Ditto. - (MachTask::BasicInfo): Ditto. - (MachTask::StartExceptionThread): Ditto. - (MachTask::ShutDownExcecptionThread): Ditto and use pthread_cancel to - interrupt the exception thread. - (MachTask::ExceptionThread): Ditto and revert back to infinite timeout - as pthread_cancel will break us out of infinite mach_msg receive calls. - * MacOSX/MachThreadList.cpp (MachThreadList::UpdateThreadList): Improved - logging. - (MachThreadList::CurrentThread): Use new PTHREAD_MUTEX_LOCKER macro to - ease debugging of deadlocks. - * DNBTimer.h (DNBTimer::DNBTimer): Initialize the mutex with a recursive - pthread. - (DNBTimer::Reset): Use new PTHREAD_MUTEX_LOCKER macro to ease debugging - of deadlocks. - (DNBTimer::TotalMicroSeconds): Ditto. - (DNBTimer::GetTime): Ditto. - (DNBTimer::ElapsedMicroSeconds): Ditto. - (DNBTimer::GetTimeOfDay): New class function. - * DNBError.cpp (DNBError::LogThreaded): Improved logging. - * test-dbgnub.cpp - * PThreadMutex.h: Added the ability to debug deadlocks by defining - DEBUG_PTHREAD_MUTEX_DEADLOCKS. - * FunctionProfiler.cpp - * PThreadEvent.cpp (PThreadEvent::NewEventBit): Use new - PTHREAD_MUTEX_LOCKER macro to ease debugging of deadlocks. - (PThreadEvent::FreeEventBits): Ditto. - (PThreadEvent::GetEventBits): Ditto. - (PThreadEvent::ReplaceEventBits): Ditto. - (PThreadEvent::SetEvents): Ditto. - (PThreadEvent::ResetEvents): Ditto. - (PThreadEvent::WaitForSetEvents): Ditto. - (PThreadEvent::WaitForEventsToReset): Ditto. - -2008-12-05 Greg Clayton <gclayton@apple.com> - - * DNBDefs.h (LOG_TASK): New log bit. - * DNB.cpp (DNBProcessIsAlive): User newly abstracted MachTask class. - (DNBProcessMemoryRead): Ditto. - (DNBProcessMemoryWrite): Ditto. - * DNBArchImpl.cpp (DNBArchMachARM::EnableHardwareSingleStep): Ditto. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints) Ditto. - * MachException.cpp (MachException::Message::Receive): Cleaned up logging - so it doesn't always log timeout errors. - (MachException::Message::Reply): Use abstracted MachTask class for any - task related queries. - (MachException::PortInfo::Save): Cleaned up logging. - (MachException::PortInfo::Restore): Cleaned up logging and now return an - error instead of the number of restored port infos. - * MachProcess.cpp (class MachProcess): Abstracted out all of the task_t - related stuff (suspend, resume, exception ports, exception thread, and - more) into a new class MachTask. - (MachProcess::Task): Now returns a reference to a MachTask class. - (MachProcess::Clear): Uses new abstracted MachTask class. - (MachProcess::Detach): Ditto. - (MachProcess::PrivateResume): Ditto. - (MachProcess::DisableBreakpoint): Ditto. - (MachProcess::ExceptionMessageReceived): Ditto. - (MachProcess::ExceptionMessageBundleComplete): Ditto. - (MachProcess::AttachForDebug): Ditto. - (MachProcess::LaunchForDebug): Ditto. - (MachProcess::SBLaunchForDebug): Ditto. - (MachProcess::TaskIsValid): Removed (replaced by similar functionality - in the new MachTask class). - (MachProcess::ExceptionPort): Ditto. - (MachProcess::ExceptionPortIsValid): Ditto. - (MachProcess::StartExceptionThread): Ditto. - (MachProcess::Suspend): Ditto. - (MachProcess::TaskResume): Ditto. - (MachProcess::TaskBasicInfo): Ditto. - (MachProcess::TaskBasicInfo): Ditto. - (MachProcess::ReadMemory): Ditto. - (MachProcess::WriteMemory): Ditto. - (MachProcess::ThreadFunctionException): Ditto. - -2008-12-04 Greg Clayton <gclayton@apple.com> - - * DNB.h (DNBProcessSetEvents): New API function prototype. - * DNB.cpp (DNBProcessSetEvents): New API function. - (DNBProcessHalt): Send our process a SIGINT instead of suspending - the task. - * DNBDefs.h (NUB_STATE_IS_STOPPED): Removed up duplicate entry in macro. - (eEventPrcoessAsyncInterrupt): New prcoess event bit that allows async - interrupting of infinite DNBProcessWaitForEvent() function calls. - * MachException.cpp (MachException::Message::Receive): Improved logging. - (MachException::Message::Reply): Improved logging. - * MachProcess.h (MachProcess::TaskBasicInfo): New member and static - functions. - * MachProcess.cpp (MachProcess::TaskIsValid): Use new TaskBasicInfo() - member function. - (MachProcess::Resume): Removed the detach parameter from the PrivateResume() - function call. - (MachProcess::Kill): Added a absolute timeout pointer to allow callers to - wait for the signal to be received if the timeout is non-NULL. - (MachProcess::TaskBasicInfo): New member and static function. - (MachProcess::TaskResume): New function that resumes the task by making sure - the suspend count is correctly ref counted. - (MachProcess::Detach): When detaching from a process make sure it is - stopped (SIGSTOP) first, then we can successfully detach. The exception - thread now also properly exits. - (MachProcess::PrivateResume): Call new TaskResume function, and removed the - detach functionality. - (MachProcess::DisableBreakpoint): Only notify the thread list that a - breakpoint has changed if the breakpoint is going to be removed. - (MachProcess::ThreadFunctionException): Added a permanent 1 second timeout - for each call to mach_msg() so we can exit the thread in the event that - we detach from a process/task. - * test-debugnub (main): Modified to show an example of how to detach using - a signal_handler to asynchronously receive a SIGINT and properly interrupt - and detach from a running process. - -2008-11-26 Greg Clayton <gclayton@apple.com> - - * DNBDefs.h (LOG_STEP): New logging define. - * DNBError.cpp (DNBError::LogThreaded): If there is no error, then - log with "success: " as a prefix instead of "error: ". - * arm/DBNArchImpl.cpp (DNBArchMachARM::EnableHardwareSingleStep): Log using - new LOG_STEP instead of LOG_BREAKPOINTS. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints): Ditto. - * MachException.cpp (MachException::Message::Dump): Log exception header - and reply header on two separate lines. - * MachProcess.cpp (IsSBProcess): Check for NULL CFArrayRef returned from - SBSCopyApplicationDisplayIdentifiers for SkankPhone. - (MachProcess::Suspend): Check if process state is not running instead of - having to receive an event after a timeout if one is given. - (MachProcess::Detach): Deallocate the exception port when detaching and - restore the inferior task exception ports prior to clearing and detaching. - (MachProcess::PrivateResume): Grab the task's basic info and make sure we - get the resume the correct number of times. - (MachProcess::DisableBreakpoint): Removed unused variable opcode_restored - and make sure the breakpoint is enabled before we start warning that - our opcode wasn't there. - * ppc/DBNArchImpl.cpp (DNBArchMachPPC::EnableHardwareSingleStep): Log - using LOG_STEP instead of LOAD_BREAKPOINTS. - * RNBServices.cpp (IsSBProcess): Check for NULL CFArrayRef returned from - SBSCopyApplicationDisplayIdentifiers for SkankPhone. - -2008-11-26 Greg Clayton <gclayton@apple.com> - - * MachProcess.h (MachProcess::Suspend): Now takes an optional absolute - timeout that, if non-NULL, will case the function to return after the - process has been suspended and is in a stopped state. If the timeout is - NULL, then no waiting will occur. - * MachProcess.cpp (MachProcess::Suspend): Ditto. - (MachProcess::Detach): Now replies to all exceptions, un-suspends all - threads and resumes the task. - (MachProcess::ReplyToAllExceptions): New function. - (MachProcess::PrivateResume): Now takes an additional parameter named - detach that will do the right thing when detaching from a process. - * DNBArchImpl.h (DNBArchMachI386::ThreadWillResume): Returns void. - * DNBArchImpl.cpp (DNBArchMachI386::ThreadWillResume): Returns void. - * RNBServices.cpp (ListApplications): #ifdef-ed for ARM only as it - currently uses SpringBoard. - (IsSBProcess): Ditto. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): #ifdef-ed around - ARM parts so it compiles for i386. - (main): Ditto. - -2008-11-24 Greg Clayton <gclayton@apple.com> - - * DNBArchProtocol.h (DNBArchProtocol::ThreadWillResume): Now returns void. - * DNBArchImpl.cpp (DNBArchMachARM::ThreadWillResume): Returns void and - has hollowed out support for software single step. - (DNBArchMachARM::ThreadDidStop): Has a debug mode that uses hardware single - step to verify software single step that can be enabled by defining - DNB_ARCH_MACH_ARM_DEBUG_SW_STEP. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints): New function. - * DNBArchImpl.h (DNBArchMachARM::ThreadWillResume): Returns void. - (DNBArchMachARM::SetSingleStepSoftwareBreakpoints): New prototype. - (DNBArchMachARM::m_sw_single_step_next_pc): New member variable. - (DNBArchMachARM::m_sw_single_step_break_id): New member variable. - * MachThread.cpp (MachThread::ThreadWillResume): Now returns void. - * MachThread.h (MachThread::ThreadWillResume): Now returns void. - -2008-11-19 Greg Clayton <gclayton@apple.com> - - * DNBError.h (FlavorType): Added SpringBoard error type for arm builds. - * DNBError.cpp (DNBError::AsString): Now returns SpringBoard error strings - if the error type is SpringBoard. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Set the error into - RNBContext as either a POSIX error or a SpringBoard error. - * RNBContext.h (m_launch_status): Changed this member to be a DNBError - instead of a uint32_t. - (RNBContext::LaunchStatus): Now returns a reference to the DNBError object - in m_launch_status. - * RNBContext.cpp (RNBContext::LaunchStatusAsString): Let DNBError handle - any error string descriptions, including SpringBoard errors. - * RNBRemote.cpp (RNBRemote::HandlePacket_q): Use new error class in - RNBContext. - (RNBRemote::HandlePacket_C): Return without an erroneous error when resuming - a process with a signal. - * DNBArch.h (DNBArchProtocol::StepNotComplete): New protocol function with - default return value. - * DNBArchImpl.cpp (DNBArchMachARM::StepNotComplete): New function. - (DNBArchMachARM::EnableHardwareSingleStep): Handle hardware single stepping - over 32 bit thumb instructions better so we always do a true instruction - level single step. - * MachProcess.cpp (MachProcess::ExceptionMessageBundleComplete): Now resumes - if single stepping wasn't able to complete in a single run. - * MachThread.cpp (MachThread::ShouldStop): Fills in new step_more parameter - if stepping is not complete. - * MachThreadList.cpp (MachThreadList::ShouldStop): Pass step_more parameter - to each MachThread::ShouldStop call. - -2008-11-13 Greg Clayton <gclayton@apple.com> - - * MachProcess.cpp (MachProcess::PosixSpawnChildForPTraceDebugging): Don't - call posix_spawnattr_setbinpref_np when launching with posix_spawn on ARM - targets as it currently selects the incorrect slice due to multiple slices - that contain the same cputype, yet they all have differing cpusubtypes. - -2008-11-04 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (GetContinueThread): Don't return the current thread when - the continue thread is zero or -1. - * RNBRemote.cpp (RNBRemote::HandlePacket_c): Resume the process if we - have no continue thread set. - (RNBRemote::HandlePacket_s): Ditto. - (RNBRemote::HandlePacket_C): Ditto unless a continue address is specified - in which case we will only succeed if we have one thread when the continue - with signal and address doesn't have a continue thread specified. - (RNBRemote::HandlePacket_S): Ditto. - * DNB.cpp (DNBProcessResumeWithSignal): New function. - (DNBProcessResume): Added better logging. - (DNBProcessHalt): Ditto. - (DNBThreadResume): Ditto. - (DNBThreadResumeWithSignal): Ditto. - * DNB.h (DNBProcessResumeWithSignal): New prototype. - * DNBError.cpp (DNBError::LogThreaded): New function. - * DNBError.h (DNBError::LogThreaded): New prototype. - * DNBLog.cpp (_DNBLogThreaded): Added sequence ID for threaded logs. - (_DNBLogThreadedIf): Ditto. - * MachException.cpp (MachException::Data::GetStopInfo): Use new SoftSignal() - accessor. - (MachException::Data::DumpStopReason): Ditto. - (MachException::Message::Reply): Added better logging and log using the - soft signal if our task matches that in the exception. - (MachException::Data::Dump): Added better logging. - * MachException.h (IsSoftSignal): Removed. - (SoftSignal): New function that returns the soft signal in the exception - data if there is one, or zero otherwise. - * MachProcess.cpp (MachProcess::Suspend): Improved logging. - (MachProcess::Resume): Ditto. - (MachProcess::PrivateResume): Handle the case where the process is told - to resume with a signal by matching the signal up to the thread that had - the soft signal if no thread id is specified. - * MachThread.cpp (MachThread::Suspend): Improved logging. - (MachThread::Resume): Improved logging. - (MachThread::RestoreSuspendCount): Improved logging. - (MachThread::Resume): Improved logging. - (MachThread::Dump): Improved logging. - * MachThreadList.cpp (MachThreadList::Dump): Improved logging. - -2008-10-22 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (RNBRunLoopMode): Added a new enum value - eRNBRunLoopModeInferiorAttaching. - (g_long_options): Added "--attach=PID" for attaching to existing processes - and "--launch=(auto|posix|fork|springboard)" options. - (RNBRunLoopLaunchInferior): Now launches process with new - nub_launch_flavor_t enum that can be overridden with the --launch option. - (RNBRunLoopLaunchAttaching): New function for attaching to existing - processes. - (main): Added command line option support for the "--attach" and "--launch" - options and added attach to pid support and better logging. - * DNB.cpp/h: (DNBProcessLaunch): Added nub_launch_flavor_t and error - parameter for more precise control when launching processes. - (DNBProcessSBLaunch): Removed function as launching with SpringBoard can - now be done using DNBProcessLaunch with launch_flavor being set to - eLaunchTypeSpringBoard (arm only). - (DNBProcessSBAttach): Removed function (SpringBoard processes are now auto - detected in the MachProcess::AttachForDebug function on ARM). - * DNBDefs.h (NUB_GENERIC_ERROR): New generic error definition. - (nub_launch_flavor_t): New enumeration used for control over process - launching. - * MachProcess.cpp (IsSBProcess): New function. - (MachProcess::AttachForDebug): Removed flags parameter that was being used - for SpringBoard flags and we now detect if a process belongs to SpringBoard - by calling IsSBProcess. - (MachProcess::LaunchForDebug): Now has launch parameter that tells it how - to launch the inferior process and there is also an error code that gets - returned. This function can now launch using fork + exec, posix_spawn, - or SpringBoard on ARM targets. - (MachProcess::SBLaunchForDebug): Now uses DNBError reference instead of - uint32_t pointer for the error code. - (MachProcess::SBForkChildForPTraceDebugging): Ditto. - -2008-10-22 Greg Clayton <gclayton@apple.com> - - * MacOSX/arm/DNBArchImpl.cpp (DNBArchMachARM::GetRegisterValue): Set - register value to a uint32 value instead of a float64 value for s0 - - s31. - -2008-10-17 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Don't listen for - the qLaunchSuccess if we aren't doing a lockdown connnection. - -2008-10-13 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (class RNBRemote): Added m_watchpoints member. - * DNB.cpp (DNBBreakpointSet): Added boolean hardware parameter for - requesting that a hardware breakpoint be set. - (DNBWatchpointSet): New function. - (DNBWatchpointClear): New function. - (DNBWatchpointGetHitCount): New function. - (DNBWatchpointGetIgnoreCount): New function. - (DNBWatchpointSetIgnoreCount): New function. - (DNBWatchpointSetCallback): New function. - (DNBWatchpointPrint): New function. - * DNBRegisterInfo.cpp (DNBRegisterValueClass::Dump): Modified to emit - a single DNBLog() call so there aren't multiple newlines when logging - to ASL. - * RNBContext.cpp (RNBContext::ThreadFunctionProcessStatus): Use new - process state changed events. - * DNBBreakpoint.h (class DNBBreakpoint): Removed m_state member and - added m_tid, m_enabled, m_hw_preferred, m_is_watchpoint, m_watch_read, - m_watch_write, and m_hw_index. - (DNBBreakpoint::ThreadID()): New accessor. - (DNBBreakpoint::IsEnabled()): New accessor. - (DNBBreakpoint::SetEnabled()): New accessor. - (DNBBreakpoint::IsWatchpoint()): New accessor. - (DNBBreakpoint::IsBreakpoint()): New accessor. - (DNBBreakpoint::SetIsWatchpoint()): New accessor. - (DNBBreakpoint::WatchpointRead()): New accessor. - (DNBBreakpoint::WatchpointWrite()): New accessor. - (DNBBreakpoint::HardwarePreferred()): New accessor. - (DNBBreakpoint::IsHardware()): New accessor. - (DNBBreakpoint::GetHardwareIndex()): New accessor. - (DNBBreakpoint::SetHardwareIndex()): New accessor. - (DNBBreakpoint::ThreadID()): New accessor. - (DNBBreakpoint::GetState()): Removed accessor. - (DNBBreakpoint::SetState()): Removed accessor. - (DNBBreakpoint::AddBreakpoint()): Renamed to Add(). - (DNBBreakpoint::RemoveBreakpoint()): Renamed to Remove(). - (DNBBreakpoint::FindBreakIDForAddress()): Renamed to FindIDByAddress(). - (DNBBreakpoint::ShouldStopAtBreakpoint()): Renamed to ShouldStop(). - (DNBBreakpoint::SetBreakpointCallback()): Renamed to SetCallback(). - (DNBBreakpoint::FindBreakpointWithAddress()): Renamed to - FindByAddress(). - (DNBBreakpoint::FindBreakpointWithBreakID()): Renamed to FindByID(). - (DNBBreakpoint::GetBreakpointAtIndex()): Renamed to GetByIndex(). - * FunctionProfiler.h: New header for subclass of DNBRuntimeAction. - * RNBRemote.cpp (RNBRemote::HandlePacket_v): Use new process state - changed events. - (RNBRemote::HandlePacket_z): Implement the hardware breakpoint and - watchpoint commands z1, Z1, z2, Z2, z3 and Z3 - * PThreadEvent.h (PThreadEvent::GetEventBits): Made member function - const. - (PThreadEvent::WaitForSetEvents): Ditto. - (PThreadEvent::WaitForEventsToReset): Ditto. - (PThreadEvent::WaitForResetAck): Ditto. - (PThreadEvent::m_mutex): Made class member mutable. - (PThreadEvent::m_set_condition): Made class member mutable. - (PThreadEvent::m_reset_condition): New mutable class member. - * ProfileObjectiveC.cpp - * DNBArch.h (DNBArch::NotifyException): Now has default implementation - that returns false. - (DNBArch::NumSupportedHardwareBreakpoints): New virtual member - function with a default implementation. - (DNBArch::NumSupportedHardwareWatchpoints): Ditto. - (DNBArch::EnableHardwareBreakpoint): Ditto. - (DNBArch::EnableHardwareWatchpoint): Ditto. - (DNBArch::DisableHardwareBreakpoint): Ditto. - (DNBArch::DisableHardwareWatchpoint): Ditto. - * DNB.h (DNBBreakpointSet): New take a HARDWARE parameter that allows - requests for setting hardware breakpoints. - (DNBWatchpointSet): New function prototype. - (DNBWatchpointClear): New function prototype. - (DNBWatchpointGetHitCount): New function prototype. - (DNBWatchpointGetIgnoreCount): New function prototype. - (DNBWatchpointSetIgnoreCount): New function prototype. - (DNBWatchpointSetCallback): New function prototype. - (DNBWatchpointPrint): New function prototype. - * MacOSX/arm/DNBArchImpl.cpp: Added hardware breakpoint and watchpoint - support for ARM. - (DNBArchMachARM::GetCPUType): New function. - (DNBArchMachARM::DumpDBGState): New function. - (DNBArchMachARM::GetDBGState): New function. - (DNBArchMachARM::SetDBGState): New function. - (DNBArchMachARM::EnableHardwareSingleStep): New function. - (DNBArchMachARM::EnableHardwareBreakpoint): New function. - (DNBArchMachARM::NotifyException): Removed. - (DNBArchMachARM::DisableHardwareBreakpoint): New function. - (DNBArchMachARM::EnableHardwareWatchpoint): New function. - (DNBArchMachARM::DisableHardwareWatchpoint): New function. - * MacOSX/MachThread.cpp (MachThread::Suspend): Added better logging. - (MachThread::Resume): Ditto. - (MachThread::RestoreSuspendCount): Ditto. - (MachThread::Dump): Ditto. - (MachThread::EnableHardwareBreakpoint): New function. - (MachThread::EnableHardwareWatchpoint): New function. - (MachThread::DisableHardwareBreakpoint): New function. - (MachThread::DisableHardwareWatchpoint): New function. - * MacOSX/MachThreadList.h (MachThreadList::GetLastError): Removed. - (MachThread::EnableHardwareBreakpoint): New prototype. - (MachThread::DisableHardwareBreakpoint): New prototype. - (MachThread::EnableHardwareWatchpoint): New prototype. - (MachThread::DisableHardwareWatchpoint): New prototype. - (class MachThread): Remove m_err member variable. - * MacOSX/ppc/DNBArchImpl.cpp (DNBArchMachPPC::GetCPUType) New - function. - (DNBArchMachPPC::NotifyException): Removed. - * MacOSX/ppc/DNBArchImpl.h (DNBArchMachPPC::NotifyException): Removed. - * MacOSX/MachThread.h (MachThread::EnableHardwareBreakpoint): New - prototype. - (MachThread::EnableHardwareWatchpoint): New prototype. - (MachThread::DisableHardwareBreakpoint): New prototype. - (MachThread::DisableHardwareWatchpoint): New prototype. - (class MachThread): Renambed class member m_exception to - m_stop_exception. - * MacOSX/MachProcess.cpp (MachProcess::SetState): Updated to use new - process event enumerations. - (MachProcess::PrivateResume): Added better logging. - (MachProcess::CreateBreakpoint): Added bool HARDWARE parameter for - requesting hardware breakpoints. - (MachProcess::CreateWatchpoint): New function. - (MachProcess::DisableAllWatchpoints): New function. - (MachProcess::DisableWatchpoint): New function. - (MachProcess::DumpWatchpoint): New function. - (MachProcess::EnableBreakpoint): Enabled breakpoints in hardware if - requested and supported. - (MachProcess::DisableBreakpoint): Disable hardware breakpoints if that - is how they were set. - (MachProcess::EnableWatchpoint): New function. - (MachProcess::ExceptionMessageBundleComplete): Wait for the - eEventProcessRunningStateChanged event to be reset before changing - state to stopped to avoid race condition with very fast start/stops. - (MachProcess::LaunchForDebug): Added posix_spawn support. - (MachProcess::PosixSpawnChildForPTraceDebugging): New function. - * MacOSX/i386/DNBArchImpl.cpp (DNBArchMachI386::GetCPUType): New - function. - * MacOSX/i386/DNBArchImpl.h (DNBArchMachI386::GetCPUType): New - prototype. - * MacOSX/MachProcess.h (PosixSpawnChildForPTraceDebugging): New - prototype. - * MacOSX/MachException.cpp (class MachException::ThreadMessage): - Renamed class to MachException::Data. - * MacOSX/MachThreadList.cpp (class MachThreadList): Removed m_err - class member. - (MachThreadList::EnableHardwareBreakpoint): New function. - (MachThreadList::DisableHardwareBreakpoint): New function. - (MachThreadList::EnableHardwareWatchpoint): New function. - (MachThreadList::DisableHardwareWatchpoint): New function. - * MacOSX/MachException.h (class MachException::ThreadMessage): - Renamed class to MachException::Data. - * DNBDefs.h (nub_watch_t): New typedef. - (INVALID_NUB_HW_INDEX): New macro definition. - (WATCH_TYPE_READ): New macro definition. - (WATCH_TYPE_WRITE): New macro definition. - (NUB_STATE_IS_RUNNING): New macro to see if state is a running state. - (NUB_STATE_IS_STOPPED): New macro to see if state is a stopped state. - (eEventProcessStateChanged): Deprecated. - (eEventProcessRunningStateChanged): New process event state. - (eEventProcessStoppedStateChanged): New process event state. - (LOG_WATCHPOINTS): New macro definition for logging watchpoints. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Use new process - event states. - * FunctionProfiler.cpp: New class that allows single stepping through - an address range for tracing exact call graphs. - -2008-09-22 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (GetContinueThread): If the continue thread is zero or - -1 then return GetCurrentThread(). - * RNBRemote.cpp (m_packets): Made the vCont functions call - RNBRemote::HandlePacket_v(). - (RNBRemote::HandlePacket_H): Cleaned up whitespace. - (RNBRemote::HandlePacket_last_signal): Return actual signal values for - EXE_SOFTWARE/EXC_SOFT_SIGNAL mach exceptions. - (RNBRemote::HandlePacket_v): Implemented the 'vCont?' and 'vCont;' - packets. - (RNBRemote::HandlePacket_c): Handle the case where an address is - provided. - (RNBRemote::HandlePacket_C): Implemented the continue with signal - including when an address is provided. - (RNBRemote::HandlePacket_S): Implemented the step with signal - including when an address is provided. - * DNB.cpp (DNBProcessResume): Pass 0 as the signal when resuming - a process without specifying a thread. - (DNBThreadResume): Pass 0 as the signal when resuming a specific thread. - (DNBThreadResumeWithSignal): New function. - * DNB.h (DNBThreadResumeWithSignal): New prototype. - * MachException.h (MachException::Message::Reply): Added a signal - parameter. - * MachException.cpp (MachException::Message::Reply): Update the thread - with the new SIGNAL parameter instead of always zero so signals can be - passed on to programs. - * MachProcess.h (MachProcess::Resume): Added a signal parameter. - * MachProcess.h (MachProcess::PrivateResume): Added a signal parameter. - * MachProcess.cpp (MachProcess::Resume): Pass new SIGNAL parameter to - MachProcess::PrivateResume. - * MachProcess.cpp (MachProcess::PrivateResume): Pass new SIGNAL - parameter to the mach exception reply. - -2008-08-08 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (gProcessMap): Removed static C++ global. - (GetProcessMap): New Function. - (AddProcessToMap): New function. - (RemoveProcessFromMap): New function. - (GetProcessSP): Use new GetProcessMap function to get process list. - -2008-07-30 Greg Clayton <gclayton@apple.com> - - * debugserver-entitlements.plist (get-task-allow): Removed. - (run-invalid-allow): Added boolean value set to TRUE. - -2008-04-18 Greg Clayton <gclayton@apple.com> - - * MachProcess.cpp (MachProcess::Task): Added getuid(), geteuid(), - getgid(), getegid() to the log message if task for pid fails. - -2008-04-07 Greg Clayton <gclayton@apple.com> - - * RNBContext.cpp (RNBContext::LaunchStatusAsString): Removed unused - tmp_str variable. - -2008-04-04 Greg Clayton <gclayton@apple.com> - - * CFString.cpp/h (UTF8): Made a static function that can convert - a CFStringRef to UTF8. - -2008-04-04 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (main): Make sure we exit after we send the - application list. - -2008-04-04 Greg Clayton <gclayton@apple.com> - - * RNBServices.h (IsSBProcess): New prototype; - * RNBServices.cpp (IsSBProcess): New function that returns true it - SpringBoard owns or knows about the process. - * RNBRemote.cpp (RNBRemote::HandlePacket_v): Made attach work correctly. - * DNB.cpp (DNBProcessSBAttach): New function for use when attaching to - a process owned by SpringBoard. - (DNBProcessAttach): Fixed an issue where a local was shadowing a - parameter. - * DNB.h (DNBProcessSBAttach): New prototype. - * MachProcess.cpp (MachProcess::AttachForDebug): AttachForDebug now - takes some flags so it knows to enable SpringBoard functionality. - * MachProcess.h (MachProcess::AttachForDebug): Added flags parameter - to prototype. - -2008-04-04 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (RNBRunLoopGetArgsFromRemote): Handle the new - attach packet and watch for connection being lost. - (main): handle the --applist option when there we aren't using lockdown - by printing the results to stdout and exiting with appropriate error code - if we failed. Also handle the new prototype for ListApplications. - * RNBServices.h (ListApplications): Change first parameter to be a std::string - that will get the contents of the plist so we can use this for more than - just lockdown. - * RNBServices.cpp (ListApplications): Change first parameter to be a std::string - that will get the contents of the plist so we can use this for more than - just lockdown and also fixed the logic so we actually create a full list of - applications instead of just overwriting the first entry. - * RNBRemote.h (PacketEnum): Added a new 'vattach' enum for the "vAttach;PID" - gdb remote command. - (RNBRemote::HandlePacket_v): New prototype; - * RNBRemote.cpp (RNBRemote::CreatePacketTable): add the vattach packet definition - to m_packets. - (RNBRemote::HandlePacket_v): New function that handles attach to a process. - -2008-04-03 Jim Ingham <jingham@apple.com> - - * RNBRemote.h: Add query_launch_success to packet enum. - * RNBRemote.cpp (RNBRemote::CreatePacketTable_): Add query_launch_success. - (HandlePacket_q): Handle query_launch_success. - * DNB.cpp (DNBProcessSBLaunch): Pass in launch_retval. - * DNB.h: Change prototype of DNBProcessSBLaunch to take launch_retval. - * RNBContext.cpp (RNBContext::LaunchStatusAsString): New function. - * RNBContext.h (RNBContext): Add m_launch_status & accessors. - * macosx/MachProcess.cpp (MachProcess::SBLaunchForDebug): Pass launch_retval. - (MachProcess::SBForkChildForPTraceDebugging): Accept & set launch_retval. - * Macosx/MachProcess.h: Change prototypes of SBLaunchForDebug & - ForkChildForPTraceDebugging to accept launch_retval. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Get the launch status and - put it in the context, then wait for the qLaunchStatus packet. - -2008-04-03 Greg Clayton <gclayton@apple.com> - - * com.apple.debugserver.plist: Changed plist so debugserver - runs as mobile user. - * com.apple.debugserver.applist.plist: Ditto. - -2008-04-03 Greg Clayton <gclayton@apple.com> - - * MachProcess.cpp: (MachProcess::SBForkChildForPTraceDebugging): - Increased SBS application launch timeout to 30 seconds. - -2008-03-27 Christopher Friesen <friesen@apple.com> - - * RNBServices.h: Pass tasks from SpringBoard as a plist - * RNBServices.cpp: Ditto. - * test-remotenub.cpp: added --applist flag - * com.apple.debugserver.applist.plist: Agent plist - -2008-03-17 Jim Ingham <jingham@apple.com> - - * DNB.h: Pass envp to DNBProcessLaunch & DNBProcessSBLaunch. - * DNB.cpp: Ditto. - * MachProcess.h: Ditto for *LaunchForDebug and - *ForkChildForPtraceDebugging. - * MachProcess.cpp (MachProcess::LaunchForDebug): Pass on envp. - (MachProcess::SBLaunchForDebug): Ditto. - (MachProcess::ForkChildForPtraceDebugging): Accept envp, haven't actually - implemented the passing yet. - (MachProcess::SBForkChildForPtraceDebuggin): Accept envp, convert to - CFDictionary and pass to SBSLaunchApplication. - * RNBContext.h: Add environment to the context. - * RBNContext.cpp (RNBContext::EnvironmentAtIndex): New function. - * RNBRemote.h: Add set_environment_variable to the PacketEnum. - * RNBRemote.cpp (RNBRemote::CreatePacketTable): Add QEnvironment:. - * (RNBRemote::HandlePacket_Q): Ingest the environment variable. - * test-remotenub.cpp (RNBRunLoppLaunchInferior): Convert the env - array in the context into an array, and pass it to the DNBProcess*Launch - methods. - -2008-03-17 Greg Clayton <gclayton@apple.com> - - * DNBBreakpoint.cpp (DNBBreakpointList::GetBreakpointAtIndex): New - functions (const and non-const versions). - * DNBBreakpoint.h (DNBBreakpointList::GetBreakpointAtIndex): New - prototypes (const and non-const versions). - * DNBError.h (DNBError::Success()): Don't use KERN_SUCCESS define. - (DNBError::Fail()): Don't use KERN_SUCCESS define. - * MachProcess.cpp (MachProcess::DisableAllBreakpoints): New function. - (MachProcess::Detach): Added initial implementation that will halt - the process, disable all breakpoints and call PT_DETACH. - * MachProcess.h (MachProcess::DisableAllBreakpoints): New prototype. - -2008-03-04 Greg Clayton <gclayton@apple.com> - - * RNBRemote.h (RNBRemote::SendHexEncodedBytePacket): New prototype. - * RNBRemote.cpp (RNBRemote::SendHexEncodedBytePacket): New function. - (RNBRemote::SendSTDOUTPacket): Use SendHexEncodedBytePacket function - to send bytes. - (RNBRemote::SendSTDERRPacket): Ditto. - (RNBRemote::HandlePacket_q): Return a valid thread info string for - qThreadExtraInfo queries. - * DNB.cpp (DNBThreadPrintStopReason): Commented out unused function. - (DNBThreadGetInfo): New function. - * DNB.h (DNBThreadPrintStopReason): Commented out prototype. - (DNBThreadGetInfo): New prototype. - * MachProcess.cpp (MachProcess::GetThreadInfo): New function. - * MachProcess.h (MachProcess::GetThreadInfo): New prototype. - * MachThreadList.cpp (MachThreadList::GetThreadInfo): New function. - * MachThreadList.h (MachThreadList::GetThreadInfo): New prototype. - * MachThread.cpp (MachThread::GetBasicInfoAsString): New function. - (MachThread::InferiorThreadID): New function. - * MachThread.cpp (MachThread::GetBasicInfoAsString): New prototype. - (MachThread::InferiorThreadID): New prototype. - -2008-02-27 Greg Clayton <gclayton@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_last_signal): Set the - current thread when we notify a thread has stopped to subsequent - g and p packets get the correct data. - -2008-02-26 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Add query_thread_extra_info enum. - * RNBRemote.cpp: Add support for qThreadExtraInfo. - Currently we return 'Ok' as the packet status for - every thread. - -2008-02-26 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (RNBRemote::HandlePacket_q): Correct handling - of qfThreadInfo/qsThreadInfo. - -2008-02-20 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Change default for gdb's max incoming packet size to - reflect the real default size. - * RNBRemote.cpp (HandlePacket_Q): Correct the string comparisons for - the QSetMaxPayloadSize and QSetMaxPacketSize packets. - -2008-02-19 Christopher Friesen <friesen@apple.com> - - * CFDataFormatters.c: CoreFoundation data formatters added to project. - -2008-02-19 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Record the max payload size, not the max packet - size for less ambiguous meaning. - * RNBRemote.cpp: Add support for QSetMaxPayloadSize: packet which - should have a clearer meaning than QSetMaxPacketSize. - QSetMaxPacketSize will be removed once we get have a chance to get - a new debugserver and gdb submitted. - -2008-02-18 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Make default size 1024. - * RNBRemote.cpp: Questionmark packet should stay under - max_packet_size - 5 to allow for start, end, checksum and nul - char bytes. - -2008-02-18 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Add m_max_packet_size to class defn. - * RNBRemote.cpp: Initialize it, use it. - -2008-02-18 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Add set_max_packet_size. - * RNBRemote.cpp: Add QSetMaxPacketSize packet handling. - -2008-02-18 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (HandleProcessStateChange): Call new - RNBRemote::FlushSTDIO function. - (RNBRunLoopInferiorExecuting): Ditto. - * RNBRemote.h (RNBRemote::FlushSTDIO): New prototype. - * RNBRemote.cpp (RNBRemote::FlushSTDIO): New function to - centralize the stdio. - -2008-02-18 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (DNBProcessWaitForEvent): Added timeout pointer as - parameter that can be NULL for infinite timeout to simplify - the DNB interface. - (DNBProcessTimedWaitForEvent): Removed function. - * DNB.h (DNBProcessWaitForEvent): Added timeout argument. - (DNBProcessTimedWaitForEvent): Removed prototype. - * DNBTimer.h (DNBTimer::OffsetTimeOfDay): New function. - * CFString.cpp (CFString::GetLength() const): New function. - * CFString.h (CFString::GetLength() const): New prototype. - * MachProcess.h (MachProcess class): Removed m_attached and - added m_flags. - * MachProcess.cpp (MachProcess::AttachForDebug): Set m_flags - to indicate we attached. - (MachProcess::SBLaunchForDebug): Set m_flags to indicate we - attached using SpringBoard and that we attached. - (MachProcess::SBForkChildForPTraceDebugging): Changed to new - SpringBoardServices API. - (MachProcess::ThreadFunctionException): Added code that will - renew a watchdog assertion when we launch apps through - SpringBoardServices. - * PThreadEvent.cpp (PThreadEvent::WaitForSetEvents): Simplified - PThreadEvent API to have only one version of WaitForSetEvents - that has an optional timeout pointer argument. - * RNBContext.cpp (RNBContext::StopProcessStatusThread): Adapt - to new PThreadEvent API changes. - (RNBContext::ThreadFunctionProcessStatus): Adapt to new - DNBProcessWaitForEvent API changes. - * RNBRemote.cpp (RNBRemote::StopReadRemoteDataThread): Adapt - to new PThreadEvent API changes. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Adapt to new - DNBProcessWaitForEvent API changes. - (RNBRunLoopInferiorExecuting): Process STDIO first, then - incoming packets. - -2008-02-14 Jason Molenda (jmolenda@apple.com) - - * MachProcess.cpp: (MachProcess::SBForkChildForPTraceDebugging): - Set mode bits on slave side of pty. - -2008-02-12 Greg Clayton <gclayton@apple.com> - - * DNB.cpp (DNBEnableLogging): Removed function. - (DNBThreadPrintStopReason): Removed the file handle from this - function and use DNBLog calls. - * DNB.h (DNBEnableLogging): Removed function prototype. - (DNBThreadPrintStopReason): Removed the file handle - from the function prototype in favor of using DNBLog calls. - * DNBDataRef.cpp (DNBDataRef::Dump): Removed file handle to use - DNBLog for the logging and print a log line each time a full line - is ready for output after caching it in a local buffer. - * DNBDataRef.cpp (DNBDataRef::Dump): Removed file handle from - prototype. - * DNBDefs.h (DNBCallbackLog): New callback prototype for all - logging. - DNBLog.cpp(g_debug_opt): Renamed to d_debug and made it a file - static. - (DNBLogGetDebug): New accessor function for g_debug. - (DNBLogSetDebug): New accessor function for g_debug. - (g_verbose): Made into a file static and added accessors. - (DNBLogGetVerbose): New accessor function for g_verbose. - (DNBLogSetVerbose): New accessor function for g_verbose. - (DNBLogSetLogCallback): New function call that registers a logging - callback for all logging in libdebugnub.dylib and any code that - loads it. - (DNBLogToASL): Removed function as it is deprecated in favor of - using DNBLogSetLogCallback to register a callback function that - implements the logging. - (DNBLogToFile): Ditto. - (DNBLogCloseLogFile): Ditto. - (DNBLogToFile): Ditto. - (DNBLogToFile): Ditto. - (_DNBLogPuts): Removed unused function. - (_DNBLogVAPrintf): Calls the callback function to do the logging - if one has been registered. - * DNBLog.h (DNBLOG_FLAG_FATAL): New defines that get passed to - any registered logging callback functions. - (DNBLOG_FLAG_FATAL): Ditto. - (DNBLOG_FLAG_ERROR): Ditto. - (DNBLOG_FLAG_WARNING): Ditto. - (DNBLOG_FLAG_DEBUG): Ditto. - (DNBLOG_FLAG_VERBOSE): Ditto. - (DNBLOG_FLAG_THREADED): Ditto. - (DNBLog*): All logging calls are now exported from libdebugnub.dylib - so there aren't two copies (one in debugserver and one in debugnub). - C99 vararg Macros wrap all logging calls so no var arg processing - occurs when logging is disabled. - * DNBRegisterInfo.cpp (DNBRegisterValueClass::Dump): Removed file - handle and now use DNBLog calls. - * DNBRegisterInfo.h (DNBRegisterValueClass::Dump): Removed file - handle from prototype. - * MachException.cpp (catch_mach_exception_raise_state_identity): - Removed newlines from logging call. - (catch_mach_exception_raise): Ditto. - (MachException::Message::Dump): Removed file handle from params - and removed newlines from logging call. - (MachException::ThreadMessage::DumpStopReason): Removed file handle - from params and use DNBLog for logging output. - (MachException::ThreadMessage::Dump): Log using DNBLog instead of - file handle. - * MachProcess.cpp (MachProcess::DumpThreadStoppedReason): Ditto. - (MachProcess::ReadMemory): Ditto. - (MachProcess::WriteMemory): Ditto. - (ExceptionMessageBundleComplete): Ditto. - * MachThread.cpp (MachThread::Dump): Ditto. - (MachThread::DumpRegisterState): Ditto. - * MachThreadList.cpp (MachThreadList::DumpThreadStoppedReason): Ditto. - (MachThreadList::Dump): Ditto. - * RNBRemote.cpp (set_logging): Use new function callback registration - calls when enabling ASL logging. - test-remotenub.cpp (ASLLogCallback): New function to handle all ASL - logging. This function gets registered with libdebugnub.dylib when we - want to log using ASL. - (FileLogCallback): New function to handle all file logging. This - function gets registered with libdebugnub.dylib when we want to log - to a 'FILE *'. - (main): Register the logging callback functions when we want to log - to file or using ASL. - -2008-02-12 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (main): Default to ASL logging with no log - bits set to allow for warning and error logging. - * RNBRemote.h (struct Breakpoint): New structure for ref counting - breakpoints in Z and z packets. - * RNBRemote.cpp (RNBRemote::SendPacket): Use new LOG_RNB_PACKETS - defined when logging actual packet content. - (RNBRemote::HandleAsyncPacket): Ditto. - (RNBRemote::HandleReceivedPacket): Ditto. - (RNBRemote::HandlePacket_z): Ref count the setting and removing - of breakpoints with the Z and z packets using new struct - RNBRemote::Breakpoint. - * RNBDefs.h (LOG_RNB_PACKETS): New define for logging the sending - and receiving of packets data. - * DNB.cpp (DNBPrintf): Check for NULL file handle. - * DNBBreakpoint.cpp (DNBBreakpoint::Dump): Ditto. - (DNBBreakpointList::Dump): Ditto. - * DNBDefs.h (LOG_EVENTS): New define for logging PThreadEvent. - * DNBLog.cpp (g_debug_opt): Relocated outside of #if that turns off - logging completely to allow option parsing code that uses it to - still compile. - (g_verbose): Ditto. - * DNBLog.h (DNBLogToASL): Added prototype for when logging is - disabled via preprocessor macro. - (DNBLogToFile): Ditto. - * DNBRegisterInfo.cpp (DNBRegisterValueClass::Dump): Check for NULL - file handle. - * MachException.cpp (MachException::ThreadMessage::DumpStopReason): Ditto. - (MachException::ThreadMessage::Dump): Ditto. - * MachProcess.cpp (MachProcess::CreateBreakpoint): Improved logging. - (MachProcess::DisableBreakpoint): Verify the original opcode gets - restored, improved logging and added unconditional logging for when - things go wrong. - (MachProcess::EnableBreakpoint): Verify the breakpoint opcode gets - written, improved logging and added unconditional logging for when - things go wrong. - * MachThread.cpp (MachThread::Dump): Check for NULL file handle. - * MachVMMemory.cpp (MachVMMemory::WriteRegion): Flush caches in inferior - after writing to inferior memory. - * PThreadEvent.cpp: Changed all logging calls to key off of LOG_EVENTS - instead of LOG_VERBOSE. - MachDYLD.cpp (MachDYLD::Dump): Check for NULL file handle. - (MachDYLD::DYLIBInfo::Dump): Ditto. - ProfileObjectiveC.cpp (ProfileObjectiveC::DumpStats): Ditto. - -2008-02-09 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (set_logging): Log to ASL unconditionally when - processing a QSetLogging packet. - -2008-02-06 Greg Clayton <gclayton@apple.com> - - * test-remotenub.cpp (main): Dup stdout and stderr to /dev/NULL - when we use lockdown. - -2008-02-06 Greg Clayton <gclayton@apple.com> - - * RNBSocket.cpp (RNBSocket::Disconnect): Removed unused var ERR. - * RNBRemote.cpp(RNBRemote::HandlePacket_Q): Removed unused var PID. - * DNBError.cpp (DNBError::LogThreadedIfError): Removed unused var - ERR_MSG. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Removed unused - variable EXECUTABLE_LENGTH. - (main): Removed unused variable ARG_IDX. - -2008-02-06 Chris Marcellino (cmarcellino@apple.com) and Myke Olson (molson@apple.com) - - * MachProcess.cpp (SBForkChildForPTraceDebugging): Bring up to date with - current SpringBoardServices.framework types and imports. - -2008-02-05 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (set_logging): Remove the mode=file and filename= - options to the QSetLogging packet. We're only going to support logging - to ASL for now. Logging to a file can still be accomplished by the - -l command line argument. - -2008-02-02 Christopher Friesen (cfriesen@apple.com) - - * Added libXcodeDebugerSupport.dylib target - * XCDebuggerIntrospection.[hc]: Support for Xcode's debugger introspection. - -2008-02-01 Jason Molenda (jmolenda@apple.com) - - * DNBLog.cpp (DNBLogCloseLogFile): New function to close a logfile - at exit. - * DNBLog.h: Prototype. - * test-remotenub.cpp (main): Close the log file before exiting. - -2008-02-01 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (set_logging): Recognize the "filename=" argument - to the QSetLogging directive. - * DNBLog.cpp (DNBLogGetLogMask): New fun.c - * DNBLog.h: Prototype. - -2008-01-31 Jason Molenda (jmolenda@apple.com) - - * DNBLog.cpp: Add ASL logging as a run-time selectable option. - (DNBLogToASL, DNBLogToFile): Functions to switch between logging to - a file and logging via ASL. - * DNBLog.h: Prototypes. - * RNBRemote.cpp (set_logging): Recognize the "mode=" field to enable - asl logging. Skip unrecognized keys. - -2008-01-31 Greg Clayton (gclayton@apple.com) - - * DNB.cpp (sigchld_handler): Better logging when we get a - SIGCHILD and we are watching for process related logging events. - * test-remotenub.cpp (RNBRunLoopInferiorExecuting): Only reset - events when we still have event bits set. - -2008-01-29 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Add set_logging_mode. - * RNBRemote.cpp (RNBRemote::CreatePacketTable): Recognize - QSetLogging. - -2008-01-29 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (set_logging): New function to parse the QSetLogging - packet. - (RNBRemote::HandlePacket_Q): Call it. - -2008-01-28 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: Minimal packet size is 1024 in our gdb now. - * RNBRemote.cpp: Add the stop_pc value in big-endian order to the - T response packet to make it a little easier to follow where gdb - is stepping. - -2008-01-28 Greg Clayton <gclayton@apple.com> - - * RNBContext.h: Removed m_pid_state from RNBContext class so that - it couldn't get out of sync with the actual process and its accessors - SetProcessState() and GetProcessState(). - * RNBContext.cpp (RNBContext::ProcessStateRunning): Always return the - current state of the process instead of a cached value. - * test-remotenub.cpp (RNBRunLoopLaunchInferior): Remove call to - deprecated RNBContext::SetProcessState(). - (HandleProcessStateChange): Ditto. - -2008-01-24 Greg Clayton (gclayton@apple.com) - - * RNBRemote.cpp (RNBRemote::HandlePacket_q): See if command starts with - "qSymbol" (no trailing "s") and return the empty string. - -2008-01-24 Greg Clayton (gclayton@apple.com) - - * RNBRemote.cpp (RNBRemote::HandlePacket_q): See if command starts with - "qSymbols" and return the empty string. - -2008-01-24 Greg Clayton (gclayton@apple.com) - - * DNBError.h (DNBError::DumpIfError): Removed prototype. - * DNBError.cpp (DNBError::DumpIfError): Removed function. - (DNBError::LogThreadedIfError): Output error as hex. - * MachException.cpp (MachException::Message::Receive): Don't use - DNBError::DumpIfError, now use DNBError::LogThreadedIfError. - * MachProcess.cpp (MachProcess::StartExceptionThread): Ditto. - (MachProcess::Suspend): Ditto. - (MachProcess::SBForkChildForPTraceDebugging): Ditto. - * MachVMMemory.cpp (MachVMMemory::Read): Cleaned up logging - calls. - (MachVMMemory::Write): Ditto. - (MachVMMemory::WriteRegion): Added logging. - * RNBContenxt.cpp (display_thread_info): Removed function. - * RNBRemote.cpp (RNBRemote::GetPacket): Commented out stderr - messages to avoid SpringBoard from killing us. - (RNBRemote::HandlePacket_p): Ditto. - (RNBRemote::HandlePacket_P): Ditto. - (RNBRemote::HandlePacket_c): Ditto. - (RNBRemote::HandlePacket_A): Removed code that was already - * RNBSocket.cpp (RNBSocket::Listen): Commented out stdout - messages to avoid SpringBoard from killing us. - (RNBSocket::ConnectToService): Ditto. - -2008-01-24 Jim Ingham <jingham@apple.com> - - * RNBRemote.cpp (RNBRemote::HandlePacket_q): Reply "" to qSymbols - and qOffsets. - -2008-01-23 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.h: m_noack_mode to RNBRemote class. - * RNBRemote.cpp: Change #ifdef NO_ACKS code blocks - to use m_noack_mode instance variable. - (RNBRemote::HandlePacket_Q): New function to handle - QStartNoAckMode packet and set m_noack_mode appropriately. - * test-remotenub.cpp: Remove NO_ACKS ifdefs. - -2008-01-22 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (RNBRemote::CreatePacketTable): Recognize - QStartNoAckMode as an unsupported remote protocol request. - * RNBRemote.h: Add start_noack_mode enum entry. - -2008-01-22 Greg Clayton (gclayton@apple.com) - - * DNBLog.h: Removed C++ namespace for DNBLog (changed all DNBLog:: - to DNBLog) so C99 var arg macros can be used to completely disable - all logging and any functions that may be called when making the - variable arguments. - * DNBLog.cpp: Ditto. - * DNB.cpp: Ditto. - * DNBBreakpoint.cpp: Ditto. - * DNBError.cpp: Ditto. - * MacOSX/MachDYLD.cpp: Ditto. - * MacOSX/MachException.cpp: Ditto. - * MacOSX/MachProcess.cpp: Ditto. - * MacOSX/MachThread.cpp: Ditto. - * MacOSX/MachThreadList.cpp: Ditto. - * MacOSX/MachVMMemory.cpp: Ditto. - * MacOSX/MachVMRegion.cpp: Ditto. - * MacOSX/arm/DNBArchImpl.cpp: Ditto. - * MacOSX/ppc/DNBArchImpl.cpp: Ditto. - * PThreadEvent.cpp: Ditto. - * RNBContext.cpp: Ditto. - * RNBRemote.cpp: Ditto. - * RNBSocket.cpp: Ditto. - * test-remotenub.cpp: Ditto. - -2008-01-21 Jason Molenda (jmolenda@apple.com) - - * test-remotenub.cpp: Add NO_SPRINGBOARD for turning off SpringBoard - dependency ala NO_ACKS. - -2008-01-18 Jason Molenda (jmolenda@apple.com) - - * RNBSocket.h (RNBSocket::RNBSocket): Take either a port # or - an already-opened socket, with a boolean to indicate which it is. - * RNBRemote.cpp (RNBRemote::RNBRemote): Ditto. - * RNBRemote.h: Prototype update. - * test-remotenub.cpp: Include lockdown.h. Take --lockdown command - line arg, get the socket from liblockdown.dylib instead of opening - our own socket if it is specified. --lockdown indicates that - the program name/args will be provided via remote protocol instead - of on the command line. - -2008-01-17 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp: Add NO_ACKS #ifdefs around code that computes - the checksums and sends/expects the gdb remote protocol ACK packets. - If NO_ACKS is defined, debugserver will not send or expect acks. - * test-remotenub.cpp (main): Print a different version string - if NO_ACKS is defined. - -2008-01-16 Greg Clayton (gclayton@apple.com) - - * PThreadEvent.cpp: Added this pointer to all logging calls. - -2008-01-16 Greg Clayton (gclayton@apple.com) - - * RNBSocket.cpp (RNBSocket::Connect()): Use TCP so we can try the - TCP_NODELAY socket option. - (RNBSocket::SetSocketOption()): New function. - * RNBSocket.h (RNBSocket::SetSocketOption()): New class function. - -2008-01-14 Jason Molenda (jmolenda@apple.com) - - * RNBRemote.cpp (RNBRemote::HandlePacket_last_signal): When printing - registers, skip over gdb regs which don't map to DNB regs. - -2008-01-14 Jim Ingham <jingham@apple.com> - - * ChangeLog - created. - * RBNContext.h: Added m_arg_vec and accessors. - * RNBContext.cpp (SetProcessID): New function. - * RBNRemote.h: Added packet type to HandlePacket & HandleAsyncPacket - * RNBRemote.cpp (HandlePacket, HandleAsyncPacket): Return type. - (HandlePacket_A): Fix a few bugs. - (HandlePacket_H): Return OK if target is not yet running. - (HandlePacket_q): Return PID of 0 if target is not yet running. - * testremotenub.cpp (RNBRunLoopGetArgsFromRemote): Implement. - (RNBRunLoopLaunchInferior): Fetch arguments from context. - (main) Store arguments in context, call RNBRunLoopGetArgsFromRemote - if appropriate. diff --git a/tools/debugserver/source/DNB.cpp b/tools/debugserver/source/DNB.cpp deleted file mode 100644 index 4f212a73d64e..000000000000 --- a/tools/debugserver/source/DNB.cpp +++ /dev/null @@ -1,1780 +0,0 @@ -//===-- DNB.cpp -------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/23/07. -// -//===----------------------------------------------------------------------===// - -#include "DNB.h" -#include <inttypes.h> -#include <libproc.h> -#include <map> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <vector> - -#if defined(__APPLE__) -#include <pthread.h> -#include <sched.h> -#endif - -#define TRY_KQUEUE 1 - -#ifdef TRY_KQUEUE -#include <sys/event.h> -#include <sys/time.h> -#ifdef NOTE_EXIT_DETAIL -#define USE_KQUEUE -#endif -#endif - -#include "CFBundle.h" -#include "CFString.h" -#include "DNBDataRef.h" -#include "DNBLog.h" -#include "DNBThreadResumeActions.h" -#include "DNBTimer.h" -#include "MacOSX/DarwinLog/DarwinLogCollector.h" -#include "MacOSX/Genealogy.h" -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachTask.h" -#include "MacOSX/ThreadInfo.h" - -typedef std::shared_ptr<MachProcess> MachProcessSP; -typedef std::map<nub_process_t, MachProcessSP> ProcessMap; -typedef ProcessMap::iterator ProcessMapIter; -typedef ProcessMap::const_iterator ProcessMapConstIter; - -size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos); -static size_t -GetAllInfosMatchingName(const char *process_name, - std::vector<struct kinfo_proc> &matching_proc_infos); - -//---------------------------------------------------------------------- -// A Thread safe singleton to get a process map pointer. -// -// Returns a pointer to the existing process map, or a pointer to a -// newly created process map if CAN_CREATE is non-zero. -//---------------------------------------------------------------------- -static ProcessMap *GetProcessMap(bool can_create) { - static ProcessMap *g_process_map_ptr = NULL; - - if (can_create && g_process_map_ptr == NULL) { - static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER; - PTHREAD_MUTEX_LOCKER(locker, &g_process_map_mutex); - if (g_process_map_ptr == NULL) - g_process_map_ptr = new ProcessMap; - } - return g_process_map_ptr; -} - -//---------------------------------------------------------------------- -// Add PID to the shared process pointer map. -// -// Return non-zero value if we succeed in adding the process to the map. -// The only time this should fail is if we run out of memory and can't -// allocate a ProcessMap. -//---------------------------------------------------------------------- -static nub_bool_t AddProcessToMap(nub_process_t pid, MachProcessSP &procSP) { - ProcessMap *process_map = GetProcessMap(true); - if (process_map) { - process_map->insert(std::make_pair(pid, procSP)); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// Remove the shared pointer for PID from the process map. -// -// Returns the number of items removed from the process map. -//---------------------------------------------------------------------- -// static size_t -// RemoveProcessFromMap (nub_process_t pid) -//{ -// ProcessMap* process_map = GetProcessMap(false); -// if (process_map) -// { -// return process_map->erase(pid); -// } -// return 0; -//} - -//---------------------------------------------------------------------- -// Get the shared pointer for PID from the existing process map. -// -// Returns true if we successfully find a shared pointer to a -// MachProcess object. -//---------------------------------------------------------------------- -static nub_bool_t GetProcessSP(nub_process_t pid, MachProcessSP &procSP) { - ProcessMap *process_map = GetProcessMap(false); - if (process_map != NULL) { - ProcessMapIter pos = process_map->find(pid); - if (pos != process_map->end()) { - procSP = pos->second; - return true; - } - } - procSP.reset(); - return false; -} - -#ifdef USE_KQUEUE -void *kqueue_thread(void *arg) { - int kq_id = (int)(intptr_t)arg; - -#if defined(__APPLE__) - pthread_setname_np("kqueue thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } -#endif -#endif - - struct kevent death_event; - while (1) { - int n_events = kevent(kq_id, NULL, 0, &death_event, 1, NULL); - if (n_events == -1) { - if (errno == EINTR) - continue; - else { - DNBLogError("kqueue failed with error: (%d): %s", errno, - strerror(errno)); - return NULL; - } - } else if (death_event.flags & EV_ERROR) { - int error_no = static_cast<int>(death_event.data); - const char *error_str = strerror(error_no); - if (error_str == NULL) - error_str = "Unknown error"; - DNBLogError("Failed to initialize kqueue event: (%d): %s", error_no, - error_str); - return NULL; - } else { - int status; - const pid_t pid = (pid_t)death_event.ident; - const pid_t child_pid = waitpid(pid, &status, 0); - - bool exited = false; - int signal = 0; - int exit_status = 0; - if (WIFSTOPPED(status)) { - signal = WSTOPSIG(status); - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", - child_pid, signal); - } else if (WIFEXITED(status)) { - exit_status = WEXITSTATUS(status); - exited = true; - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", - child_pid, exit_status); - } else if (WIFSIGNALED(status)) { - signal = WTERMSIG(status); - if (child_pid == abs(pid)) { - DNBLogThreadedIf(LOG_PROCESS, - "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", - child_pid, signal); - char exit_info[64]; - ::snprintf(exit_info, sizeof(exit_info), - "Terminated due to signal %i", signal); - DNBProcessSetExitInfo(child_pid, exit_info); - exited = true; - exit_status = INT8_MAX; - } else { - DNBLogThreadedIf(LOG_PROCESS, - "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, - signal); - } - } - - if (exited) { - if (death_event.data & NOTE_EXIT_MEMORY) - DNBProcessSetExitInfo(child_pid, "Terminated due to memory issue"); - else if (death_event.data & NOTE_EXIT_DECRYPTFAIL) - DNBProcessSetExitInfo(child_pid, "Terminated due to decrypt failure"); - else if (death_event.data & NOTE_EXIT_CSERROR) - DNBProcessSetExitInfo(child_pid, - "Terminated due to code signing error"); - - DNBLogThreadedIf( - LOG_PROCESS, - "waitpid_process_thread (): setting exit status for pid = %i to %i", - child_pid, exit_status); - DNBProcessSetExitStatus(child_pid, status); - return NULL; - } - } - } -} - -static bool spawn_kqueue_thread(pid_t pid) { - pthread_t thread; - int kq_id; - - kq_id = kqueue(); - if (kq_id == -1) { - DNBLogError("Could not get kqueue for pid = %i.", pid); - return false; - } - - struct kevent reg_event; - - EV_SET(®_event, pid, EVFILT_PROC, EV_ADD, - NOTE_EXIT | NOTE_EXITSTATUS | NOTE_EXIT_DETAIL, 0, NULL); - // Register the event: - int result = kevent(kq_id, ®_event, 1, NULL, 0, NULL); - if (result != 0) { - DNBLogError( - "Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, - result); - return false; - } - - int ret = - ::pthread_create(&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id); - - // pthread_create returns 0 if successful - if (ret == 0) { - ::pthread_detach(thread); - return true; - } - return false; -} -#endif // #if USE_KQUEUE - -static void *waitpid_thread(void *arg) { - const pid_t pid = (pid_t)(intptr_t)arg; - int status; - -#if defined(__APPLE__) - pthread_setname_np("waitpid thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } -#endif -#endif - - while (1) { - pid_t child_pid = waitpid(pid, &status, 0); - DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, " - "&status, 0) => %i, status = %i, errno = %i", - pid, child_pid, status, errno); - - if (child_pid < 0) { - if (errno == EINTR) - continue; - break; - } else { - if (WIFSTOPPED(status)) { - continue; - } else // if (WIFEXITED(status) || WIFSIGNALED(status)) - { - DNBLogThreadedIf( - LOG_PROCESS, - "waitpid_thread (): setting exit status for pid = %i to %i", - child_pid, status); - DNBProcessSetExitStatus(child_pid, status); - return NULL; - } - } - } - - // We should never exit as long as our child process is alive, so if we - // do something else went wrong and we should exit... - DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting " - "exit status to an invalid value (-1) for pid " - "%i", - pid); - DNBProcessSetExitStatus(pid, -1); - return NULL; -} -static bool spawn_waitpid_thread(pid_t pid) { -#ifdef USE_KQUEUE - bool success = spawn_kqueue_thread(pid); - if (success) - return true; -#endif - - pthread_t thread; - int ret = - ::pthread_create(&thread, NULL, waitpid_thread, (void *)(intptr_t)pid); - // pthread_create returns 0 if successful - if (ret == 0) { - ::pthread_detach(thread); - return true; - } - return false; -} - -nub_process_t DNBProcessLaunch( - const char *path, char const *argv[], const char *envp[], - const char *working_directory, // NULL => don't change, non-NULL => set - // working directory for inferior to this - const char *stdin_path, const char *stdout_path, const char *stderr_path, - bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, - const char *event_data, char *err_str, size_t err_len) { - DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, " - "working_dir=%s, stdin=%s, stdout=%s, " - "stderr=%s, no-stdio=%i, launch_flavor = %u, " - "disable_aslr = %d, err = %p, err_len = " - "%llu) called...", - __FUNCTION__, path, static_cast<void *>(argv), - static_cast<void *>(envp), working_directory, stdin_path, - stdout_path, stderr_path, no_stdio, launch_flavor, - disable_aslr, static_cast<void *>(err_str), - static_cast<uint64_t>(err_len)); - - if (err_str && err_len > 0) - err_str[0] = '\0'; - struct stat path_stat; - if (::stat(path, &path_stat) == -1) { - char stat_error[256]; - ::strerror_r(errno, stat_error, sizeof(stat_error)); - snprintf(err_str, err_len, "%s (%s)", stat_error, path); - return INVALID_NUB_PROCESS; - } - - MachProcessSP processSP(new MachProcess); - if (processSP.get()) { - DNBError launch_err; - pid_t pid = processSP->LaunchForDebug(path, argv, envp, working_directory, - stdin_path, stdout_path, stderr_path, - no_stdio, launch_flavor, disable_aslr, - event_data, launch_err); - if (err_str) { - *err_str = '\0'; - if (launch_err.Fail()) { - const char *launch_err_str = launch_err.AsString(); - if (launch_err_str) { - strlcpy(err_str, launch_err_str, err_len - 1); - err_str[err_len - 1] = - '\0'; // Make sure the error string is terminated - } - } - } - - DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid); - - if (pid != INVALID_NUB_PROCESS) { - // Spawn a thread to reap our child inferior process... - spawn_waitpid_thread(pid); - - if (processSP->Task().TaskPortForProcessID(launch_err) == TASK_NULL) { - // We failed to get the task for our process ID which is bad. - // Kill our process otherwise it will be stopped at the entry - // point and get reparented to someone else and never go away. - DNBLog("Could not get task port for process, sending SIGKILL and " - "exiting."); - kill(SIGKILL, pid); - - if (err_str && err_len > 0) { - if (launch_err.AsString()) { - ::snprintf(err_str, err_len, - "failed to get the task for process %i (%s)", pid, - launch_err.AsString()); - } else { - ::snprintf(err_str, err_len, - "failed to get the task for process %i", pid); - } - } - } else { - bool res = AddProcessToMap(pid, processSP); - UNUSED_IF_ASSERT_DISABLED(res); - assert(res && "Couldn't add process to map!"); - return pid; - } - } - } - return INVALID_NUB_PROCESS; -} - -// If there is one process with a given name, return the pid for that process. -nub_process_t DNBProcessGetPIDByName(const char *name) { - std::vector<struct kinfo_proc> matching_proc_infos; - size_t num_matching_proc_infos = - GetAllInfosMatchingName(name, matching_proc_infos); - if (num_matching_proc_infos == 1) { - return matching_proc_infos[0].kp_proc.p_pid; - } - return INVALID_NUB_PROCESS; -} - -nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, - char *err_str, size_t err_len) { - if (err_str && err_len > 0) - err_str[0] = '\0'; - std::vector<struct kinfo_proc> matching_proc_infos; - size_t num_matching_proc_infos = - GetAllInfosMatchingName(name, matching_proc_infos); - if (num_matching_proc_infos == 0) { - DNBLogError("error: no processes match '%s'\n", name); - return INVALID_NUB_PROCESS; - } else if (num_matching_proc_infos > 1) { - DNBLogError("error: %llu processes match '%s':\n", - (uint64_t)num_matching_proc_infos, name); - size_t i; - for (i = 0; i < num_matching_proc_infos; ++i) - DNBLogError("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, - matching_proc_infos[i].kp_proc.p_comm); - return INVALID_NUB_PROCESS; - } - - return DNBProcessAttach(matching_proc_infos[0].kp_proc.p_pid, timeout, - err_str, err_len); -} - -nub_process_t DNBProcessAttach(nub_process_t attach_pid, - struct timespec *timeout, char *err_str, - size_t err_len) { - if (err_str && err_len > 0) - err_str[0] = '\0'; - - pid_t pid = INVALID_NUB_PROCESS; - MachProcessSP processSP(new MachProcess); - if (processSP.get()) { - DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", - attach_pid); - pid = processSP->AttachForDebug(attach_pid, err_str, err_len); - - if (pid != INVALID_NUB_PROCESS) { - bool res = AddProcessToMap(pid, processSP); - UNUSED_IF_ASSERT_DISABLED(res); - assert(res && "Couldn't add process to map!"); - spawn_waitpid_thread(pid); - } - } - - while (pid != INVALID_NUB_PROCESS) { - // Wait for process to start up and hit entry point - DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged, true, " - "INFINITE)...", - __FUNCTION__, pid); - nub_event_t set_events = - DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged, - true, timeout); - - DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged, true, " - "INFINITE) => 0x%8.8x", - __FUNCTION__, pid, set_events); - - if (set_events == 0) { - if (err_str && err_len > 0) - snprintf(err_str, err_len, "operation timed out"); - pid = INVALID_NUB_PROCESS; - } else { - if (set_events & (eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged)) { - nub_state_t pid_state = DNBProcessGetState(pid); - DNBLogThreadedIf( - LOG_PROCESS, - "%s process %4.4x state changed (eEventProcessStateChanged): %s", - __FUNCTION__, pid, DNBStateAsString(pid_state)); - - switch (pid_state) { - case eStateInvalid: - case eStateUnloaded: - case eStateAttaching: - case eStateLaunching: - case eStateSuspended: - break; // Ignore - - case eStateRunning: - case eStateStepping: - // Still waiting to stop at entry point... - break; - - case eStateStopped: - case eStateCrashed: - return pid; - - case eStateDetached: - case eStateExited: - if (err_str && err_len > 0) - snprintf(err_str, err_len, "process exited"); - return INVALID_NUB_PROCESS; - } - } - - DNBProcessResetEvents(pid, set_events); - } - } - - return INVALID_NUB_PROCESS; -} - -size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos) { - size_t size = 0; - int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; - u_int namelen = sizeof(name) / sizeof(int); - int err; - - // Try to find out how many processes are around so we can - // size the buffer appropriately. sysctl's man page specifically suggests - // this approach, and says it returns a bit larger size than needed to - // handle any new processes created between then and now. - - err = ::sysctl(name, namelen, NULL, &size, NULL, 0); - - if ((err < 0) && (err != ENOMEM)) { - proc_infos.clear(); - perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)"); - return 0; - } - - // Increase the size of the buffer by a few processes in case more have - // been spawned - proc_infos.resize(size / sizeof(struct kinfo_proc)); - size = proc_infos.size() * - sizeof(struct kinfo_proc); // Make sure we don't exceed our resize... - err = ::sysctl(name, namelen, &proc_infos[0], &size, NULL, 0); - if (err < 0) { - proc_infos.clear(); - return 0; - } - - // Trim down our array to fit what we actually got back - proc_infos.resize(size / sizeof(struct kinfo_proc)); - return proc_infos.size(); -} - -static size_t -GetAllInfosMatchingName(const char *full_process_name, - std::vector<struct kinfo_proc> &matching_proc_infos) { - - matching_proc_infos.clear(); - if (full_process_name && full_process_name[0]) { - // We only get the process name, not the full path, from the proc_info. So - // just take the - // base name of the process name... - const char *process_name; - process_name = strrchr(full_process_name, '/'); - if (process_name == NULL) - process_name = full_process_name; - else - process_name++; - - const size_t process_name_len = strlen(process_name); - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = GetAllInfos(proc_infos); - if (num_proc_infos > 0) { - uint32_t i; - for (i = 0; i < num_proc_infos; i++) { - // Skip zombie processes and processes with unset status - if (proc_infos[i].kp_proc.p_stat == 0 || - proc_infos[i].kp_proc.p_stat == SZOMB) - continue; - - // Check for process by name. We only check the first MAXCOMLEN - // chars as that is all that kp_proc.p_comm holds. - - if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, - MAXCOMLEN) == 0) { - if (process_name_len > MAXCOMLEN) { - // We found a matching process name whose first MAXCOMLEN - // characters match, but there is more to the name than - // this. We need to get the full process name. Use proc_pidpath, - // which will get - // us the full path to the executed process. - - char proc_path_buf[PATH_MAX]; - - int return_val = proc_pidpath(proc_infos[i].kp_proc.p_pid, - proc_path_buf, PATH_MAX); - if (return_val > 0) { - // Okay, now search backwards from that to see if there is a - // slash in the name. Note, even though we got all the args we - // don't care - // because the list data is just a bunch of concatenated null - // terminated strings - // so strrchr will start from the end of argv0. - - const char *argv_basename = strrchr(proc_path_buf, '/'); - if (argv_basename) { - // Skip the '/' - ++argv_basename; - } else { - // We didn't find a directory delimiter in the process argv[0], - // just use what was in there - argv_basename = proc_path_buf; - } - - if (argv_basename) { - if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0) { - matching_proc_infos.push_back(proc_infos[i]); - } - } - } - } else { - // We found a matching process, add it to our list - matching_proc_infos.push_back(proc_infos[i]); - } - } - } - } - } - // return the newly added matches. - return matching_proc_infos.size(); -} - -nub_process_t DNBProcessAttachWait( - const char *waitfor_process_name, nub_launch_flavor_t launch_flavor, - bool ignore_existing, struct timespec *timeout_abstime, - useconds_t waitfor_interval, char *err_str, size_t err_len, - DNBShouldCancelCallback should_cancel_callback, void *callback_data) { - DNBError prepare_error; - std::vector<struct kinfo_proc> exclude_proc_infos; - size_t num_exclude_proc_infos; - - // If the PrepareForAttach returns a valid token, use MachProcess to check - // for the process, otherwise scan the process table. - - const void *attach_token = MachProcess::PrepareForAttach( - waitfor_process_name, launch_flavor, true, prepare_error); - - if (prepare_error.Fail()) { - DNBLogError("Error in PrepareForAttach: %s", prepare_error.AsString()); - return INVALID_NUB_PROCESS; - } - - if (attach_token == NULL) { - if (ignore_existing) - num_exclude_proc_infos = - GetAllInfosMatchingName(waitfor_process_name, exclude_proc_infos); - else - num_exclude_proc_infos = 0; - } - - DNBLogThreadedIf(LOG_PROCESS, "Waiting for '%s' to appear...\n", - waitfor_process_name); - - // Loop and try to find the process by name - nub_process_t waitfor_pid = INVALID_NUB_PROCESS; - - while (waitfor_pid == INVALID_NUB_PROCESS) { - if (attach_token != NULL) { - nub_process_t pid; - pid = MachProcess::CheckForProcess(attach_token, launch_flavor); - if (pid != INVALID_NUB_PROCESS) { - waitfor_pid = pid; - break; - } - } else { - - // Get the current process list, and check for matches that - // aren't in our original list. If anyone wants to attach - // to an existing process by name, they should do it with - // --attach=PROCNAME. Else we will wait for the first matching - // process that wasn't in our exclusion list. - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = - GetAllInfosMatchingName(waitfor_process_name, proc_infos); - for (size_t i = 0; i < num_proc_infos; i++) { - nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid; - for (size_t j = 0; j < num_exclude_proc_infos; j++) { - if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid) { - // This process was in our exclusion list, don't use it. - curr_pid = INVALID_NUB_PROCESS; - break; - } - } - - // If we didn't find CURR_PID in our exclusion list, then use it. - if (curr_pid != INVALID_NUB_PROCESS) { - // We found our process! - waitfor_pid = curr_pid; - break; - } - } - } - - // If we haven't found our process yet, check for a timeout - // and then sleep for a bit until we poll again. - if (waitfor_pid == INVALID_NUB_PROCESS) { - if (timeout_abstime != NULL) { - // Check to see if we have a waitfor-duration option that - // has timed out? - if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime)) { - if (err_str && err_len > 0) - snprintf(err_str, err_len, "operation timed out"); - DNBLogError("error: waiting for process '%s' timed out.\n", - waitfor_process_name); - return INVALID_NUB_PROCESS; - } - } - - // Call the should cancel callback as well... - - if (should_cancel_callback != NULL && - should_cancel_callback(callback_data)) { - DNBLogThreadedIf( - LOG_PROCESS, - "DNBProcessAttachWait cancelled by should_cancel callback."); - waitfor_pid = INVALID_NUB_PROCESS; - break; - } - - ::usleep(waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again - } - } - - if (waitfor_pid != INVALID_NUB_PROCESS) { - DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n", - waitfor_process_name, waitfor_pid); - waitfor_pid = - DNBProcessAttach(waitfor_pid, timeout_abstime, err_str, err_len); - } - - bool success = waitfor_pid != INVALID_NUB_PROCESS; - MachProcess::CleanupAfterAttach(attach_token, launch_flavor, success, - prepare_error); - - return waitfor_pid; -} - -nub_bool_t DNBProcessDetach(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - const bool remove = true; - DNBLogThreaded( - "Disabling breakpoints and watchpoints, and detaching from %d.", pid); - procSP->DisableAllBreakpoints(remove); - procSP->DisableAllWatchpoints(remove); - return procSP->Detach(); - } - return false; -} - -nub_bool_t DNBProcessKill(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->Kill(); - } - return false; -} - -nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->Signal(signal); - } - return false; -} - -nub_bool_t DNBProcessInterrupt(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Interrupt(); - return false; -} - -nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - // FIXME: Do something with the error... - DNBError send_error; - return procSP->SendEvent(event, send_error); - } - return false; -} - -nub_bool_t DNBProcessIsAlive(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return MachTask::IsValid(procSP->Task().TaskPort()); - } - return eStateInvalid; -} - -//---------------------------------------------------------------------- -// Process and Thread state information -//---------------------------------------------------------------------- -nub_state_t DNBProcessGetState(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetState(); - } - return eStateInvalid; -} - -//---------------------------------------------------------------------- -// Process and Thread state information -//---------------------------------------------------------------------- -nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetExitStatus(status); - } - return false; -} - -nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SetExitStatus(status); - return true; - } - return false; -} - -const char *DNBProcessGetExitInfo(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetExitInfo(); - } - return NULL; -} - -nub_bool_t DNBProcessSetExitInfo(nub_process_t pid, const char *info) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SetExitInfo(info); - return true; - } - return false; -} - -const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->ThreadGetName(tid); - return NULL; -} - -nub_bool_t -DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid, - thread_identifier_info_data_t *ident_info) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info); - return false; -} - -nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->ThreadGetState(tid); - } - return eStateInvalid; -} - -const char *DNBStateAsString(nub_state_t state) { - switch (state) { - case eStateInvalid: - return "Invalid"; - case eStateUnloaded: - return "Unloaded"; - case eStateAttaching: - return "Attaching"; - case eStateLaunching: - return "Launching"; - case eStateStopped: - return "Stopped"; - case eStateRunning: - return "Running"; - case eStateStepping: - return "Stepping"; - case eStateCrashed: - return "Crashed"; - case eStateDetached: - return "Detached"; - case eStateExited: - return "Exited"; - case eStateSuspended: - return "Suspended"; - } - return "nub_state_t ???"; -} - -Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid, - nub_thread_t tid, - bool &timed_out) { - Genealogy::ThreadActivitySP thread_activity_sp; - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - thread_activity_sp = procSP->GetGenealogyInfoForThread(tid, timed_out); - return thread_activity_sp; -} - -Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid, - size_t idx) { - Genealogy::ProcessExecutableInfoSP image_info_sp; - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - image_info_sp = procSP->GetGenealogyImageInfo(idx); - } - return image_info_sp; -} - -ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid, - nub_addr_t tsd, - uint64_t dti_qos_class_index) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetRequestedQoS(tid, tsd, dti_qos_class_index); - } - return ThreadInfo::QoS(); -} - -nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetPThreadT(tid); - } - return INVALID_NUB_ADDRESS; -} - -nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetDispatchQueueT(tid); - } - return INVALID_NUB_ADDRESS; -} - -nub_addr_t -DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid, - uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetTSDAddressForThread( - tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, - plo_pthread_tsd_entry_size); - } - return INVALID_NUB_ADDRESS; -} - -JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos( - nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetLoadedDynamicLibrariesInfos(pid, image_list_address, - image_count); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetAllLoadedLibrariesInfos(pid); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP -DNBGetLibrariesInfoForAddresses(nub_process_t pid, - std::vector<uint64_t> &macho_addresses) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetLibrariesInfoForAddresses(pid, macho_addresses); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->GetSharedCacheInfo(pid); - } - return JSONGenerator::ObjectSP(); -} - -const char *DNBProcessGetExecutablePath(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->Path(); - } - return NULL; -} - -nub_size_t DNBProcessGetArgumentCount(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->ArgumentCount(); - } - return 0; -} - -const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->ArgumentAtIndex(idx); - } - return NULL; -} - -//---------------------------------------------------------------------- -// Execution control -//---------------------------------------------------------------------- -nub_bool_t DNBProcessResume(nub_process_t pid, - const DNBThreadResumeAction *actions, - size_t num_actions) { - DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - DNBThreadResumeActions thread_actions(actions, num_actions); - - // Below we add a default thread plan just in case one wasn't - // provided so all threads always know what they were supposed to do - if (thread_actions.IsEmpty()) { - // No thread plans were given, so the default it to run all threads - thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); - } else { - // Some thread plans were given which means anything that wasn't - // specified should remain stopped. - thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - } - return procSP->Resume(thread_actions); - } - return false; -} - -nub_bool_t DNBProcessHalt(nub_process_t pid) { - DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Signal(SIGSTOP); - return false; -} -// -// nub_bool_t -// DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step) -//{ -// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", -// __FUNCTION__, pid, tid, (uint32_t)step); -// MachProcessSP procSP; -// if (GetProcessSP (pid, procSP)) -// { -// return procSP->Resume(tid, step, 0); -// } -// return false; -//} -// -// nub_bool_t -// DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t -// step, int signal) -//{ -// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, -// signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal); -// MachProcessSP procSP; -// if (GetProcessSP (pid, procSP)) -// { -// return procSP->Resume(tid, step, signal); -// } -// return false; -//} - -nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask, - bool wait_for_set, - struct timespec *timeout) { - nub_event_t result = 0; - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - if (wait_for_set) - result = procSP->Events().WaitForSetEvents(event_mask, timeout); - else - result = procSP->Events().WaitForEventsToReset(event_mask, timeout); - } - return result; -} - -void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - procSP->Events().ResetEvents(event_mask); -} - -// Breakpoints -nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, - nub_bool_t hardware) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->CreateBreakpoint(addr, size, hardware) != NULL; - return false; -} - -nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->DisableBreakpoint(addr, true); - return false; // Failed -} - -//---------------------------------------------------------------------- -// Watchpoints -//---------------------------------------------------------------------- -nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, - uint32_t watch_flags, nub_bool_t hardware) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL; - return false; -} - -nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->DisableWatchpoint(addr, true); - return false; // Failed -} - -//---------------------------------------------------------------------- -// Return the number of supported hardware watchpoints. -//---------------------------------------------------------------------- -uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetNumSupportedHardwareWatchpoints(); - return 0; -} - -//---------------------------------------------------------------------- -// Read memory in the address space of process PID. This call will take -// care of setting and restoring permissions and breaking up the memory -// read into multiple chunks as required. -// -// RETURNS: number of bytes actually read -//---------------------------------------------------------------------- -nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr, - nub_size_t size, void *buf) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->ReadMemory(addr, size, buf); - return 0; -} - -uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr, - nub_size_t integer_size, - uint64_t fail_value) { - union Integers { - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - }; - - if (integer_size <= sizeof(uint64_t)) { - Integers ints; - if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size) { - switch (integer_size) { - case 1: - return ints.u8; - case 2: - return ints.u16; - case 3: - return ints.u32 & 0xffffffu; - case 4: - return ints.u32; - case 5: - return ints.u32 & 0x000000ffffffffffull; - case 6: - return ints.u32 & 0x0000ffffffffffffull; - case 7: - return ints.u32 & 0x00ffffffffffffffull; - case 8: - return ints.u64; - } - } - } - return fail_value; -} - -nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid, nub_addr_t addr) { - cpu_type_t cputype = DNBProcessGetCPUType(pid); - if (cputype) { - const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4; - return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0); - } - return 0; -} - -std::string DNBProcessMemoryReadCString(nub_process_t pid, nub_addr_t addr) { - std::string cstr; - char buffer[256]; - const nub_size_t max_buffer_cstr_length = sizeof(buffer) - 1; - buffer[max_buffer_cstr_length] = '\0'; - nub_size_t length = 0; - nub_addr_t curr_addr = addr; - do { - nub_size_t bytes_read = - DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer); - if (bytes_read == 0) - break; - length = strlen(buffer); - cstr.append(buffer, length); - curr_addr += length; - } while (length == max_buffer_cstr_length); - return cstr; -} - -std::string DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr, - nub_size_t fixed_length) { - std::string cstr; - char buffer[fixed_length + 1]; - buffer[fixed_length] = '\0'; - nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer); - if (bytes_read > 0) - cstr.assign(buffer); - return cstr; -} - -//---------------------------------------------------------------------- -// Write memory to the address space of process PID. This call will take -// care of setting and restoring permissions and breaking up the memory -// write into multiple chunks as required. -// -// RETURNS: number of bytes actually written -//---------------------------------------------------------------------- -nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr, - nub_size_t size, const void *buf) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->WriteMemory(addr, size, buf); - return 0; -} - -nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size, - uint32_t permissions) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Task().AllocateMemory(size, permissions); - return 0; -} - -nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid, nub_addr_t addr) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Task().DeallocateMemory(addr); - return 0; -} - -//---------------------------------------------------------------------- -// Find attributes of the memory region that contains ADDR for process PID, -// if possible, and return a string describing those attributes. -// -// Returns 1 if we could find attributes for this region and OUTBUF can -// be sent to the remote debugger. -// -// Returns 0 if we couldn't find the attributes for a region of memory at -// that address and OUTBUF should not be sent. -// -// Returns -1 if this platform cannot look up information about memory regions -// or if we do not yet have a valid launched process. -// -//---------------------------------------------------------------------- -int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr, - DNBRegionInfo *region_info) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Task().GetMemoryRegionInfo(addr, region_info); - - return -1; -} - -std::string DNBProcessGetProfileData(nub_process_t pid, - DNBProfileDataScanType scanType) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->Task().GetProfileData(scanType); - - return std::string(""); -} - -nub_bool_t DNBProcessSetEnableAsyncProfiling(nub_process_t pid, - nub_bool_t enable, - uint64_t interval_usec, - DNBProfileDataScanType scan_type) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type); - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -// Get the number of threads for the specified process. -//---------------------------------------------------------------------- -nub_size_t DNBProcessGetNumThreads(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetNumThreads(); - return 0; -} - -//---------------------------------------------------------------------- -// Get the thread ID of the current thread. -//---------------------------------------------------------------------- -nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetCurrentThread(); - return 0; -} - -//---------------------------------------------------------------------- -// Get the mach port number of the current thread. -//---------------------------------------------------------------------- -nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetCurrentThreadMachPort(); - return 0; -} - -//---------------------------------------------------------------------- -// Change the current thread. -//---------------------------------------------------------------------- -nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->SetCurrentThread(tid); - return INVALID_NUB_THREAD; -} - -//---------------------------------------------------------------------- -// Dump a string describing a thread's stop reason to the specified file -// handle -//---------------------------------------------------------------------- -nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid, - struct DNBThreadStopInfo *stop_info) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadStoppedReason(tid, stop_info); - return false; -} - -//---------------------------------------------------------------------- -// Return string description for the specified thread. -// -// RETURNS: NULL if the thread isn't valid, else a NULL terminated C -// string from a static buffer that must be copied prior to subsequent -// calls. -//---------------------------------------------------------------------- -const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadInfo(tid); - return NULL; -} - -//---------------------------------------------------------------------- -// Get the thread ID given a thread index. -//---------------------------------------------------------------------- -nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid, size_t thread_idx) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadAtIndex(thread_idx); - return INVALID_NUB_THREAD; -} - -//---------------------------------------------------------------------- -// Do whatever is needed to sync the thread's register state with it's kernel -// values. -//---------------------------------------------------------------------- -nub_bool_t DNBProcessSyncThreadState(nub_process_t pid, nub_thread_t tid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->SyncThreadState(tid); - return false; -} - -nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) { - MachProcessSP procSP; - DNBError err; - if (GetProcessSP(pid, procSP)) - return procSP->Task().GetDYLDAllImageInfosAddress(err); - return INVALID_NUB_ADDRESS; -} - -nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SharedLibrariesUpdated(); - return true; - } - return false; -} - -const char *DNBGetDeploymentInfo(nub_process_t pid, - const struct load_command& lc, - uint64_t load_command_address, - uint32_t& major_version, - uint32_t& minor_version, - uint32_t& patch_version) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetDeploymentInfo(lc, load_command_address, - major_version, minor_version, - patch_version); - return nullptr; -} - - -//---------------------------------------------------------------------- -// Get the current shared library information for a process. Only return -// the shared libraries that have changed since the last shared library -// state changed event if only_changed is non-zero. -//---------------------------------------------------------------------- -nub_size_t -DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed, - struct DNBExecutableImageInfo **image_infos) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->CopyImageInfos(image_infos, only_changed); - - // If we have no process, then return NULL for the shared library info - // and zero for shared library count - *image_infos = NULL; - return 0; -} - -uint32_t DNBGetRegisterCPUType() { - return DNBArchProtocol::GetRegisterCPUType(); -} -//---------------------------------------------------------------------- -// Get the register set information for a specific thread. -//---------------------------------------------------------------------- -const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets) { - return DNBArchProtocol::GetRegisterSetInfo(num_reg_sets); -} - -//---------------------------------------------------------------------- -// Read a register value by register set and register index. -//---------------------------------------------------------------------- -nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid, - uint32_t set, uint32_t reg, - DNBRegisterValue *value) { - MachProcessSP procSP; - ::bzero(value, sizeof(DNBRegisterValue)); - if (GetProcessSP(pid, procSP)) { - if (tid != INVALID_NUB_THREAD) - return procSP->GetRegisterValue(tid, set, reg, value); - } - return false; -} - -nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid, - uint32_t set, uint32_t reg, - const DNBRegisterValue *value) { - if (tid != INVALID_NUB_THREAD) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->SetRegisterValue(tid, set, reg, value); - } - return false; -} - -nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid, - void *buf, size_t buf_len) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - if (tid != INVALID_NUB_THREAD) - return procSP->GetThreadList().GetRegisterContext(tid, buf, buf_len); - } - ::bzero(buf, buf_len); - return 0; -} - -nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid, - const void *buf, size_t buf_len) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - if (tid != INVALID_NUB_THREAD) - return procSP->GetThreadList().SetRegisterContext(tid, buf, buf_len); - } - return 0; -} - -uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid) { - if (tid != INVALID_NUB_THREAD) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadList().SaveRegisterState(tid); - } - return 0; -} -nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid, - uint32_t save_id) { - if (tid != INVALID_NUB_THREAD) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetThreadList().RestoreRegisterState(tid, save_id); - } - return false; -} - -//---------------------------------------------------------------------- -// Read a register value by name. -//---------------------------------------------------------------------- -nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid, - uint32_t reg_set, - const char *reg_name, - DNBRegisterValue *value) { - MachProcessSP procSP; - ::bzero(value, sizeof(DNBRegisterValue)); - if (GetProcessSP(pid, procSP)) { - const struct DNBRegisterSetInfo *set_info; - nub_size_t num_reg_sets = 0; - set_info = DNBGetRegisterSetInfo(&num_reg_sets); - if (set_info) { - uint32_t set = reg_set; - uint32_t reg; - if (set == REGISTER_SET_ALL) { - for (set = 1; set < num_reg_sets; ++set) { - for (reg = 0; reg < set_info[set].num_registers; ++reg) { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) - return procSP->GetRegisterValue(tid, set, reg, value); - } - } - } else { - for (reg = 0; reg < set_info[set].num_registers; ++reg) { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) - return procSP->GetRegisterValue(tid, set, reg, value); - } - } - } - } - return false; -} - -//---------------------------------------------------------------------- -// Read a register set and register number from the register name. -//---------------------------------------------------------------------- -nub_bool_t DNBGetRegisterInfoByName(const char *reg_name, - DNBRegisterInfo *info) { - const struct DNBRegisterSetInfo *set_info; - nub_size_t num_reg_sets = 0; - set_info = DNBGetRegisterSetInfo(&num_reg_sets); - if (set_info) { - uint32_t set, reg; - for (set = 1; set < num_reg_sets; ++set) { - for (reg = 0; reg < set_info[set].num_registers; ++reg) { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) { - *info = set_info[set].registers[reg]; - return true; - } - } - } - - for (set = 1; set < num_reg_sets; ++set) { - uint32_t reg; - for (reg = 0; reg < set_info[set].num_registers; ++reg) { - if (set_info[set].registers[reg].alt == NULL) - continue; - - if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0) { - *info = set_info[set].registers[reg]; - return true; - } - } - } - } - - ::bzero(info, sizeof(DNBRegisterInfo)); - return false; -} - -//---------------------------------------------------------------------- -// Set the name to address callback function that this nub can use -// for any name to address lookups that are needed. -//---------------------------------------------------------------------- -nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid, - DNBCallbackNameToAddress callback, - void *baton) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SetNameToAddressCallback(callback, baton); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// Set the name to address callback function that this nub can use -// for any name to address lookups that are needed. -//---------------------------------------------------------------------- -nub_bool_t DNBProcessSetSharedLibraryInfoCallback( - nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, - void *baton) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - procSP->SetSharedLibraryInfoCallback(callback, baton); - return true; - } - return false; -} - -nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name, - const char *shlib) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) { - return procSP->LookupSymbol(name, shlib); - } - return INVALID_NUB_ADDRESS; -} - -nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf, - nub_size_t buf_size) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetAvailableSTDOUT(buf, buf_size); - return 0; -} - -nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf, - nub_size_t buf_size) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetAvailableSTDERR(buf, buf_size); - return 0; -} - -nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf, - nub_size_t buf_size) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetAsyncProfileData(buf, buf_size); - return 0; -} - -DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid) { - return DarwinLogCollector::GetEventsForProcess(pid); -} - -nub_size_t DNBProcessGetStopCount(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->StopCount(); - return 0; -} - -uint32_t DNBProcessGetCPUType(nub_process_t pid) { - MachProcessSP procSP; - if (GetProcessSP(pid, procSP)) - return procSP->GetCPUType(); - return 0; -} - -nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path, - size_t resolved_path_size) { - if (path == NULL || path[0] == '\0') - return false; - - char max_path[PATH_MAX]; - std::string result; - CFString::GlobPath(path, result); - - if (result.empty()) - result = path; - - struct stat path_stat; - if (::stat(path, &path_stat) == 0) { - if ((path_stat.st_mode & S_IFMT) == S_IFDIR) { - CFBundle bundle(path); - CFReleaser<CFURLRef> url(bundle.CopyExecutableURL()); - if (url.get()) { - if (::CFURLGetFileSystemRepresentation( - url.get(), true, (UInt8 *)resolved_path, resolved_path_size)) - return true; - } - } - } - - if (realpath(path, max_path)) { - // Found the path relatively... - ::strlcpy(resolved_path, max_path, resolved_path_size); - return strlen(resolved_path) + 1 < resolved_path_size; - } else { - // Not a relative path, check the PATH environment variable if the - const char *PATH = getenv("PATH"); - if (PATH) { - const char *curr_path_start = PATH; - const char *curr_path_end; - while (curr_path_start && *curr_path_start) { - curr_path_end = strchr(curr_path_start, ':'); - if (curr_path_end == NULL) { - result.assign(curr_path_start); - curr_path_start = NULL; - } else if (curr_path_end > curr_path_start) { - size_t len = curr_path_end - curr_path_start; - result.assign(curr_path_start, len); - curr_path_start += len + 1; - } else - break; - - result += '/'; - result += path; - struct stat s; - if (stat(result.c_str(), &s) == 0) { - ::strlcpy(resolved_path, result.c_str(), resolved_path_size); - return result.size() + 1 < resolved_path_size; - } - } - } - } - return false; -} - -bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch) { - return MachProcess::GetOSVersionNumbers(major, minor, patch); -} - -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 -} - -void DNBTerminate() {} - -nub_bool_t DNBSetArchitecture(const char *arch) { - if (arch && arch[0]) { - if (strcasecmp(arch, "i386") == 0) - return DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); - else if ((strcasecmp(arch, "x86_64") == 0) || - (strcasecmp(arch, "x86_64h") == 0)) - return DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); - else if (strstr(arch, "arm64") == arch || strstr(arch, "armv8") == arch || - strstr(arch, "aarch64") == arch) - return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); - else if (strstr(arch, "arm") == arch) - return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); - } - return false; -} diff --git a/tools/debugserver/source/DNB.h b/tools/debugserver/source/DNB.h deleted file mode 100644 index bce2c6abafd1..000000000000 --- a/tools/debugserver/source/DNB.h +++ /dev/null @@ -1,247 +0,0 @@ -//===-- DNB.h ---------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/23/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNB_h__ -#define __DNB_h__ - -#include "DNBDefs.h" -#include "JSONGenerator.h" -#include "MacOSX/DarwinLog/DarwinLogEvent.h" -#include "MacOSX/Genealogy.h" -#include "MacOSX/ThreadInfo.h" -#include <mach/thread_info.h> -#include <string> - -#define DNB_EXPORT __attribute__((visibility("default"))) - -#ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 ((cpu_type_t)12 | 0x01000000) -#endif - -typedef bool (*DNBShouldCancelCallback)(void *); - -void DNBInitialize(); -void DNBTerminate(); - -nub_bool_t DNBSetArchitecture(const char *arch); - -//---------------------------------------------------------------------- -// Process control -//---------------------------------------------------------------------- -nub_process_t DNBProcessLaunch( - const char *path, char const *argv[], const char *envp[], - const char *working_directory, // NULL => don't change, non-NULL => set - // working directory for inferior to this - const char *stdin_path, const char *stdout_path, const char *stderr_path, - bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, - const char *event_data, char *err_str, size_t err_len); - -nub_process_t DNBProcessGetPIDByName(const char *name); -nub_process_t DNBProcessAttach(nub_process_t pid, struct timespec *timeout, - char *err_str, size_t err_len); -nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, - char *err_str, size_t err_len); -nub_process_t -DNBProcessAttachWait(const char *wait_name, nub_launch_flavor_t launch_flavor, - bool ignore_existing, struct timespec *timeout, - useconds_t interval, char *err_str, size_t err_len, - DNBShouldCancelCallback should_cancel = NULL, - void *callback_data = NULL); -// Resume a process with exact instructions on what to do with each thread: -// - If no thread actions are supplied (actions is NULL or num_actions is zero), -// then all threads are continued. -// - If any thread actions are supplied, then each thread will do as it is told -// by the action. A default actions for any threads that don't have an -// explicit thread action can be made by making a thread action with a tid of -// INVALID_NUB_THREAD. If there is no default action, those threads will -// remain stopped. -nub_bool_t DNBProcessResume(nub_process_t pid, - const DNBThreadResumeAction *actions, - size_t num_actions) DNB_EXPORT; -nub_bool_t DNBProcessHalt(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessDetach(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) DNB_EXPORT; -nub_bool_t DNBProcessInterrupt(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessKill(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) DNB_EXPORT; -nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr, - nub_size_t size, void *buf) DNB_EXPORT; -uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr, - nub_size_t integer_size, - uint64_t fail_value) DNB_EXPORT; -nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid, - nub_addr_t addr) DNB_EXPORT; -std::string DNBProcessMemoryReadCString(nub_process_t pid, - nub_addr_t addr) DNB_EXPORT; -std::string -DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr, - nub_size_t fixed_length) DNB_EXPORT; -nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr, - nub_size_t size, const void *buf) DNB_EXPORT; -nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size, - uint32_t permissions) DNB_EXPORT; -nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid, - nub_addr_t addr) DNB_EXPORT; -int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr, - DNBRegionInfo *region_info) DNB_EXPORT; -std::string -DNBProcessGetProfileData(nub_process_t pid, - DNBProfileDataScanType scanType) DNB_EXPORT; -nub_bool_t -DNBProcessSetEnableAsyncProfiling(nub_process_t pid, nub_bool_t enable, - uint64_t interval_usec, - DNBProfileDataScanType scan_type) DNB_EXPORT; -DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid); - -//---------------------------------------------------------------------- -// Process status -//---------------------------------------------------------------------- -nub_bool_t DNBProcessIsAlive(nub_process_t pid) DNB_EXPORT; -nub_state_t DNBProcessGetState(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) DNB_EXPORT; -nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) DNB_EXPORT; -const char *DNBProcessGetExitInfo(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSetExitInfo(nub_process_t pid, - const char *info) DNB_EXPORT; -nub_size_t DNBProcessGetNumThreads(nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid, - nub_thread_t tid) DNB_EXPORT; -nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid, - nub_size_t thread_idx) DNB_EXPORT; -nub_bool_t DNBProcessSyncThreadState(nub_process_t pid, - nub_thread_t tid) DNB_EXPORT; -nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) DNB_EXPORT; -nub_size_t -DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed, - DNBExecutableImageInfo **image_infos) DNB_EXPORT; -const char *DNBGetDeploymentInfo(nub_process_t pid, - const struct load_command& lc, - uint64_t load_command_address, - uint32_t& major_version, - uint32_t& minor_version, - uint32_t& patch_version); -nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid, - DNBCallbackNameToAddress callback, - void *baton) DNB_EXPORT; -nub_bool_t DNBProcessSetSharedLibraryInfoCallback( - nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, - void *baton) DNB_EXPORT; -nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name, - const char *shlib) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf, - nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf, - nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf, - nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetStopCount(nub_process_t pid) DNB_EXPORT; -uint32_t DNBProcessGetCPUType(nub_process_t pid) DNB_EXPORT; - -//---------------------------------------------------------------------- -// Process executable and arguments -//---------------------------------------------------------------------- -const char *DNBProcessGetExecutablePath(nub_process_t pid); -const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx); -nub_size_t DNBProcessGetArgumentCount(nub_process_t pid); - -//---------------------------------------------------------------------- -// Process events -//---------------------------------------------------------------------- -nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask, - bool wait_for_set, - struct timespec *timeout); -void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask); - -//---------------------------------------------------------------------- -// Thread functions -//---------------------------------------------------------------------- -const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid); -nub_bool_t -DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid, - thread_identifier_info_data_t *ident_info); -nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid); -nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid, - uint32_t set, uint32_t reg, - DNBRegisterValue *value); -nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid, - uint32_t set, uint32_t reg, - const DNBRegisterValue *value); -nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid, - void *buf, size_t buf_len); -nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid, - const void *buf, size_t buf_len); -uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid); -nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid, - uint32_t save_id); -nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid, - uint32_t set, const char *name, - DNBRegisterValue *value); -nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid, - DNBThreadStopInfo *stop_info); -const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid); -Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid, - nub_thread_t tid, - bool &timed_out); -Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid, - size_t idx); -ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid, - nub_addr_t tsd, - uint64_t dti_qos_class_index); -nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid); -nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid); -nub_addr_t -DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid, - uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size); -JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos( - nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); -JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid); -JSONGenerator::ObjectSP -DNBGetLibrariesInfoForAddresses(nub_process_t pid, - std::vector<uint64_t> &macho_addresses); -JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid); - -// -//---------------------------------------------------------------------- -// Breakpoint functions -//---------------------------------------------------------------------- -nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, - nub_bool_t hardware); -nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr); - -//---------------------------------------------------------------------- -// Watchpoint functions -//---------------------------------------------------------------------- -nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, - uint32_t watch_flags, nub_bool_t hardware); -nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr); -uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid); - -uint32_t DNBGetRegisterCPUType(); -const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets); -nub_bool_t DNBGetRegisterInfoByName(const char *reg_name, - DNBRegisterInfo *info); - -//---------------------------------------------------------------------- -// Other static nub information calls. -//---------------------------------------------------------------------- -const char *DNBStateAsString(nub_state_t state); -nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path, - size_t resolved_path_size); -bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch); - -#endif diff --git a/tools/debugserver/source/DNBArch.cpp b/tools/debugserver/source/DNBArch.cpp deleted file mode 100644 index 1312bcf7dfdd..000000000000 --- a/tools/debugserver/source/DNBArch.cpp +++ /dev/null @@ -1,80 +0,0 @@ -//===-- DNBArch.cpp ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/24/07. -// -//===----------------------------------------------------------------------===// - -#include "DNBArch.h" -#include <assert.h> -#include <mach/mach.h> - -#include <map> - -#include "DNBLog.h" - -typedef std::map<uint32_t, DNBArchPluginInfo> CPUPluginInfoMap; - -static uint32_t g_current_cpu_type = 0; -CPUPluginInfoMap g_arch_plugins; - -static const DNBArchPluginInfo *GetArchInfo() { - CPUPluginInfoMap::const_iterator pos = - g_arch_plugins.find(g_current_cpu_type); - if (pos != g_arch_plugins.end()) - return &pos->second; - return NULL; -} - -uint32_t DNBArchProtocol::GetArchitecture() { return g_current_cpu_type; } - -bool DNBArchProtocol::SetArchitecture(uint32_t cpu_type) { - g_current_cpu_type = cpu_type; - bool result = g_arch_plugins.find(g_current_cpu_type) != g_arch_plugins.end(); - DNBLogThreadedIf( - LOG_PROCESS, - "DNBArchProtocol::SetDefaultArchitecture (cpu_type=0x%8.8x) => %i", - cpu_type, result); - return result; -} - -void DNBArchProtocol::RegisterArchPlugin(const DNBArchPluginInfo &arch_info) { - if (arch_info.cpu_type) - g_arch_plugins[arch_info.cpu_type] = arch_info; -} - -uint32_t DNBArchProtocol::GetRegisterCPUType() { - const DNBArchPluginInfo *arch_info = GetArchInfo(); - if (arch_info) - return arch_info->cpu_type; - return 0; -} - -const DNBRegisterSetInfo * -DNBArchProtocol::GetRegisterSetInfo(nub_size_t *num_reg_sets) { - const DNBArchPluginInfo *arch_info = GetArchInfo(); - if (arch_info) - return arch_info->GetRegisterSetInfo(num_reg_sets); - *num_reg_sets = 0; - return NULL; -} - -DNBArchProtocol *DNBArchProtocol::Create(MachThread *thread) { - const DNBArchPluginInfo *arch_info = GetArchInfo(); - if (arch_info) - return arch_info->Create(thread); - return NULL; -} - -const uint8_t *DNBArchProtocol::GetBreakpointOpcode(nub_size_t byte_size) { - const DNBArchPluginInfo *arch_info = GetArchInfo(); - if (arch_info) - return arch_info->GetBreakpointOpcode(byte_size); - return NULL; -} diff --git a/tools/debugserver/source/DNBArch.h b/tools/debugserver/source/DNBArch.h deleted file mode 100644 index 317da70e6422..000000000000 --- a/tools/debugserver/source/DNBArch.h +++ /dev/null @@ -1,127 +0,0 @@ -//===-- DNBArch.h -----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/24/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DebugNubArch_h__ -#define __DebugNubArch_h__ - -#include "DNBDefs.h" -#include "MacOSX/MachException.h" - -#include <mach/mach.h> -#include <stdio.h> - -struct DNBRegisterValue; -struct DNBRegisterSetInfo; -class DNBArchProtocol; -class MachThread; - -typedef DNBArchProtocol *(*DNBArchCallbackCreate)(MachThread *thread); -typedef const DNBRegisterSetInfo *(*DNBArchCallbackGetRegisterSetInfo)( - nub_size_t *num_reg_sets); -typedef const uint8_t *(*DNBArchCallbackGetBreakpointOpcode)( - nub_size_t byte_size); - -typedef struct DNBArchPluginInfoTag { - uint32_t cpu_type; - DNBArchCallbackCreate Create; - DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo; - DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode; -} DNBArchPluginInfo; - -class DNBArchProtocol { -public: - static DNBArchProtocol *Create(MachThread *thread); - - static uint32_t GetRegisterCPUType(); - - static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); - - static const uint8_t *GetBreakpointOpcode(nub_size_t byte_size); - - static void RegisterArchPlugin(const DNBArchPluginInfo &arch_info); - - static uint32_t GetArchitecture(); - - static bool SetArchitecture(uint32_t cpu_type); - - DNBArchProtocol() : m_save_id(0) {} - - virtual ~DNBArchProtocol() {} - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) = 0; - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) = 0; - virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) = 0; - virtual nub_size_t SetRegisterContext(const void *buf, - nub_size_t buf_len) = 0; - virtual uint32_t SaveRegisterState() = 0; - virtual bool RestoreRegisterState(uint32_t save_id) = 0; - - virtual kern_return_t GetRegisterState(int set, bool force) = 0; - virtual kern_return_t SetRegisterState(int set) = 0; - virtual bool RegisterSetStateIsValid(int set) const = 0; - - virtual uint64_t GetPC(uint64_t failValue) = 0; // Get program counter - virtual kern_return_t SetPC(uint64_t value) = 0; - virtual uint64_t GetSP(uint64_t failValue) = 0; // Get stack pointer - virtual void ThreadWillResume() = 0; - virtual bool ThreadDidStop() = 0; - virtual bool NotifyException(MachException::Data &exc) { return false; } - virtual uint32_t NumSupportedHardwareBreakpoints() { return 0; } - virtual uint32_t NumSupportedHardwareWatchpoints() { return 0; } - virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size) { - return INVALID_NUB_HW_INDEX; - } - virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task) { - return INVALID_NUB_HW_INDEX; - } - virtual bool DisableHardwareBreakpoint(uint32_t hw_index) { return false; } - virtual bool DisableHardwareWatchpoint(uint32_t hw_index, - bool also_set_on_task) { - return false; - } - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) { - return INVALID_NUB_HW_INDEX; - } - virtual bool StepNotComplete() { return false; } - -protected: - friend class MachThread; - - uint32_t GetNextRegisterStateSaveID() { return ++m_save_id; } - - enum { - Trans_Pending = - 0, // Transaction is pending, and checkpoint state has been snapshotted. - Trans_Done = 1, // Transaction is done, the current state is committed, and - // checkpoint state is irrelevant. - Trans_Rolled_Back = 2 // Transaction is done, the current state has been - // rolled back to the checkpoint state. - }; - virtual bool StartTransForHWP() { return true; } - virtual bool RollbackTransForHWP() { return true; } - virtual bool FinishTransForHWP() { return true; } - - uint32_t m_save_id; // An always incrementing integer ID used with - // SaveRegisterState/RestoreRegisterState -}; - -#include "MacOSX/arm/DNBArchImpl.h" -#include "MacOSX/arm64/DNBArchImplARM64.h" -#include "MacOSX/i386/DNBArchImplI386.h" -#include "MacOSX/ppc/DNBArchImpl.h" -#include "MacOSX/x86_64/DNBArchImplX86_64.h" - -#endif diff --git a/tools/debugserver/source/DNBBreakpoint.cpp b/tools/debugserver/source/DNBBreakpoint.cpp deleted file mode 100644 index 89a91287f9e3..000000000000 --- a/tools/debugserver/source/DNBBreakpoint.cpp +++ /dev/null @@ -1,178 +0,0 @@ -//===-- DNBBreakpoint.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/29/07. -// -//===----------------------------------------------------------------------===// - -#include "DNBBreakpoint.h" -#include "DNBLog.h" -#include "MachProcess.h" -#include <algorithm> -#include <assert.h> -#include <inttypes.h> - -#pragma mark-- DNBBreakpoint -DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, - bool hardware) - : m_retain_count(1), m_byte_size(static_cast<uint32_t>(byte_size)), - m_opcode(), m_addr(addr), m_enabled(0), m_hw_preferred(hardware), - m_is_watchpoint(0), m_watch_read(0), m_watch_write(0), - m_hw_index(INVALID_NUB_HW_INDEX) {} - -DNBBreakpoint::~DNBBreakpoint() {} - -void DNBBreakpoint::Dump() const { - if (IsBreakpoint()) { - DNBLog("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint " - "hw_index = %i", - (uint64_t)m_addr, m_enabled ? "enabled " : "disabled", - IsHardware() ? "hardware" : "software", GetHardwareIndex()); - } else { - DNBLog("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s " - "watchpoint (%s%s) hw_index = %i", - (uint64_t)m_addr, (uint64_t)m_byte_size, - m_enabled ? "enabled " : "disabled", - IsHardware() ? "hardware" : "software", m_watch_read ? "r" : "", - m_watch_write ? "w" : "", GetHardwareIndex()); - } -} - -#pragma mark-- DNBBreakpointList - -DNBBreakpointList::DNBBreakpointList() {} - -DNBBreakpointList::~DNBBreakpointList() {} - -DNBBreakpoint *DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, - bool hardware) { - m_breakpoints.insert( - std::make_pair(addr, DNBBreakpoint(addr, length, hardware))); - iterator pos = m_breakpoints.find(addr); - return &pos->second; -} - -bool DNBBreakpointList::Remove(nub_addr_t addr) { - iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) { - m_breakpoints.erase(pos); - return true; - } - return false; -} - -DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) { - iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - return &pos->second; - - return NULL; -} - -const DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) const { - const_iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - return &pos->second; - - return NULL; -} - -// Finds the next breakpoint at an address greater than or equal to "addr" -size_t DNBBreakpointList::FindBreakpointsThatOverlapRange( - nub_addr_t addr, nub_addr_t size, std::vector<DNBBreakpoint *> &bps) { - bps.clear(); - iterator end = m_breakpoints.end(); - // Find the first breakpoint with an address >= to "addr" - iterator pos = m_breakpoints.lower_bound(addr); - if (pos != end) { - if (pos != m_breakpoints.begin()) { - // Watch out for a breakpoint at an address less than "addr" that might - // still overlap - iterator prev_pos = pos; - --prev_pos; - if (prev_pos->second.IntersectsRange(addr, size, NULL, NULL, NULL)) - bps.push_back(&pos->second); - } - - while (pos != end) { - // When we hit a breakpoint whose start address is greater than "addr + - // size" we are done. - // Do the math in a way that doesn't risk unsigned overflow with bad - // input. - if ((pos->second.Address() - addr) >= size) - break; - - // Check if this breakpoint overlaps, and if it does, add it to the list - if (pos->second.IntersectsRange(addr, size, NULL, NULL, NULL)) { - bps.push_back(&pos->second); - ++pos; - } - } - } - return bps.size(); -} - -void DNBBreakpointList::Dump() const { - const_iterator pos; - const_iterator end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - pos->second.Dump(); -} - -void DNBBreakpointList::DisableAll() { - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - pos->second.SetEnabled(false); -} - -void DNBBreakpointList::RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, - void *p) const { - uint8_t *buf = (uint8_t *)p; - const_iterator end = m_breakpoints.end(); - const_iterator pos = m_breakpoints.lower_bound(addr); - while (pos != end && (pos->first < (addr + size))) { - nub_addr_t intersect_addr; - nub_size_t intersect_size; - nub_size_t opcode_offset; - const DNBBreakpoint &bp = pos->second; - if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, - &opcode_offset)) { - assert(addr <= intersect_addr && intersect_addr < addr + size); - assert(addr < intersect_addr + intersect_size && - intersect_addr + intersect_size <= addr + size); - assert(opcode_offset + intersect_size <= bp.ByteSize()); - nub_size_t buf_offset = intersect_addr - addr; - ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, - intersect_size); - } - ++pos; - } -} - -void DNBBreakpointList::DisableAllBreakpoints(MachProcess *process) { - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - process->DisableBreakpoint(pos->second.Address(), false); -} - -void DNBBreakpointList::DisableAllWatchpoints(MachProcess *process) { - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - process->DisableWatchpoint(pos->second.Address(), false); -} - -void DNBBreakpointList::RemoveDisabled() { - iterator pos = m_breakpoints.begin(); - while (pos != m_breakpoints.end()) { - if (!pos->second.IsEnabled()) - pos = m_breakpoints.erase(pos); - else - ++pos; - } -} diff --git a/tools/debugserver/source/DNBBreakpoint.h b/tools/debugserver/source/DNBBreakpoint.h deleted file mode 100644 index 889478b28957..000000000000 --- a/tools/debugserver/source/DNBBreakpoint.h +++ /dev/null @@ -1,149 +0,0 @@ -//===-- DNBBreakpoint.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/29/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBBreakpoint_h__ -#define __DNBBreakpoint_h__ - -#include <mach/mach.h> - -#include <map> -#include <vector> - -#include "DNBDefs.h" - -class MachProcess; - -class DNBBreakpoint { -public: - DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); - ~DNBBreakpoint(); - - nub_size_t ByteSize() const { return m_byte_size; } - uint8_t *SavedOpcodeBytes() { return &m_opcode[0]; } - const uint8_t *SavedOpcodeBytes() const { return &m_opcode[0]; } - nub_addr_t Address() const { return m_addr; } - // nub_thread_t ThreadID() const { return m_tid; } - bool IsEnabled() const { return m_enabled; } - bool IntersectsRange(nub_addr_t addr, nub_size_t size, - nub_addr_t *intersect_addr, nub_size_t *intersect_size, - nub_size_t *opcode_offset) const { - // We only use software traps for software breakpoints - if (IsBreakpoint() && IsEnabled() && !IsHardware()) { - if (m_byte_size > 0) { - const nub_addr_t bp_end_addr = m_addr + m_byte_size; - const nub_addr_t end_addr = addr + size; - // Is the breakpoint end address before the passed in start address? - if (bp_end_addr <= addr) - return false; - // Is the breakpoint start address after passed in end address? - if (end_addr <= m_addr) - return false; - if (intersect_addr || intersect_size || opcode_offset) { - if (m_addr < addr) { - if (intersect_addr) - *intersect_addr = addr; - if (intersect_size) - *intersect_size = - std::min<nub_addr_t>(bp_end_addr, end_addr) - addr; - if (opcode_offset) - *opcode_offset = addr - m_addr; - } else { - if (intersect_addr) - *intersect_addr = m_addr; - if (intersect_size) - *intersect_size = - std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr; - if (opcode_offset) - *opcode_offset = 0; - } - } - return true; - } - } - return false; - } - void SetEnabled(bool enabled) { - if (!enabled) - SetHardwareIndex(INVALID_NUB_HW_INDEX); - m_enabled = enabled; - } - void SetIsWatchpoint(uint32_t type) { - m_is_watchpoint = 1; - m_watch_read = (type & WATCH_TYPE_READ) != 0; - m_watch_write = (type & WATCH_TYPE_WRITE) != 0; - } - bool IsBreakpoint() const { return m_is_watchpoint == 0; } - bool IsWatchpoint() const { return m_is_watchpoint == 1; } - bool WatchpointRead() const { return m_watch_read != 0; } - bool WatchpointWrite() const { return m_watch_write != 0; } - bool HardwarePreferred() const { return m_hw_preferred; } - bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } - uint32_t GetHardwareIndex() const { return m_hw_index; } - void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } - void Dump() const; - uint32_t Retain() { return ++m_retain_count; } - uint32_t Release() { - if (m_retain_count == 0) - return 0; - return --m_retain_count; - } - -private: - uint32_t m_retain_count; // Each breakpoint is maintained by address and is - // ref counted in case multiple people set a - // breakpoint at the same address - uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory - uint8_t m_opcode[8]; // Saved opcode bytes - nub_addr_t m_addr; // Address of this breakpoint - uint32_t m_enabled : 1, // Flags for this breakpoint - m_hw_preferred : 1, // 1 if this point has been requested to be set using - // hardware (which may fail due to lack of resources) - m_is_watchpoint : 1, // 1 if this is a watchpoint - m_watch_read : 1, // 1 if we stop when the watched data is read from - m_watch_write : 1; // 1 if we stop when the watched data is written to - uint32_t - m_hw_index; // The hardware resource index for this breakpoint/watchpoint -}; - -class DNBBreakpointList { -public: - DNBBreakpointList(); - ~DNBBreakpointList(); - - DNBBreakpoint *Add(nub_addr_t addr, nub_size_t length, bool hardware); - bool Remove(nub_addr_t addr); - DNBBreakpoint *FindByAddress(nub_addr_t addr); - const DNBBreakpoint *FindByAddress(nub_addr_t addr) const; - - size_t FindBreakpointsThatOverlapRange(nub_addr_t addr, nub_addr_t size, - std::vector<DNBBreakpoint *> &bps); - - void Dump() const; - - size_t Size() const { return m_breakpoints.size(); } - void DisableAll(); - - void RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, void *buf) const; - - void DisableAllBreakpoints(MachProcess *process); - void DisableAllWatchpoints(MachProcess *process); - void RemoveDisabled(); - -protected: - typedef std::map<nub_addr_t, DNBBreakpoint> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - collection m_breakpoints; -}; - -#endif diff --git a/tools/debugserver/source/DNBDataRef.cpp b/tools/debugserver/source/DNBDataRef.cpp deleted file mode 100644 index 8c12b0afac69..000000000000 --- a/tools/debugserver/source/DNBDataRef.cpp +++ /dev/null @@ -1,351 +0,0 @@ -//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/11/06. -// -//===----------------------------------------------------------------------===// - -#include "DNBDataRef.h" -#include "DNBLog.h" -#include <assert.h> -#include <ctype.h> -#include <libkern/OSByteOrder.h> - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- - -DNBDataRef::DNBDataRef() - : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0), - m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), - m_addrDATA(INVALID_NUB_ADDRESS) {} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- - -DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) - : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0), - m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), - m_addrDATA(INVALID_NUB_ADDRESS) {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- - -DNBDataRef::~DNBDataRef() {} - -//---------------------------------------------------------------------- -// Get8 -//---------------------------------------------------------------------- -uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const { - uint8_t val = 0; - if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { - val = *(m_start + *offset_ptr); - *offset_ptr += sizeof(val); - } - return val; -} - -//---------------------------------------------------------------------- -// Get16 -//---------------------------------------------------------------------- -uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const { - uint16_t val = 0; - if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { - const uint8_t *p = m_start + *offset_ptr; - memcpy(&val, p, sizeof(uint16_t)); - - if (m_swap) - val = OSSwapInt16(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; -} - -//---------------------------------------------------------------------- -// Get32 -//---------------------------------------------------------------------- -uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const { - uint32_t val = 0; - if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { - const uint8_t *p = m_start + *offset_ptr; - memcpy(&val, p, sizeof(uint32_t)); - if (m_swap) - val = OSSwapInt32(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; -} - -//---------------------------------------------------------------------- -// Get64 -//---------------------------------------------------------------------- -uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const { - uint64_t val = 0; - if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { - const uint8_t *p = m_start + *offset_ptr; - memcpy(&val, p, sizeof(uint64_t)); - if (m_swap) - val = OSSwapInt64(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; -} - -//---------------------------------------------------------------------- -// GetMax32 -// -// Used for calls when the size can vary. Fill in extra cases if they -// are ever needed. -//---------------------------------------------------------------------- -uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const { - switch (byte_size) { - case 1: - return Get8(offset_ptr); - break; - case 2: - return Get16(offset_ptr); - break; - case 4: - return Get32(offset_ptr); - break; - default: - assert(false && "GetMax32 unhandled case!"); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// GetMax64 -// -// Used for calls when the size can vary. Fill in extra cases if they -// are ever needed. -//---------------------------------------------------------------------- -uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const { - switch (size) { - case 1: - return Get8(offset_ptr); - break; - case 2: - return Get16(offset_ptr); - break; - case 4: - return Get32(offset_ptr); - break; - case 8: - return Get64(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// GetPointer -// -// Extract a pointer value from the buffer. The pointer size must be -// set prior to using this using one of the SetPointerSize functions. -//---------------------------------------------------------------------- -uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const { - // Must set pointer size prior to using this call - assert(m_ptrSize != 0); - return GetMax64(offset_ptr, m_ptrSize); -} -//---------------------------------------------------------------------- -// GetCStr -//---------------------------------------------------------------------- -const char *DNBDataRef::GetCStr(offset_t *offset_ptr, - uint32_t fixed_length) const { - const char *s = NULL; - if (m_start < m_end) { - s = (const char *)m_start + *offset_ptr; - - // Advance the offset - if (fixed_length) - *offset_ptr += fixed_length; - else - *offset_ptr += strlen(s) + 1; - } - return s; -} - -//---------------------------------------------------------------------- -// GetData -//---------------------------------------------------------------------- -const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr, - uint32_t length) const { - const uint8_t *data = NULL; - if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) { - data = m_start + *offset_ptr; - *offset_ptr += length; - } - return data; -} - -//---------------------------------------------------------------------- -// Get_ULEB128 -//---------------------------------------------------------------------- -uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const { - uint64_t result = 0; - if (m_start < m_end) { - int shift = 0; - const uint8_t *src = m_start + *offset_ptr; - uint8_t byte; - int bytecount = 0; - - while (src < m_end) { - bytecount++; - byte = *src++; - result |= (uint64_t)(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - *offset_ptr += bytecount; - } - return result; -} - -//---------------------------------------------------------------------- -// Get_SLEB128 -//---------------------------------------------------------------------- -int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const { - int64_t result = 0; - - if (m_start < m_end) { - int shift = 0; - int size = sizeof(uint32_t) * 8; - const uint8_t *src = m_start + *offset_ptr; - - uint8_t byte = 0; - int bytecount = 0; - - while (src < m_end) { - bytecount++; - byte = *src++; - result |= (int64_t)(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - // Sign bit of byte is 2nd high order bit (0x40) - if (shift < size && (byte & 0x40)) - result |= -(1ll << shift); - - *offset_ptr += bytecount; - } - return result; -} - -//---------------------------------------------------------------------- -// Skip_LEB128 -// -// Skips past ULEB128 and SLEB128 numbers (just updates the offset) -//---------------------------------------------------------------------- -void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const { - if (m_start < m_end) { - const uint8_t *start = m_start + *offset_ptr; - const uint8_t *src = start; - - while ((src < m_end) && (*src++ & 0x80)) - /* Do nothing */; - - *offset_ptr += src - start; - } -} - -uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset, - uint64_t offsetBase, DNBDataRef::Type type, - uint32_t numPerLine, const char *format) { - uint32_t offset; - uint32_t count; - char str[1024]; - str[0] = '\0'; - size_t str_offset = 0; - - for (offset = startOffset, count = 0; - ValidOffset(offset) && offset < endOffset; ++count) { - if ((count % numPerLine) == 0) { - // Print out any previous string - if (str[0] != '\0') - DNBLog("%s", str); - // Reset string offset and fill the current line string with address: - str_offset = 0; - str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", - (uint64_t)(offsetBase + (offset - startOffset))); - } - - // Make sure we don't pass the bounds of our current string buffer on each - // iteration through this loop - if (str_offset >= sizeof(str)) { - // The last snprintf consumed our string buffer, we will need to dump this - // out - // and reset the string with no address - DNBLog("%s", str); - str_offset = 0; - str[0] = '\0'; - } - - // We already checked that there is at least some room in the string str - // above, so it is safe to make - // the snprintf call each time through this loop - switch (type) { - case TypeUInt8: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %2.2x", Get8(&offset)); - break; - case TypeChar: { - char ch = Get8(&offset); - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %c", isprint(ch) ? ch : ' '); - } break; - case TypeUInt16: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %4.4x", Get16(&offset)); - break; - case TypeUInt32: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %8.8x", Get32(&offset)); - break; - case TypeUInt64: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %16.16llx", Get64(&offset)); - break; - case TypePointer: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " 0x%llx", GetPointer(&offset)); - break; - case TypeULEB128: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " 0x%llx", Get_ULEB128(&offset)); - break; - case TypeSLEB128: - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, - format ? format : " %lld", Get_SLEB128(&offset)); - break; - } - } - - if (str[0] != '\0') - DNBLog("%s", str); - - return offset; // Return the offset at which we ended up -} diff --git a/tools/debugserver/source/DNBDataRef.h b/tools/debugserver/source/DNBDataRef.h deleted file mode 100644 index 9a19f20227e6..000000000000 --- a/tools/debugserver/source/DNBDataRef.h +++ /dev/null @@ -1,125 +0,0 @@ -//===-- DNBDataRef.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/11/06. -// -//===----------------------------------------------------------------------===// -// -// DNBDataRef is a class that can extract data in normal or byte -// swapped order from a data buffer that someone else owns. The data -// buffer needs to remain intact as long as the DNBDataRef object -// needs the data. Strings returned are pointers into the data buffer -// and will need to be copied if they are needed after the data buffer -// is no longer around. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBDataRef_h__ -#define __DNBDataRef_h__ - -#include "DNBDefs.h" -#include <limits.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -class DNBDataRef { -public: - // For use with Dump - typedef enum { - TypeUInt8 = 0, - TypeChar, - TypeUInt16, - TypeUInt32, - TypeUInt64, - TypePointer, - TypeULEB128, - TypeSLEB128 - } Type; - typedef uint32_t offset_t; - typedef nub_addr_t addr_t; - - DNBDataRef(); - DNBDataRef(const uint8_t *start, size_t size, bool swap); - ~DNBDataRef(); - void Clear() { - DNBDataRef::SetData(NULL, 0); - m_swap = false; - } - - size_t BytesLeft(size_t offset) const { - const size_t size = GetSize(); - if (size > offset) - return size - offset; - return 0; - } - - bool ValidOffset(offset_t offset) const { return BytesLeft(offset) > 0; } - bool ValidOffsetForDataOfSize(offset_t offset, uint32_t num_bytes) const { - return num_bytes <= BytesLeft(offset); - } - size_t GetSize() const { return m_end - m_start; } - const uint8_t *GetDataStart() const { return m_start; } - const uint8_t *GetDataEnd() const { return m_end; } - bool GetSwap() const { return m_swap; } - void SetSwap(bool swap) { m_swap = swap; } - void SetData(const uint8_t *start, size_t size) { - m_start = start; - if (m_start != NULL) - m_end = start + size; - else - m_end = NULL; - } - uint8_t GetPointerSize() const { return m_ptrSize; } - void SetPointerSize(uint8_t size) { m_ptrSize = size; } - void SetEHPtrBaseAddrPCRelative(addr_t addr = INVALID_NUB_ADDRESS) { - m_addrPCRelative = addr; - } - void SetEHPtrBaseAddrTEXT(addr_t addr = INVALID_NUB_ADDRESS) { - m_addrTEXT = addr; - } - void SetEHPtrBaseAddrDATA(addr_t addr = INVALID_NUB_ADDRESS) { - m_addrDATA = addr; - } - uint8_t Get8(offset_t *offset_ptr) const; - uint16_t Get16(offset_t *offset_ptr) const; - uint32_t Get32(offset_t *offset_ptr) const; - uint64_t Get64(offset_t *offset_ptr) const; - uint32_t GetMax32(offset_t *offset_ptr, uint32_t byte_size) const; - uint64_t GetMax64(offset_t *offset_ptr, uint32_t byte_size) const; - uint64_t GetPointer(offset_t *offset_ptr) const; - // uint64_t GetDwarfEHPtr(offset_t *offset_ptr, uint32_t eh_ptr_enc) - // const; - const char *GetCStr(offset_t *offset_ptr, uint32_t fixed_length = 0) const; - const char *PeekCStr(offset_t offset) const { - if (ValidOffset(offset)) - return (const char *)m_start + offset; - return NULL; - } - - const uint8_t *GetData(offset_t *offset_ptr, uint32_t length) const; - uint64_t Get_ULEB128(offset_t *offset_ptr) const; - int64_t Get_SLEB128(offset_t *offset_ptr) const; - void Skip_LEB128(offset_t *offset_ptr) const; - - uint32_t Dump(offset_t startOffset, offset_t endOffset, uint64_t offsetBase, - DNBDataRef::Type type, uint32_t numPerLine, - const char *typeFormat = NULL); - -protected: - const uint8_t *m_start; - const uint8_t *m_end; - bool m_swap; - uint8_t m_ptrSize; - addr_t m_addrPCRelative; - addr_t m_addrTEXT; - addr_t m_addrDATA; -}; - -#endif // #ifndef __DNBDataRef_h__ diff --git a/tools/debugserver/source/DNBDefs.h b/tools/debugserver/source/DNBDefs.h deleted file mode 100644 index 46476490aa69..000000000000 --- a/tools/debugserver/source/DNBDefs.h +++ /dev/null @@ -1,373 +0,0 @@ -//===-- DNBDefs.h -----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBDefs_h__ -#define __DNBDefs_h__ - -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <sys/syslimits.h> -#include <unistd.h> - -//---------------------------------------------------------------------- -// Define nub_addr_t and the invalid address value from the architecture -//---------------------------------------------------------------------- -#if defined(__x86_64__) || defined(__ppc64__) || defined(__arm64__) || \ - defined(__aarch64__) - -//---------------------------------------------------------------------- -// 64 bit address architectures -//---------------------------------------------------------------------- -typedef uint64_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) - -#elif defined(__i386__) || defined(__powerpc__) || defined(__ppc__) || \ - defined(__arm__) - -//---------------------------------------------------------------------- -// 32 bit address architectures -//---------------------------------------------------------------------- - -typedef uint32_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ul) - -#else - -//---------------------------------------------------------------------- -// Default to 64 bit address for unrecognized architectures. -//---------------------------------------------------------------------- - -#warning undefined architecture, defaulting to 8 byte addresses -typedef uint64_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) - -#endif - -typedef size_t nub_size_t; -typedef ssize_t nub_ssize_t; -typedef uint32_t nub_index_t; -typedef pid_t nub_process_t; -typedef uint64_t nub_thread_t; -typedef uint32_t nub_event_t; -typedef uint32_t nub_bool_t; - -#define INVALID_NUB_PROCESS ((nub_process_t)0) -#define INVALID_NUB_THREAD ((nub_thread_t)0) -#define INVALID_NUB_WATCH_ID ((nub_watch_t)0) -#define INVALID_NUB_HW_INDEX UINT32_MAX -#define INVALID_NUB_REGNUM UINT32_MAX -#define NUB_GENERIC_ERROR UINT32_MAX - -// Watchpoint types -#define WATCH_TYPE_READ (1u << 0) -#define WATCH_TYPE_WRITE (1u << 1) - -typedef enum { - eStateInvalid = 0, - eStateUnloaded, - eStateAttaching, - eStateLaunching, - eStateStopped, - eStateRunning, - eStateStepping, - eStateCrashed, - eStateDetached, - eStateExited, - eStateSuspended -} nub_state_t; - -typedef enum { - eLaunchFlavorDefault = 0, - eLaunchFlavorPosixSpawn = 1, - eLaunchFlavorForkExec = 2, -#ifdef WITH_SPRINGBOARD - eLaunchFlavorSpringBoard = 3, -#endif -#ifdef WITH_BKS - eLaunchFlavorBKS = 4, -#endif -#ifdef WITH_FBS - eLaunchFlavorFBS = 5 -#endif -} nub_launch_flavor_t; - -#define NUB_STATE_IS_RUNNING(s) \ - ((s) == eStateAttaching || (s) == eStateLaunching || (s) == eStateRunning || \ - (s) == eStateStepping || (s) == eStateDetached) - -#define NUB_STATE_IS_STOPPED(s) \ - ((s) == eStateUnloaded || (s) == eStateStopped || (s) == eStateCrashed || \ - (s) == eStateExited) - -enum { - eEventProcessRunningStateChanged = - 1 << 0, // The process has changed state to running - eEventProcessStoppedStateChanged = - 1 << 1, // The process has changed state to stopped - eEventSharedLibsStateChange = - 1 << 2, // Shared libraries loaded/unloaded state has changed - eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr - eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval - kAllEventsMask = eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged | - eEventSharedLibsStateChange | eEventStdioAvailable | - eEventProfileDataAvailable -}; - -#define LOG_VERBOSE (1u << 0) -#define LOG_PROCESS (1u << 1) -#define LOG_THREAD (1u << 2) -#define LOG_EXCEPTIONS (1u << 3) -#define LOG_SHLIB (1u << 4) -#define LOG_MEMORY (1u << 5) // Log memory reads/writes calls -#define LOG_MEMORY_DATA_SHORT (1u << 6) // Log short memory reads/writes bytes -#define LOG_MEMORY_DATA_LONG (1u << 7) // Log all memory reads/writes bytes -#define LOG_MEMORY_PROTECTIONS (1u << 8) // Log memory protection changes -#define LOG_BREAKPOINTS (1u << 9) -#define LOG_EVENTS (1u << 10) -#define LOG_WATCHPOINTS (1u << 11) -#define LOG_STEP (1u << 12) -#define LOG_TASK (1u << 13) -#define LOG_DARWIN_LOG (1u << 14) -#define LOG_LO_USER (1u << 16) -#define LOG_HI_USER (1u << 31) -#define LOG_ALL 0xFFFFFFFFu -#define LOG_DEFAULT \ - ((LOG_PROCESS) | (LOG_TASK) | (LOG_THREAD) | (LOG_EXCEPTIONS) | \ - (LOG_SHLIB) | (LOG_MEMORY) | (LOG_BREAKPOINTS) | (LOG_WATCHPOINTS) | \ - (LOG_STEP)) - -#define REGISTER_SET_ALL 0 -// Generic Register set to be defined by each architecture for access to common -// register values. -#define REGISTER_SET_GENERIC ((uint32_t)0xFFFFFFFFu) -#define GENERIC_REGNUM_PC 0 // Program Counter -#define GENERIC_REGNUM_SP 1 // Stack Pointer -#define GENERIC_REGNUM_FP 2 // Frame Pointer -#define GENERIC_REGNUM_RA 3 // Return Address -#define GENERIC_REGNUM_FLAGS 4 // Processor flags register -#define GENERIC_REGNUM_ARG1 \ - 5 // The register that would contain pointer size or less argument 1 (if any) -#define GENERIC_REGNUM_ARG2 \ - 6 // The register that would contain pointer size or less argument 2 (if any) -#define GENERIC_REGNUM_ARG3 \ - 7 // The register that would contain pointer size or less argument 3 (if any) -#define GENERIC_REGNUM_ARG4 \ - 8 // The register that would contain pointer size or less argument 4 (if any) -#define GENERIC_REGNUM_ARG5 \ - 9 // The register that would contain pointer size or less argument 5 (if any) -#define GENERIC_REGNUM_ARG6 \ - 10 // The register that would contain pointer size or less argument 6 (if any) -#define GENERIC_REGNUM_ARG7 \ - 11 // The register that would contain pointer size or less argument 7 (if any) -#define GENERIC_REGNUM_ARG8 \ - 12 // The register that would contain pointer size or less argument 8 (if any) - -enum DNBRegisterType { - InvalidRegType = 0, - Uint, // unsigned integer - Sint, // signed integer - IEEE754, // float - Vector // vector registers -}; - -enum DNBRegisterFormat { - InvalidRegFormat = 0, - Binary, - Decimal, - Hex, - Float, - VectorOfSInt8, - VectorOfUInt8, - VectorOfSInt16, - VectorOfUInt16, - VectorOfSInt32, - VectorOfUInt32, - VectorOfFloat32, - VectorOfUInt128 -}; - -struct DNBRegisterInfo { - uint32_t set; // Register set - uint32_t reg; // Register number - const char *name; // Name of this register - const char *alt; // Alternate name - uint16_t type; // Type of the register bits (DNBRegisterType) - uint16_t format; // Default format for display (DNBRegisterFormat), - uint32_t size; // Size in bytes of the register - uint32_t offset; // Offset from the beginning of the register context - uint32_t - reg_ehframe; // eh_frame register number (INVALID_NUB_REGNUM when none) - uint32_t reg_dwarf; // DWARF register number (INVALID_NUB_REGNUM when none) - uint32_t - reg_generic; // Generic register number (INVALID_NUB_REGNUM when none) - uint32_t reg_debugserver; // The debugserver register number we'll use over - // gdb-remote protocol (INVALID_NUB_REGNUM when - // none) - const char **value_regs; // If this register is a part of other registers, - // list the register names terminated by NULL - const char **update_regs; // If modifying this register will invalidate other - // registers, list the register names terminated by - // NULL -}; - -struct DNBRegisterSetInfo { - const char *name; // Name of this register set - const struct DNBRegisterInfo *registers; // An array of register descriptions - nub_size_t num_registers; // The number of registers in REGISTERS array above -}; - -struct DNBThreadResumeAction { - nub_thread_t tid; // The thread ID that this action applies to, - // INVALID_NUB_THREAD for the default thread action - nub_state_t state; // Valid values are eStateStopped/eStateSuspended, - // eStateRunning, and eStateStepping. - int signal; // When resuming this thread, resume it with this signal - nub_addr_t addr; // If not INVALID_NUB_ADDRESS, then set the PC for the thread - // to ADDR before resuming/stepping -}; - -enum DNBThreadStopType { - eStopTypeInvalid = 0, - eStopTypeSignal, - eStopTypeException, - eStopTypeExec -}; - -enum DNBMemoryPermissions { - eMemoryPermissionsWritable = (1 << 0), - eMemoryPermissionsReadable = (1 << 1), - eMemoryPermissionsExecutable = (1 << 2) -}; - -#define DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH 256 -#define DNB_THREAD_STOP_INFO_MAX_EXC_DATA 8 - -//---------------------------------------------------------------------- -// DNBThreadStopInfo -// -// Describes the reason a thread stopped. -//---------------------------------------------------------------------- -struct DNBThreadStopInfo { - DNBThreadStopType reason; - char description[DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH]; - union { - // eStopTypeSignal - struct { - uint32_t signo; - } signal; - - // eStopTypeException - struct { - uint32_t type; - nub_size_t data_count; - nub_addr_t data[DNB_THREAD_STOP_INFO_MAX_EXC_DATA]; - } exception; - } details; -}; - -struct DNBRegisterValue { - struct DNBRegisterInfo info; // Register information for this register - union { - int8_t sint8; - int16_t sint16; - int32_t sint32; - int64_t sint64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float float32; - double float64; - int8_t v_sint8[64]; - int16_t v_sint16[32]; - int32_t v_sint32[16]; - int64_t v_sint64[8]; - uint8_t v_uint8[64]; - uint16_t v_uint16[32]; - uint32_t v_uint32[16]; - uint64_t v_uint64[8]; - float v_float32[16]; - double v_float64[8]; - void *pointer; - char *c_str; - } value; -}; - -enum DNBSharedLibraryState { eShlibStateUnloaded = 0, eShlibStateLoaded = 1 }; - -#ifndef DNB_MAX_SEGMENT_NAME_LENGTH -#define DNB_MAX_SEGMENT_NAME_LENGTH 32 -#endif - -struct DNBSegment { - char name[DNB_MAX_SEGMENT_NAME_LENGTH]; - nub_addr_t addr; - nub_addr_t size; -}; - -struct DNBExecutableImageInfo { - char name[PATH_MAX]; // Name of the executable image (usually a full path) - uint32_t - state; // State of the executable image (see enum DNBSharedLibraryState) - nub_addr_t header_addr; // Executable header address - uuid_t uuid; // Unique identifier for matching with symbols - uint32_t - num_segments; // Number of contiguous memory segments to in SEGMENTS array - DNBSegment *segments; // Array of contiguous memory segments in executable -}; - -struct DNBRegionInfo { - nub_addr_t addr; - nub_addr_t size; - uint32_t permissions; -}; - -enum DNBProfileDataScanType { - eProfileHostCPU = (1 << 0), - eProfileCPU = (1 << 1), - - eProfileThreadsCPU = - (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName. - eProfileThreadName = - (1 << 3), // Assume eProfileThreadsCPU, get thread name as well. - eProfileQueueName = - (1 << 4), // Assume eProfileThreadsCPU, get queue name as well. - - eProfileHostMemory = (1 << 5), - - eProfileMemory = (1 << 6), - eProfileMemoryAnonymous = - (1 << 8), // Assume eProfileMemory, get Anonymous memory as well. - - eProfileEnergy = (1 << 9), - - eProfileMemoryCap = (1 << 15), - - eProfileAll = 0xffffffff -}; - -typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, - const char *name, - const char *shlib_regex, - void *baton); -typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)( - nub_process_t pid, struct DNBExecutableImageInfo **image_infos, - nub_bool_t only_changed, void *baton); -typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format, - va_list args); - -#define UNUSED_IF_ASSERT_DISABLED(x) ((void)(x)) - -#endif // #ifndef __DNBDefs_h__ diff --git a/tools/debugserver/source/DNBError.cpp b/tools/debugserver/source/DNBError.cpp deleted file mode 100644 index cd04358a4eca..000000000000 --- a/tools/debugserver/source/DNBError.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//===-- DNBError.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#include "DNBError.h" -#include "CFString.h" -#include "DNBLog.h" -#include "PThreadMutex.h" - -#ifdef WITH_SPRINGBOARD -#include <SpringBoardServices/SpringBoardServer.h> -#endif - -const char *DNBError::AsString() const { - if (Success()) - return NULL; - - if (m_str.empty()) { - const char *s = NULL; - switch (m_flavor) { - case MachKernel: - s = ::mach_error_string(m_err); - break; - - case POSIX: - s = ::strerror(m_err); - break; - -#ifdef WITH_SPRINGBOARD - case SpringBoard: { - CFStringRef statusStr = SBSApplicationLaunchingErrorString(m_err); - if (CFString::UTF8(statusStr, m_str) == NULL) - m_str.clear(); - } break; -#endif -#ifdef WITH_BKS - case BackBoard: { - // You have to call ObjC routines to get the error string from - // BackBoardServices. - // Not sure I want to make DNBError.cpp an .mm file. For now just make - // sure you - // pre-populate the error string when you make the DNBError of type - // BackBoard. - m_str.assign( - "Should have set BackBoard error when making the error string."); - } break; -#endif -#ifdef WITH_FBS - case FrontBoard: { - // You have to call ObjC routines to get the error string from - // FrontBoardServices. - // Not sure I want to make DNBError.cpp an .mm file. For now just make - // sure you - // pre-populate the error string when you make the DNBError of type - // FrontBoard. - m_str.assign( - "Should have set FrontBoard error when making the error string."); - } break; -#endif - default: - break; - } - if (s) - m_str.assign(s); - } - if (m_str.empty()) - return NULL; - return m_str.c_str(); -} - -void DNBError::LogThreadedIfError(const char *format, ...) const { - if (Fail()) { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - const char *err_str = AsString(); - if (err_str == NULL) - err_str = "???"; - DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); - free(arg_msg); - } - } -} - -void DNBError::LogThreaded(const char *format, ...) const { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - if (Fail()) { - const char *err_str = AsString(); - if (err_str == NULL) - err_str = "???"; - DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); - } else { - DNBLogThreaded("%s err = 0x%8.8x", arg_msg, m_err); - } - free(arg_msg); - } -} diff --git a/tools/debugserver/source/DNBError.h b/tools/debugserver/source/DNBError.h deleted file mode 100644 index 419f4b9492ed..000000000000 --- a/tools/debugserver/source/DNBError.h +++ /dev/null @@ -1,98 +0,0 @@ -//===-- DNBError.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBError_h__ -#define __DNBError_h__ - -#include <errno.h> -#include <mach/mach.h> -#include <stdio.h> -#include <string> - -class DNBError { -public: - typedef uint32_t ValueType; - typedef enum { - Generic = 0, - MachKernel = 1, - POSIX = 2 -#ifdef WITH_SPRINGBOARD - , - SpringBoard = 3 -#endif -#ifdef WITH_BKS - , - BackBoard = 4 -#endif -#ifdef WITH_FBS - , - FrontBoard = 5 -#endif - } FlavorType; - - explicit DNBError(ValueType err = 0, FlavorType flavor = Generic) - : m_err(err), m_flavor(flavor) {} - - const char *AsString() const; - void Clear() { - m_err = 0; - m_flavor = Generic; - m_str.clear(); - } - ValueType Status() const { return m_err; } - FlavorType Flavor() const { return m_flavor; } - - ValueType operator=(kern_return_t err) { - m_err = err; - m_flavor = MachKernel; - m_str.clear(); - return m_err; - } - - void SetError(kern_return_t err) { - m_err = err; - m_flavor = MachKernel; - m_str.clear(); - } - - void SetErrorToErrno() { - m_err = errno; - m_flavor = POSIX; - m_str.clear(); - } - - void SetError(ValueType err, FlavorType flavor) { - m_err = err; - m_flavor = flavor; - m_str.clear(); - } - - // Generic errors can set their own string values - void SetErrorString(const char *err_str) { - if (err_str && err_str[0]) - m_str = err_str; - else - m_str.clear(); - } - bool Success() const { return m_err == 0; } - bool Fail() const { return m_err != 0; } - void LogThreadedIfError(const char *format, ...) const; - void LogThreaded(const char *format, ...) const; - -protected: - ValueType m_err; - FlavorType m_flavor; - mutable std::string m_str; -}; - -#endif // #ifndef __DNBError_h__ diff --git a/tools/debugserver/source/DNBLog.cpp b/tools/debugserver/source/DNBLog.cpp deleted file mode 100644 index c3d42a2a84da..000000000000 --- a/tools/debugserver/source/DNBLog.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#include "DNBLog.h" - -static int g_debug = 0; -static int g_verbose = 0; - -#if defined(DNBLOG_ENABLED) - -#include "PThreadMutex.h" -#include <mach/mach.h> -#include <pthread.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> -#include <unistd.h> - -uint32_t g_log_bits = 0; -static DNBCallbackLog g_log_callback = NULL; -static void *g_log_baton = NULL; - -int DNBLogGetDebug() { return g_debug; } - -void DNBLogSetDebug(int g) { g_debug = g; } - -int DNBLogGetVerbose() { return g_verbose; } - -void DNBLogSetVerbose(int v) { g_verbose = v; } - -bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; } - -uint32_t DNBLogSetLogMask(uint32_t mask) { - uint32_t old = g_log_bits; - g_log_bits = mask; - return old; -} - -uint32_t DNBLogGetLogMask() { return g_log_bits; } - -void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) { - g_log_callback = callback; - g_log_baton = baton; -} - -DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; } - -bool DNBLogEnabled() { return g_log_callback != NULL; } - -bool DNBLogEnabledForAny(uint32_t mask) { - if (g_log_callback) - return (g_log_bits & mask) != 0; - return false; -} -static inline void _DNBLogVAPrintf(uint32_t flags, const char *format, - va_list args) { - static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); - PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); - - if (g_log_callback) - g_log_callback(g_log_baton, flags, format, args); -} - -void _DNBLog(uint32_t flags, const char *format, ...) { - va_list args; - va_start(args, format); - _DNBLogVAPrintf(flags, format, args); - va_end(args); -} - -//---------------------------------------------------------------------- -// Print debug strings if and only if the global g_debug is set to -// a non-zero value. -//---------------------------------------------------------------------- -void _DNBLogDebug(const char *format, ...) { - if (DNBLogEnabled() && g_debug) { - va_list args; - va_start(args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); - va_end(args); - } -} - -//---------------------------------------------------------------------- -// Print debug strings if and only if the global g_debug is set to -// a non-zero value. -//---------------------------------------------------------------------- -void _DNBLogDebugVerbose(const char *format, ...) { - if (DNBLogEnabled() && g_debug && g_verbose) { - va_list args; - va_start(args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); - va_end(args); - } -} - -static uint32_t g_message_id = 0; - -//---------------------------------------------------------------------- -// Prefix the formatted log string with process and thread IDs and -// suffix it with a newline. -//---------------------------------------------------------------------- -void _DNBLogThreaded(const char *format, ...) { - if (DNBLogEnabled()) { - // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); - - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - static struct timeval g_timeval = {0, 0}; - static struct timeval tv; - static struct timeval delta; - gettimeofday(&tv, NULL); - if (g_timeval.tv_sec == 0) { - delta.tv_sec = 0; - delta.tv_usec = 0; - } else { - timersub(&tv, &g_timeval, &delta); - } - g_timeval = tv; - - // Calling "mach_port_deallocate()" bumps the reference count on the - // thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the - // ref - // count. - thread_port_t thread_self = mach_thread_self(); - - _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", - ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), - thread_self, arg_msg); - - mach_port_deallocate(mach_task_self(), thread_self); - free(arg_msg); - } - } -} - -//---------------------------------------------------------------------- -// Prefix the formatted log string with process and thread IDs and -// suffix it with a newline. -//---------------------------------------------------------------------- -void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) { - if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) { - // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); - - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - static struct timeval g_timeval = {0, 0}; - static struct timeval tv; - static struct timeval delta; - gettimeofday(&tv, NULL); - if (g_timeval.tv_sec == 0) { - delta.tv_sec = 0; - delta.tv_usec = 0; - } else { - timersub(&tv, &g_timeval, &delta); - } - g_timeval = tv; - - // Calling "mach_port_deallocate()" bumps the reference count on the - // thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the - // ref - // count. - thread_port_t thread_self = mach_thread_self(); - - _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", - ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), - thread_self, arg_msg); - - mach_port_deallocate(mach_task_self(), thread_self); - - free(arg_msg); - } - } -} - -//---------------------------------------------------------------------- -// Printing of errors that are not fatal. -//---------------------------------------------------------------------- -void _DNBLogError(const char *format, ...) { - if (DNBLogEnabled()) { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg); - free(arg_msg); - } - } -} - -//---------------------------------------------------------------------- -// Printing of errors that ARE fatal. Exit with ERR exit code -// immediately. -//---------------------------------------------------------------------- -void _DNBLogFatalError(int err, const char *format, ...) { - if (DNBLogEnabled()) { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); - free(arg_msg); - } - ::exit(err); - } -} - -//---------------------------------------------------------------------- -// Printing of warnings that are not fatal only if verbose mode is -// enabled. -//---------------------------------------------------------------------- -void _DNBLogVerbose(const char *format, ...) { - if (DNBLogEnabled() && g_verbose) { - va_list args; - va_start(args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); - va_end(args); - } -} - -//---------------------------------------------------------------------- -// Printing of warnings that are not fatal only if verbose mode is -// enabled. -//---------------------------------------------------------------------- -void _DNBLogWarningVerbose(const char *format, ...) { - if (DNBLogEnabled() && g_verbose) { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", - arg_msg); - free(arg_msg); - } - } -} -//---------------------------------------------------------------------- -// Printing of warnings that are not fatal. -//---------------------------------------------------------------------- -void _DNBLogWarning(const char *format, ...) { - if (DNBLogEnabled()) { - char *arg_msg = NULL; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != NULL) { - _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); - free(arg_msg); - } - } -} - -#endif diff --git a/tools/debugserver/source/DNBLog.h b/tools/debugserver/source/DNBLog.h deleted file mode 100644 index 65181caa412d..000000000000 --- a/tools/debugserver/source/DNBLog.h +++ /dev/null @@ -1,153 +0,0 @@ -//===-- DNBLog.h ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBLog_h__ -#define __DNBLog_h__ - -#include "DNBDefs.h" -#include <stdint.h> -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -// Flags that get filled in automatically before calling the log callback -// function -#define DNBLOG_FLAG_FATAL (1u << 0) -#define DNBLOG_FLAG_ERROR (1u << 1) -#define DNBLOG_FLAG_WARNING (1u << 2) -#define DNBLOG_FLAG_DEBUG (1u << 3) -#define DNBLOG_FLAG_VERBOSE (1u << 4) -#define DNBLOG_FLAG_THREADED (1u << 5) - -#define DNBLOG_ENABLED - -#if defined(DNBLOG_ENABLED) - -void _DNBLog(uint32_t flags, const char *format, ...) - __attribute__((format(printf, 2, 3))); -void _DNBLogDebug(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void _DNBLogDebugVerbose(const char *fmt, ...) - __attribute__((format(printf, 1, 2))); -void _DNBLogThreaded(const char *fmt, ...) - __attribute__((format(printf, 1, 2))); -void _DNBLogThreadedIf(uint32_t mask, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -void _DNBLogError(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void _DNBLogFatalError(int err, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -void _DNBLogVerbose(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void _DNBLogWarning(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void _DNBLogWarningVerbose(const char *fmt, ...) - __attribute__((format(printf, 1, 2))); -bool DNBLogCheckLogBit(uint32_t bit); -uint32_t DNBLogSetLogMask(uint32_t mask); -uint32_t DNBLogGetLogMask(); -void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton); -DNBCallbackLog DNBLogGetLogCallback(); -bool DNBLogEnabled(); -bool DNBLogEnabledForAny(uint32_t mask); -int DNBLogGetDebug(); -void DNBLogSetDebug(int g); -int DNBLogGetVerbose(); -void DNBLogSetVerbose(int g); - -#define DNBLog(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLog(0, fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogDebug(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogDebug(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogDebugVerbose(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogDebugVerbose(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogThreaded(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogThreaded(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogThreadedIf(mask, fmt, ...) \ - do { \ - if (DNBLogEnabledForAny(mask)) { \ - _DNBLogThreaded(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogError(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogError(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogFatalError(err, fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogFatalError(err, fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogVerbose(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogVerbose(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogWarning(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogWarning(fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define DNBLogWarningVerbose(fmt, ...) \ - do { \ - if (DNBLogEnabled()) { \ - _DNBLogWarningVerbose(fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -#else // #if defined(DNBLOG_ENABLED) - -#define DNBLogDebug(...) ((void)0) -#define DNBLogDebugVerbose(...) ((void)0) -#define DNBLogThreaded(...) ((void)0) -#define DNBLogThreadedIf(...) ((void)0) -#define DNBLogError(...) ((void)0) -#define DNBLogFatalError(...) ((void)0) -#define DNBLogVerbose(...) ((void)0) -#define DNBLogWarning(...) ((void)0) -#define DNBLogWarningVerbose(...) ((void)0) -#define DNBLogGetLogFile() ((FILE *)NULL) -#define DNBLogSetLogFile(f) ((void)0) -#define DNBLogCheckLogBit(bit) ((bool)false) -#define DNBLogSetLogMask(mask) ((uint32_t)0u) -#define DNBLogGetLogMask() ((uint32_t)0u) -#define DNBLogToASL() ((void)0) -#define DNBLogToFile() ((void)0) -#define DNBLogCloseLogFile() ((void)0) - -#endif // #else defined(DNBLOG_ENABLED) - -#ifdef __cplusplus -} -#endif - -#endif // #ifndef __DNBLog_h__ diff --git a/tools/debugserver/source/DNBRegisterInfo.cpp b/tools/debugserver/source/DNBRegisterInfo.cpp deleted file mode 100644 index d0f6063fbce0..000000000000 --- a/tools/debugserver/source/DNBRegisterInfo.cpp +++ /dev/null @@ -1,252 +0,0 @@ -//===-- DNBRegisterInfo.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 8/3/07. -// -//===----------------------------------------------------------------------===// - -#include "DNBRegisterInfo.h" -#include "DNBLog.h" -#include <string.h> - -DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo) { - Clear(); - if (regInfo) - info = *regInfo; -} - -void DNBRegisterValueClass::Clear() { - memset(&info, 0, sizeof(DNBRegisterInfo)); - memset(&value, 0, sizeof(value)); -} - -bool DNBRegisterValueClass::IsValid() const { - return info.name != NULL && info.type != InvalidRegType && info.size > 0 && - info.size <= sizeof(value); -} - -#define PRINT_COMMA_SEPARATOR \ - do { \ - if (pos < end) { \ - if (i > 0) { \ - strlcpy(pos, ", ", end - pos); \ - pos += 2; \ - } \ - } \ - } while (0) - -void DNBRegisterValueClass::Dump(const char *pre, const char *post) const { - if (info.name != NULL) { - char str[1024]; - char *pos; - char *end = str + sizeof(str); - if (info.format == Hex) { - switch (info.size) { - case 0: - snprintf(str, sizeof(str), "%s", - "error: invalid register size of zero."); - break; - case 1: - snprintf(str, sizeof(str), "0x%2.2x", value.uint8); - break; - case 2: - snprintf(str, sizeof(str), "0x%4.4x", value.uint16); - break; - case 4: - snprintf(str, sizeof(str), "0x%8.8x", value.uint32); - break; - case 8: - snprintf(str, sizeof(str), "0x%16.16llx", value.uint64); - break; - case 16: - snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0], - value.v_uint64[1]); - break; - default: - strlcpy(str, "0x", 3); - pos = str + 2; - for (uint32_t i = 0; i < info.size; ++i) { - if (pos < end) - pos += - snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]); - } - break; - } - } else { - switch (info.type) { - case Uint: - switch (info.size) { - case 1: - snprintf(str, sizeof(str), "%u", value.uint8); - break; - case 2: - snprintf(str, sizeof(str), "%u", value.uint16); - break; - case 4: - snprintf(str, sizeof(str), "%u", value.uint32); - break; - case 8: - snprintf(str, sizeof(str), "%llu", value.uint64); - break; - default: - snprintf(str, sizeof(str), "error: unsupported uint byte size %d.", - info.size); - break; - } - break; - - case Sint: - switch (info.size) { - case 1: - snprintf(str, sizeof(str), "%d", value.sint8); - break; - case 2: - snprintf(str, sizeof(str), "%d", value.sint16); - break; - case 4: - snprintf(str, sizeof(str), "%d", value.sint32); - break; - case 8: - snprintf(str, sizeof(str), "%lld", value.sint64); - break; - default: - snprintf(str, sizeof(str), "error: unsupported sint byte size %d.", - info.size); - break; - } - break; - - case IEEE754: - switch (info.size) { - case 4: - snprintf(str, sizeof(str), "%f", value.float32); - break; - case 8: - snprintf(str, sizeof(str), "%g", value.float64); - break; - default: - snprintf(str, sizeof(str), "error: unsupported float byte size %d.", - info.size); - break; - } - break; - - case Vector: - if (info.size > 0) { - switch (info.format) { - case VectorOfSInt8: - snprintf(str, sizeof(str), "%s", "sint8 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]); - } - strlcat(str, " }", sizeof(str)); - break; - - default: - DNBLogError( - "unsupported vector format %d, defaulting to hex bytes.", - info.format); - [[clang::fallthrough]]; - case VectorOfUInt8: - snprintf(str, sizeof(str), "%s", "uint8 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]); - } - break; - - case VectorOfSInt16: - snprintf(str, sizeof(str), "%s", "sint16 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 2; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]); - } - break; - - case VectorOfUInt16: - snprintf(str, sizeof(str), "%s", "uint16 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 2; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]); - } - break; - - case VectorOfSInt32: - snprintf(str, sizeof(str), "%s", "sint32 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 4; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]); - } - break; - - case VectorOfUInt32: - snprintf(str, sizeof(str), "%s", "uint32 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 4; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += - snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]); - } - break; - - case VectorOfFloat32: - snprintf(str, sizeof(str), "%s", "float32 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 4; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%f", value.v_float32[i]); - } - break; - - case VectorOfUInt128: - snprintf(str, sizeof(str), "%s", "uint128 { "); - pos = str + strlen(str); - for (uint32_t i = 0; i < info.size / 16; ++i) { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx", - value.v_uint64[i], value.v_uint64[i + 1]); - } - break; - } - strlcat(str, " }", sizeof(str)); - } else { - snprintf(str, sizeof(str), "error: unsupported vector size %d.", - info.size); - } - break; - - default: - snprintf(str, sizeof(str), "error: unsupported register type %d.", - info.type); - break; - } - } - - DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : ""); - } -} diff --git a/tools/debugserver/source/DNBRegisterInfo.h b/tools/debugserver/source/DNBRegisterInfo.h deleted file mode 100644 index d665e3cb9485..000000000000 --- a/tools/debugserver/source/DNBRegisterInfo.h +++ /dev/null @@ -1,30 +0,0 @@ -//===-- DNBRegisterInfo.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 8/3/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBRegisterInfo_h__ -#define __DNBRegisterInfo_h__ - -#include "DNBDefs.h" -#include <stdint.h> -#include <stdio.h> - -struct DNBRegisterValueClass : public DNBRegisterValue { -#ifdef __cplusplus - DNBRegisterValueClass(const DNBRegisterInfo *regInfo = NULL); - void Clear(); - void Dump(const char *pre, const char *post) const; - bool IsValid() const; -#endif -}; - -#endif diff --git a/tools/debugserver/source/DNBRuntimeAction.h b/tools/debugserver/source/DNBRuntimeAction.h deleted file mode 100644 index 85d7bc1df0a5..000000000000 --- a/tools/debugserver/source/DNBRuntimeAction.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- DNBRuntimeAction.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 10/8/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBRuntimeAction_h__ -#define __DNBRuntimeAction_h__ - -class DNBRuntimeAction { - virtual void Initialize(nub_process_t pid) = 0; - virtual void ProcessStateChanged(nub_state_t state) = 0; - virtual void SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, - nub_size_t num_image_infos) = 0; -}; - -#endif // #ifndef __DNBRuntimeAction_h__ diff --git a/tools/debugserver/source/DNBThreadResumeActions.cpp b/tools/debugserver/source/DNBThreadResumeActions.cpp deleted file mode 100644 index 4a97abc20e24..000000000000 --- a/tools/debugserver/source/DNBThreadResumeActions.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===-- DNBThreadResumeActions.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 03/13/2010 -// -//===----------------------------------------------------------------------===// - -#include "DNBThreadResumeActions.h" - -DNBThreadResumeActions::DNBThreadResumeActions() - : m_actions(), m_signal_handled() {} - -DNBThreadResumeActions::DNBThreadResumeActions( - const DNBThreadResumeAction *actions, size_t num_actions) - : m_actions(), m_signal_handled() { - if (actions && num_actions) { - m_actions.assign(actions, actions + num_actions); - m_signal_handled.assign(num_actions, false); - } -} - -DNBThreadResumeActions::DNBThreadResumeActions(nub_state_t default_action, - int signal) - : m_actions(), m_signal_handled() { - SetDefaultThreadActionIfNeeded(default_action, signal); -} - -void DNBThreadResumeActions::Append(const DNBThreadResumeAction &action) { - m_actions.push_back(action); - m_signal_handled.push_back(false); -} - -void DNBThreadResumeActions::AppendAction(nub_thread_t tid, nub_state_t state, - int signal, nub_addr_t addr) { - DNBThreadResumeAction action = {tid, state, signal, addr}; - Append(action); -} - -const DNBThreadResumeAction * -DNBThreadResumeActions::GetActionForThread(nub_thread_t tid, - bool default_ok) const { - const size_t num_actions = m_actions.size(); - for (size_t i = 0; i < num_actions; ++i) { - if (m_actions[i].tid == tid) - return &m_actions[i]; - } - if (default_ok && tid != INVALID_NUB_THREAD) - return GetActionForThread(INVALID_NUB_THREAD, false); - return NULL; -} - -size_t DNBThreadResumeActions::NumActionsWithState(nub_state_t state) const { - size_t count = 0; - const size_t num_actions = m_actions.size(); - for (size_t i = 0; i < num_actions; ++i) { - if (m_actions[i].state == state) - ++count; - } - return count; -} - -bool DNBThreadResumeActions::SetDefaultThreadActionIfNeeded(nub_state_t action, - int signal) { - if (GetActionForThread(INVALID_NUB_THREAD, true) == NULL) { - // There isn't a default action so we do need to set it. - DNBThreadResumeAction default_action = {INVALID_NUB_THREAD, action, signal, - INVALID_NUB_ADDRESS}; - m_actions.push_back(default_action); - m_signal_handled.push_back(false); - return true; // Return true as we did add the default action - } - return false; -} - -void DNBThreadResumeActions::SetSignalHandledForThread(nub_thread_t tid) const { - if (tid != INVALID_NUB_THREAD) { - const size_t num_actions = m_actions.size(); - for (size_t i = 0; i < num_actions; ++i) { - if (m_actions[i].tid == tid) - m_signal_handled[i] = true; - } - } -} diff --git a/tools/debugserver/source/DNBThreadResumeActions.h b/tools/debugserver/source/DNBThreadResumeActions.h deleted file mode 100644 index 40d2da03e9e4..000000000000 --- a/tools/debugserver/source/DNBThreadResumeActions.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- DNBThreadResumeActions.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 03/13/2010 -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBThreadResumeActions_h__ -#define __DNBThreadResumeActions_h__ - -#include <vector> - -#include "DNBDefs.h" - -class DNBThreadResumeActions { -public: - DNBThreadResumeActions(); - - DNBThreadResumeActions(nub_state_t default_action, int signal); - - DNBThreadResumeActions(const DNBThreadResumeAction *actions, - size_t num_actions); - - bool IsEmpty() const { return m_actions.empty(); } - - void Append(const DNBThreadResumeAction &action); - - void AppendAction(nub_thread_t tid, nub_state_t state, int signal = 0, - nub_addr_t addr = INVALID_NUB_ADDRESS); - - void AppendResumeAll() { AppendAction(INVALID_NUB_THREAD, eStateRunning); } - - void AppendSuspendAll() { AppendAction(INVALID_NUB_THREAD, eStateStopped); } - - void AppendStepAll() { AppendAction(INVALID_NUB_THREAD, eStateStepping); } - - const DNBThreadResumeAction *GetActionForThread(nub_thread_t tid, - bool default_ok) const; - - size_t NumActionsWithState(nub_state_t state) const; - - bool SetDefaultThreadActionIfNeeded(nub_state_t action, int signal); - - void SetSignalHandledForThread(nub_thread_t tid) const; - - const DNBThreadResumeAction *GetFirst() const { return m_actions.data(); } - - size_t GetSize() const { return m_actions.size(); } - - void Clear() { - m_actions.clear(); - m_signal_handled.clear(); - } - -protected: - std::vector<DNBThreadResumeAction> m_actions; - mutable std::vector<bool> m_signal_handled; -}; - -#endif // #ifndef __DNBThreadResumeActions_h__ diff --git a/tools/debugserver/source/DNBTimer.h b/tools/debugserver/source/DNBTimer.h deleted file mode 100644 index 881b8cdcde76..000000000000 --- a/tools/debugserver/source/DNBTimer.h +++ /dev/null @@ -1,145 +0,0 @@ -//===-- DNBTimer.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/13/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBTimer_h__ -#define __DNBTimer_h__ - -#include "DNBDefs.h" -#include "PThreadMutex.h" -#include <memory> -#include <stdint.h> -#include <sys/time.h> - -class DNBTimer { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - DNBTimer(bool threadSafe) : m_mutexAP() { - if (threadSafe) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - Reset(); - } - - DNBTimer(const DNBTimer &rhs) : m_mutexAP() { - // Create a new mutex to make this timer thread safe as well if - // the timer we are copying is thread safe - if (rhs.IsThreadSafe()) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - m_timeval = rhs.m_timeval; - } - - DNBTimer &operator=(const DNBTimer &rhs) { - // Create a new mutex to make this timer thread safe as well if - // the timer we are copying is thread safe - if (rhs.IsThreadSafe()) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - m_timeval = rhs.m_timeval; - return *this; - } - - ~DNBTimer() {} - - bool IsThreadSafe() const { return m_mutexAP.get() != NULL; } - //------------------------------------------------------------------ - // Reset the time value to now - //------------------------------------------------------------------ - void Reset() { - PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); - gettimeofday(&m_timeval, NULL); - } - //------------------------------------------------------------------ - // Get the total mircoseconds since Jan 1, 1970 - //------------------------------------------------------------------ - uint64_t TotalMicroSeconds() const { - PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); - return (uint64_t)(m_timeval.tv_sec) * 1000000ull + - (uint64_t)m_timeval.tv_usec; - } - - void GetTime(uint64_t &sec, uint32_t &usec) const { - PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); - sec = m_timeval.tv_sec; - usec = m_timeval.tv_usec; - } - //------------------------------------------------------------------ - // Return the number of microseconds elapsed between now and the - // m_timeval - //------------------------------------------------------------------ - uint64_t ElapsedMicroSeconds(bool update) { - PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); - struct timeval now; - gettimeofday(&now, NULL); - uint64_t now_usec = - (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; - uint64_t this_usec = - (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; - uint64_t elapsed = now_usec - this_usec; - // Update the timer time value if requeseted - if (update) - m_timeval = now; - return elapsed; - } - - static uint64_t GetTimeOfDay() { - struct timeval now; - gettimeofday(&now, NULL); - uint64_t now_usec = - (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; - return now_usec; - } - - static void OffsetTimeOfDay(struct timespec *ts, - __darwin_time_t sec_offset = 0, - long nsec_offset = 0) { - if (ts == NULL) - return; - // Get the current time in a timeval structure - struct timeval now; - gettimeofday(&now, NULL); - // Morph it into a timespec - TIMEVAL_TO_TIMESPEC(&now, ts); - // Offset the timespec if requested - if (sec_offset != 0 || nsec_offset != 0) { - // Offset the nano seconds - ts->tv_nsec += nsec_offset; - // Offset the seconds taking into account a nano-second overflow - ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; - // Trim the nanoseconds back there was an overflow - ts->tv_nsec = ts->tv_nsec % 1000000000; - } - } - static bool TimeOfDayLaterThan(struct timespec &ts) { - struct timespec now; - OffsetTimeOfDay(&now); - if (now.tv_sec > ts.tv_sec) - return true; - else if (now.tv_sec < ts.tv_sec) - return false; - else { - if (now.tv_nsec > ts.tv_nsec) - return true; - else - return false; - } - } - -protected: - //------------------------------------------------------------------ - // Classes that inherit from DNBTimer can see and modify these - //------------------------------------------------------------------ - std::unique_ptr<PThreadMutex> m_mutexAP; - struct timeval m_timeval; -}; - -#endif // #ifndef __DNBTimer_h__ diff --git a/tools/debugserver/source/JSON.cpp b/tools/debugserver/source/JSON.cpp deleted file mode 100644 index 439918b6fcc4..000000000000 --- a/tools/debugserver/source/JSON.cpp +++ /dev/null @@ -1,585 +0,0 @@ -//===--------------------- JSON.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JSON.h" - -// C includes -#include <assert.h> -#include <limits.h> - -// C++ includes -#include "lldb/Host/StringConvert.h" -#include <iomanip> -#include <sstream> - -using namespace lldb_private; - -std::string JSONString::json_string_quote_metachars(const std::string &s) { - if (s.find('"') == std::string::npos) - return s; - - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); - for (size_t i = 0; i < s_size; i++) { - unsigned char ch = *(s_chars + i); - if (ch == '"') { - output.push_back('\\'); - } - output.push_back(ch); - } - return output; -} - -JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} - -JSONString::JSONString(const char *s) - : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {} - -JSONString::JSONString(const std::string &s) - : JSONValue(JSONValue::Kind::String), m_data(s) {} - -void JSONString::Write(std::ostream &s) { - s << "\"" << json_string_quote_metachars(m_data).c_str() << "\""; -} - -uint64_t JSONNumber::GetAsUnsigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return m_data.m_unsigned; - case DataType::Signed: - return (uint64_t)m_data.m_signed; - case DataType::Double: - return (uint64_t)m_data.m_double; - } -} - -int64_t JSONNumber::GetAsSigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return (int64_t)m_data.m_unsigned; - case DataType::Signed: - return m_data.m_signed; - case DataType::Double: - return (int64_t)m_data.m_double; - } -} - -double JSONNumber::GetAsDouble() const { - switch (m_data_type) { - case DataType::Unsigned: - return (double)m_data.m_unsigned; - case DataType::Signed: - return (double)m_data.m_signed; - case DataType::Double: - return m_data.m_double; - } -} - -void JSONNumber::Write(std::ostream &s) { - switch (m_data_type) { - case DataType::Unsigned: - s << m_data.m_unsigned; - break; - case DataType::Signed: - s << m_data.m_signed; - break; - case DataType::Double: - // Set max precision to emulate %g. - s << std::setprecision(std::numeric_limits<double>::digits10 + 1); - s << m_data.m_double; - break; - } -} - -JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} - -void JSONTrue::Write(std::ostream &s) { s << "true"; } - -JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} - -void JSONFalse::Write(std::ostream &s) { s << "false"; } - -JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} - -void JSONNull::Write(std::ostream &s) { s << "null"; } - -JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} - -void JSONObject::Write(std::ostream &s) { - bool first = true; - s << '{'; - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s << ','; - JSONString key(iter->first); - JSONValue::SP value(iter->second); - key.Write(s); - s << ':'; - value->Write(s); - } - s << '}'; -} - -bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) { - if (key.empty() || nullptr == value.get()) - return false; - m_elements[key] = value; - return true; -} - -JSONValue::SP JSONObject::GetObject(const std::string &key) const { - auto iter = m_elements.find(key), end = m_elements.end(); - if (iter == end) - return JSONValue::SP(); - return iter->second; -} - -bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const { - auto value_sp = GetObject(key); - if (!value_sp) { - // The given key doesn't exist, so we have no value. - return false; - } - - if (JSONTrue::classof(value_sp.get())) { - // We have the value, and it is true. - value = true; - return true; - } else if (JSONFalse::classof(value_sp.get())) { - // We have the value, and it is false. - value = false; - return true; - } else { - // We don't have a valid bool value for the given key. - return false; - } -} - -bool JSONObject::GetObjectAsString(const std::string &key, - std::string &value) const { - auto value_sp = GetObject(key); - if (!value_sp) { - // The given key doesn't exist, so we have no value. - return false; - } - - if (!JSONString::classof(value_sp.get())) - return false; - - value = static_cast<JSONString *>(value_sp.get())->GetData(); - return true; -} - -JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {} - -void JSONArray::Write(std::ostream &s) { - bool first = true; - s << '['; - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s << ','; - (*iter)->Write(s); - } - s << ']'; -} - -bool JSONArray::SetObject(Index i, JSONValue::SP value) { - if (value.get() == nullptr) - return false; - if (i < m_elements.size()) { - m_elements[i] = value; - return true; - } - if (i == m_elements.size()) { - m_elements.push_back(value); - return true; - } - return false; -} - -bool JSONArray::AppendObject(JSONValue::SP value) { - if (value.get() == nullptr) - return false; - m_elements.push_back(value); - return true; -} - -JSONValue::SP JSONArray::GetObject(Index i) { - if (i < m_elements.size()) - return m_elements[i]; - return JSONValue::SP(); -} - -JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); } - -JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {} - -JSONParser::Token JSONParser::GetToken(std::string &value) { - std::ostringstream error; - - value.clear(); - SkipSpaces(); - const uint64_t start_index = m_index; - const char ch = GetChar(); - switch (ch) { - case '{': - return Token::ObjectStart; - case '}': - return Token::ObjectEnd; - case '[': - return Token::ArrayStart; - case ']': - return Token::ArrayEnd; - case ',': - return Token::Comma; - case ':': - return Token::Colon; - case '\0': - return Token::EndOfFile; - case 't': - if (GetChar() == 'r') - if (GetChar() == 'u') - if (GetChar() == 'e') - return Token::True; - break; - - case 'f': - if (GetChar() == 'a') - if (GetChar() == 'l') - if (GetChar() == 's') - if (GetChar() == 'e') - return Token::False; - break; - - case 'n': - if (GetChar() == 'u') - if (GetChar() == 'l') - if (GetChar() == 'l') - return Token::Null; - break; - - case '"': { - while (1) { - bool was_escaped = false; - int escaped_ch = GetEscapedChar(was_escaped); - if (escaped_ch == -1) { - error << "error: an error occurred getting a character from offset " - << start_index; - value = error.str(); - return Token::Status; - - } else { - const bool is_end_quote = escaped_ch == '"'; - const bool is_null = escaped_ch == 0; - if (was_escaped || (!is_end_quote && !is_null)) { - if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) { - value.append(1, (char)escaped_ch); - } else { - error << "error: wide character support is needed for unicode " - "character 0x" - << std::setprecision(4) << std::hex << escaped_ch; - error << " at offset " << start_index; - value = error.str(); - return Token::Status; - } - } else if (is_end_quote) { - return Token::String; - } else if (is_null) { - value = "error: missing end quote for string"; - return Token::Status; - } - } - } - } break; - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - bool done = false; - bool got_decimal_point = false; - uint64_t exp_index = 0; - bool got_int_digits = (ch >= '0') && (ch <= '9'); - bool got_frac_digits = false; - bool got_exp_digits = false; - while (!done) { - const char next_ch = PeekChar(); - switch (next_ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (exp_index != 0) { - got_exp_digits = true; - } else if (got_decimal_point) { - got_frac_digits = true; - } else { - got_int_digits = true; - } - ++m_index; // Skip this character - break; - - case '.': - if (got_decimal_point) { - error << "error: extra decimal point found at offset " << start_index; - value = error.str(); - return Token::Status; - } else { - got_decimal_point = true; - ++m_index; // Skip this character - } - break; - - case 'e': - case 'E': - if (exp_index != 0) { - error << "error: extra exponent character found at offset " - << start_index; - value = error.str(); - return Token::Status; - } else { - exp_index = m_index; - ++m_index; // Skip this character - } - break; - - case '+': - case '-': - // The '+' and '-' can only come after an exponent character... - if (exp_index == m_index - 1) { - ++m_index; // Skip the exponent sign character - } else { - error << "error: unexpected " << next_ch << " character at offset " - << start_index; - value = error.str(); - return Token::Status; - } - break; - - default: - done = true; - break; - } - } - - if (m_index > start_index) { - value = m_packet.substr(start_index, m_index - start_index); - if (got_decimal_point) { - if (exp_index != 0) { - // We have an exponent, make sure we got exponent digits - if (got_exp_digits) { - return Token::Float; - } else { - error << "error: got exponent character but no exponent digits at " - "offset in float value \"" - << value.c_str() << "\""; - value = error.str(); - return Token::Status; - } - } else { - // No exponent, but we need at least one decimal after the decimal - // point - if (got_frac_digits) { - return Token::Float; - } else { - error << "error: no digits after decimal point \"" << value.c_str() - << "\""; - value = error.str(); - return Token::Status; - } - } - } else { - // No decimal point - if (got_int_digits) { - // We need at least some integer digits to make an integer - return Token::Integer; - } else { - error << "error: no digits negate sign \"" << value.c_str() << "\""; - value = error.str(); - return Token::Status; - } - } - } else { - error << "error: invalid number found at offset " << start_index; - value = error.str(); - return Token::Status; - } - } break; - default: - break; - } - error << "error: failed to parse token at offset " << start_index - << " (around character '" << ch << "')"; - value = error.str(); - return Token::Status; -} - -int JSONParser::GetEscapedChar(bool &was_escaped) { - was_escaped = false; - const char ch = GetChar(); - if (ch == '\\') { - was_escaped = true; - const char ch2 = GetChar(); - switch (ch2) { - case '"': - case '\\': - case '/': - default: - break; - - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'u': { - const int hi_byte = DecodeHexU8(); - const int lo_byte = DecodeHexU8(); - if (hi_byte >= 0 && lo_byte >= 0) - return hi_byte << 8 | lo_byte; - return -1; - } break; - } - return ch2; - } - return ch; -} - -JSONValue::SP JSONParser::ParseJSONObject() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed - // by the time this function is called - std::unique_ptr<JSONObject> dict_up(new JSONObject()); - - std::string value; - std::string key; - while (1) { - JSONParser::Token token = GetToken(value); - - if (token == JSONParser::Token::String) { - key.swap(value); - token = GetToken(value); - if (token == JSONParser::Token::Colon) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - dict_up->SetObject(key, value_sp); - else - break; - } - } else if (token == JSONParser::Token::ObjectEnd) { - return JSONValue::SP(dict_up.release()); - } else if (token == JSONParser::Token::Comma) { - continue; - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONArray() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed - // by the time this function is called - std::unique_ptr<JSONArray> array_up(new JSONArray()); - - std::string value; - std::string key; - while (1) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - array_up->AppendObject(value_sp); - else - break; - - JSONParser::Token token = GetToken(value); - if (token == JSONParser::Token::Comma) { - continue; - } else if (token == JSONParser::Token::ArrayEnd) { - return JSONValue::SP(array_up.release()); - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONValue() { - std::string value; - const JSONParser::Token token = GetToken(value); - switch (token) { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(); - - case JSONParser::Token::Integer: { - if (value.front() == '-') { - bool success = false; - int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success); - if (success) - return JSONValue::SP(new JSONNumber(sval)); - } else { - bool success = false; - uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); - if (success) - return JSONValue::SP(new JSONNumber(uval)); - } - } break; - - case JSONParser::Token::Float: { - bool success = false; - double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); - if (success) - return JSONValue::SP(new JSONNumber(val)); - } break; - - case JSONParser::Token::String: - return JSONValue::SP(new JSONString(value)); - - case JSONParser::Token::True: - return JSONValue::SP(new JSONTrue()); - - case JSONParser::Token::False: - return JSONValue::SP(new JSONFalse()); - - case JSONParser::Token::Null: - return JSONValue::SP(new JSONNull()); - - default: - break; - } - return JSONValue::SP(); -} diff --git a/tools/debugserver/source/JSON.h b/tools/debugserver/source/JSON.h deleted file mode 100644 index 252ff021f912..000000000000 --- a/tools/debugserver/source/JSON.h +++ /dev/null @@ -1,303 +0,0 @@ -//===---------------------JSON.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef utility_JSON_h_ -#define utility_JSON_h_ - -#include "StdStringExtractor.h" - -// C includes -#include <inttypes.h> -#include <stdint.h> - -// C++ includes -#include <map> -#include <memory> -#include <ostream> -#include <string> -#include <vector> - -class JSONValue { -public: - virtual void Write(std::ostream &s) = 0; - - typedef std::shared_ptr<JSONValue> SP; - - enum class Kind { String, Number, True, False, Null, Object, Array }; - - JSONValue(Kind k) : m_kind(k) {} - - Kind GetKind() const { return m_kind; } - - virtual ~JSONValue() = default; - -private: - const Kind m_kind; -}; - -class JSONString : public JSONValue { -public: - JSONString(); - JSONString(const char *s); - JSONString(const std::string &s); - - JSONString(const JSONString &s) = delete; - JSONString &operator=(const JSONString &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONString> SP; - - std::string GetData() { return m_data; } - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::String; - } - - ~JSONString() override = default; - -private: - static std::string json_string_quote_metachars(const std::string &); - - std::string m_data; -}; - -class JSONNumber : public JSONValue { -public: - typedef std::shared_ptr<JSONNumber> SP; - - // We cretae a constructor for all integer and floating point type with using - // templates and - // SFINAE to avoid having ambiguous overloads because of the implicit type - // promotion. If we - // would have constructors only with int64_t, uint64_t and double types then - // constructing a - // JSONNumber from an int32_t (or any other similar type) would fail to - // compile. - - template <typename T, typename std::enable_if< - std::is_integral<T>::value && - std::is_unsigned<T>::value>::type * = nullptr> - explicit JSONNumber(T u) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) { - m_data.m_unsigned = u; - } - - template <typename T, - typename std::enable_if<std::is_integral<T>::value && - std::is_signed<T>::value>::type * = nullptr> - explicit JSONNumber(T s) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) { - m_data.m_signed = s; - } - - template <typename T, typename std::enable_if< - std::is_floating_point<T>::value>::type * = nullptr> - explicit JSONNumber(T d) - : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) { - m_data.m_double = d; - } - - ~JSONNumber() override = default; - - JSONNumber(const JSONNumber &s) = delete; - JSONNumber &operator=(const JSONNumber &s) = delete; - - void Write(std::ostream &s) override; - - uint64_t GetAsUnsigned() const; - - int64_t GetAsSigned() const; - - double GetAsDouble() const; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Number; - } - -private: - enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type; - - union { - uint64_t m_unsigned; - int64_t m_signed; - double m_double; - } m_data; -}; - -class JSONTrue : public JSONValue { -public: - JSONTrue(); - - JSONTrue(const JSONTrue &s) = delete; - JSONTrue &operator=(const JSONTrue &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONTrue> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::True; - } - - ~JSONTrue() override = default; -}; - -class JSONFalse : public JSONValue { -public: - JSONFalse(); - - JSONFalse(const JSONFalse &s) = delete; - JSONFalse &operator=(const JSONFalse &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONFalse> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::False; - } - - ~JSONFalse() override = default; -}; - -class JSONNull : public JSONValue { -public: - JSONNull(); - - JSONNull(const JSONNull &s) = delete; - JSONNull &operator=(const JSONNull &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONNull> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Null; - } - - ~JSONNull() override = default; -}; - -class JSONObject : public JSONValue { -public: - JSONObject(); - - JSONObject(const JSONObject &s) = delete; - JSONObject &operator=(const JSONObject &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONObject> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Object; - } - - bool SetObject(const std::string &key, JSONValue::SP value); - - JSONValue::SP GetObject(const std::string &key) const; - - // ------------------------------------------------------------------------- - /// Return keyed value as bool - /// - /// @param[in] key - /// The value of the key to lookup - /// - /// @param[out] value - /// The value of the key as a bool. Undefined if the key doesn't - /// exist or if the key is not either true or false. - /// - /// @return - /// true if the key existed as was a bool value; false otherwise. - /// Note the return value is *not* the value of the bool, use - /// \b value for that. - // ------------------------------------------------------------------------- - bool GetObjectAsBool(const std::string &key, bool &value) const; - - bool GetObjectAsString(const std::string &key, std::string &value) const; - - ~JSONObject() override = default; - -private: - typedef std::map<std::string, JSONValue::SP> Map; - typedef Map::iterator Iterator; - Map m_elements; -}; - -class JSONArray : public JSONValue { -public: - JSONArray(); - - JSONArray(const JSONArray &s) = delete; - JSONArray &operator=(const JSONArray &s) = delete; - - void Write(std::ostream &s) override; - - typedef std::shared_ptr<JSONArray> SP; - - static bool classof(const JSONValue *V) { - return V->GetKind() == JSONValue::Kind::Array; - } - -private: - typedef std::vector<JSONValue::SP> Vector; - typedef Vector::iterator Iterator; - typedef Vector::size_type Index; - typedef Vector::size_type Size; - -public: - bool SetObject(Index i, JSONValue::SP value); - - bool AppendObject(JSONValue::SP value); - - JSONValue::SP GetObject(Index i); - - Size GetNumElements(); - - ~JSONArray() override = default; - - Vector m_elements; -}; - -class JSONParser : public StdStringExtractor { -public: - enum Token { - Invalid, - Status, - ObjectStart, - ObjectEnd, - ArrayStart, - ArrayEnd, - Comma, - Colon, - String, - Integer, - Float, - True, - False, - Null, - EndOfFile - }; - - JSONParser(const char *cstr); - - int GetEscapedChar(bool &was_escaped); - - Token GetToken(std::string &value); - - JSONValue::SP ParseJSONValue(); - -protected: - JSONValue::SP ParseJSONObject(); - - JSONValue::SP ParseJSONArray(); -}; - -#endif // utility_JSON_h_ diff --git a/tools/debugserver/source/JSONGenerator.h b/tools/debugserver/source/JSONGenerator.h deleted file mode 100644 index 0ac5e0bb768c..000000000000 --- a/tools/debugserver/source/JSONGenerator.h +++ /dev/null @@ -1,317 +0,0 @@ -//===-- JSONGenerator.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __JSONGenerator_h_ -#define __JSONGenerator_h_ - - -#include <iomanip> -#include <sstream> -#include <string> -#include <utility> -#include <vector> - -//---------------------------------------------------------------------- -/// @class JSONGenerator JSONGenerator.h -/// A class which can construct structured data for the sole purpose -/// of printing it in JSON format. -/// -/// A stripped down version of lldb's StructuredData objects which are much -/// general purpose. This variant is intended only for assembling information -/// and printing it as a JSON string. -//---------------------------------------------------------------------- - -class JSONGenerator { -public: - class Object; - class Array; - class Integer; - class Float; - class Boolean; - class String; - class Dictionary; - class Generic; - - typedef std::shared_ptr<Object> ObjectSP; - typedef std::shared_ptr<Array> ArraySP; - typedef std::shared_ptr<Integer> IntegerSP; - typedef std::shared_ptr<Float> FloatSP; - typedef std::shared_ptr<Boolean> BooleanSP; - typedef std::shared_ptr<String> StringSP; - typedef std::shared_ptr<Dictionary> DictionarySP; - typedef std::shared_ptr<Generic> GenericSP; - - enum class Type { - eTypeInvalid = -1, - eTypeNull = 0, - eTypeGeneric, - eTypeArray, - eTypeInteger, - eTypeFloat, - eTypeBoolean, - eTypeString, - eTypeDictionary - }; - - class Object : public std::enable_shared_from_this<Object> { - public: - Object(Type t = Type::eTypeInvalid) : m_type(t) {} - - virtual ~Object() {} - - virtual bool IsValid() const { return true; } - - virtual void Clear() { m_type = Type::eTypeInvalid; } - - Type GetType() const { return m_type; } - - void SetType(Type t) { m_type = t; } - - Array *GetAsArray() { - if (m_type == Type::eTypeArray) - return (Array *)this; - return NULL; - } - - Dictionary *GetAsDictionary() { - if (m_type == Type::eTypeDictionary) - return (Dictionary *)this; - return NULL; - } - - Integer *GetAsInteger() { - if (m_type == Type::eTypeInteger) - return (Integer *)this; - return NULL; - } - - Float *GetAsFloat() { - if (m_type == Type::eTypeFloat) - return (Float *)this; - return NULL; - } - - Boolean *GetAsBoolean() { - if (m_type == Type::eTypeBoolean) - return (Boolean *)this; - return NULL; - } - - String *GetAsString() { - if (m_type == Type::eTypeString) - return (String *)this; - return NULL; - } - - Generic *GetAsGeneric() { - if (m_type == Type::eTypeGeneric) - return (Generic *)this; - return NULL; - } - - virtual void Dump(std::ostream &s) const = 0; - - private: - Type m_type; - }; - - class Array : public Object { - public: - Array() : Object(Type::eTypeArray) {} - - virtual ~Array() {} - - void AddItem(ObjectSP item) { m_items.push_back(item); } - - void Dump(std::ostream &s) const override { - s << "["; - const size_t arrsize = m_items.size(); - for (size_t i = 0; i < arrsize; ++i) { - m_items[i]->Dump(s); - if (i + 1 < arrsize) - s << ","; - } - s << "]"; - } - - protected: - typedef std::vector<ObjectSP> collection; - collection m_items; - }; - - class Integer : public Object { - public: - Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {} - - virtual ~Integer() {} - - void SetValue(uint64_t value) { m_value = value; } - - void Dump(std::ostream &s) const override { s << m_value; } - - protected: - uint64_t m_value; - }; - - class Float : public Object { - public: - Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {} - - virtual ~Float() {} - - void SetValue(double value) { m_value = value; } - - void Dump(std::ostream &s) const override { s << m_value; } - - protected: - double m_value; - }; - - class Boolean : public Object { - public: - Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {} - - virtual ~Boolean() {} - - void SetValue(bool value) { m_value = value; } - - void Dump(std::ostream &s) const override { - if (m_value) - s << "true"; - else - s << "false"; - } - - protected: - bool m_value; - }; - - class String : public Object { - public: - String() : Object(Type::eTypeString), m_value() {} - - String(const std::string &s) : Object(Type::eTypeString), m_value(s) {} - - String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {} - - void SetValue(const std::string &string) { m_value = string; } - - void Dump(std::ostream &s) const override { - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize; ++i) { - char ch = m_value[i]; - if (ch == '"') - quoted.push_back('\\'); - quoted.push_back(ch); - } - s << '"' << quoted.c_str() << '"'; - } - - protected: - std::string m_value; - }; - - class Dictionary : public Object { - public: - Dictionary() : Object(Type::eTypeDictionary), m_dict() {} - - virtual ~Dictionary() {} - - void AddItem(std::string key, ObjectSP value) { - m_dict.push_back(Pair(key, value)); - } - - void AddIntegerItem(std::string key, uint64_t value) { - AddItem(key, ObjectSP(new Integer(value))); - } - - void AddFloatItem(std::string key, double value) { - AddItem(key, ObjectSP(new Float(value))); - } - - void AddStringItem(std::string key, std::string value) { - AddItem(key, ObjectSP(new String(std::move(value)))); - } - - void AddBytesAsHexASCIIString(std::string key, const uint8_t *src, - size_t src_len) { - if (src && src_len) { - std::ostringstream strm; - for (size_t i = 0; i < src_len; i++) - strm << std::setfill('0') << std::hex << std::right << std::setw(2) - << ((uint32_t)(src[i])); - AddItem(key, ObjectSP(new String(std::move(strm.str())))); - } else { - AddItem(key, ObjectSP(new String())); - } - } - - void AddBooleanItem(std::string key, bool value) { - AddItem(key, ObjectSP(new Boolean(value))); - } - - void Dump(std::ostream &s) const override { - bool have_printed_one_elem = false; - s << "{"; - for (collection::const_iterator iter = m_dict.begin(); - iter != m_dict.end(); ++iter) { - if (!have_printed_one_elem) { - have_printed_one_elem = true; - } else { - s << ","; - } - s << "\"" << iter->first.c_str() << "\":"; - iter->second->Dump(s); - } - s << "}"; - } - - protected: - // Keep the dictionary as a vector so the dictionary doesn't reorder itself - // when you dump it - // We aren't accessing keys by name, so this won't affect performance - typedef std::pair<std::string, ObjectSP> Pair; - typedef std::vector<Pair> collection; - collection m_dict; - }; - - class Null : public Object { - public: - Null() : Object(Type::eTypeNull) {} - - virtual ~Null() {} - - bool IsValid() const override { return false; } - - void Dump(std::ostream &s) const override { s << "null"; } - - protected: - }; - - class Generic : public Object { - public: - explicit Generic(void *object = nullptr) - : Object(Type::eTypeGeneric), m_object(object) {} - - void SetValue(void *value) { m_object = value; } - - void *GetValue() const { return m_object; } - - bool IsValid() const override { return m_object != nullptr; } - - void Dump(std::ostream &s) const override; - - private: - void *m_object; - }; - -}; // class JSONGenerator - -#endif // __JSONGenerator_h_ diff --git a/tools/debugserver/source/MacOSX/CFBundle.cpp b/tools/debugserver/source/MacOSX/CFBundle.cpp deleted file mode 100644 index 40f82b4243e0..000000000000 --- a/tools/debugserver/source/MacOSX/CFBundle.cpp +++ /dev/null @@ -1,80 +0,0 @@ -//===-- CFBundle.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#include "CFBundle.h" -#include "CFString.h" - -//---------------------------------------------------------------------- -// CFBundle constructor -//---------------------------------------------------------------------- -CFBundle::CFBundle(const char *path) - : CFReleaser<CFBundleRef>(), m_bundle_url() { - if (path && path[0]) - SetPath(path); -} - -//---------------------------------------------------------------------- -// CFBundle copy constructor -//---------------------------------------------------------------------- -CFBundle::CFBundle(const CFBundle &rhs) - : CFReleaser<CFBundleRef>(rhs), m_bundle_url(rhs.m_bundle_url) {} - -//---------------------------------------------------------------------- -// CFBundle copy constructor -//---------------------------------------------------------------------- -CFBundle &CFBundle::operator=(const CFBundle &rhs) { - if (this != &rhs) - *this = rhs; - return *this; -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -CFBundle::~CFBundle() {} - -//---------------------------------------------------------------------- -// Set the path for a bundle by supplying a -//---------------------------------------------------------------------- -bool CFBundle::SetPath(const char *path) { - CFAllocatorRef alloc = kCFAllocatorDefault; - // Release our old bundle and ULR - reset(); // This class is a CFReleaser<CFBundleRef> - m_bundle_url.reset(); - // Make a CFStringRef from the supplied path - CFString cf_path; - cf_path.SetFileSystemRepresentation(path); - if (cf_path.get()) { - // Make our Bundle URL - m_bundle_url.reset(::CFURLCreateWithFileSystemPath( - alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); - if (m_bundle_url.get()) { - reset(::CFBundleCreate(alloc, m_bundle_url.get())); - } - } - return get() != NULL; -} - -CFStringRef CFBundle::GetIdentifier() const { - CFBundleRef bundle = get(); - if (bundle != NULL) - return ::CFBundleGetIdentifier(bundle); - return NULL; -} - -CFURLRef CFBundle::CopyExecutableURL() const { - CFBundleRef bundle = get(); - if (bundle != NULL) - return CFBundleCopyExecutableURL(bundle); - return NULL; -} diff --git a/tools/debugserver/source/MacOSX/CFBundle.h b/tools/debugserver/source/MacOSX/CFBundle.h deleted file mode 100644 index 09957af534b3..000000000000 --- a/tools/debugserver/source/MacOSX/CFBundle.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- CFBundle.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFBundle_h__ -#define __CFBundle_h__ - -#include "CFUtils.h" - -class CFBundle : public CFReleaser<CFBundleRef> { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFBundle(const char *path = NULL); - CFBundle(const CFBundle &rhs); - CFBundle &operator=(const CFBundle &rhs); - virtual ~CFBundle(); - bool SetPath(const char *path); - - CFStringRef GetIdentifier() const; - - CFURLRef CopyExecutableURL() const; - -protected: - CFReleaser<CFURLRef> m_bundle_url; -}; - -#endif // #ifndef __CFBundle_h__ diff --git a/tools/debugserver/source/MacOSX/CFString.cpp b/tools/debugserver/source/MacOSX/CFString.cpp deleted file mode 100644 index 84ad56774d7c..000000000000 --- a/tools/debugserver/source/MacOSX/CFString.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//===-- CFString.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#include "CFString.h" -#include <glob.h> -#include <string> - -//---------------------------------------------------------------------- -// CFString constructor -//---------------------------------------------------------------------- -CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} - -//---------------------------------------------------------------------- -// CFString copy constructor -//---------------------------------------------------------------------- -CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {} - -//---------------------------------------------------------------------- -// CFString copy constructor -//---------------------------------------------------------------------- -CFString &CFString::operator=(const CFString &rhs) { - if (this != &rhs) - *this = rhs; - return *this; -} - -CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding) - : CFReleaser<CFStringRef>() { - if (cstr && cstr[0]) { - reset( - ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); - } -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -CFString::~CFString() {} - -const char *CFString::GetFileSystemRepresentation(std::string &s) { - return CFString::FileSystemRepresentation(get(), s); -} - -CFStringRef CFString::SetFileSystemRepresentation(const char *path) { - CFStringRef new_value = NULL; - if (path && path[0]) - new_value = - ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); - reset(new_value); - return get(); -} - -CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { - CFStringRef new_value = NULL; - if (cf_type != NULL) { - CFTypeID cf_type_id = ::CFGetTypeID(cf_type); - - if (cf_type_id == ::CFStringGetTypeID()) { - // Retain since we are using the existing object - new_value = (CFStringRef)::CFRetain(cf_type); - } else if (cf_type_id == ::CFURLGetTypeID()) { - new_value = - ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); - } - } - reset(new_value); - return get(); -} - -CFStringRef -CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) { - std::string expanded_path; - if (CFString::GlobPath(path, expanded_path)) - SetFileSystemRepresentation(expanded_path.c_str()); - else - reset(); - return get(); -} - -const char *CFString::UTF8(std::string &str) { - return CFString::UTF8(get(), str); -} - -// Static function that puts a copy of the UTF8 contents of CF_STR into STR -// and returns the C string pointer that is contained in STR when successful, -// else -// NULL is returned. This allows the std::string parameter to own the extracted -// string, -// and also allows that string to be returned as a C string pointer that can be -// used. - -const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { - if (cf_str) { - const CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex max_utf8_str_len = CFStringGetLength(cf_str); - max_utf8_str_len = - CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); - if (max_utf8_str_len > 0) { - str.resize(max_utf8_str_len); - if (!str.empty()) { - if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { - str.resize(strlen(str.c_str())); - return str.c_str(); - } - } - } - } - return NULL; -} - -// Static function that puts a copy of the file system representation of CF_STR -// into STR and returns the C string pointer that is contained in STR when -// successful, else NULL is returned. This allows the std::string parameter -// to own the extracted string, and also allows that string to be returned as -// a C string pointer that can be used. - -const char *CFString::FileSystemRepresentation(CFStringRef cf_str, - std::string &str) { - if (cf_str) { - CFIndex max_length = - ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); - if (max_length > 0) { - str.resize(max_length); - if (!str.empty()) { - if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], - str.size())) { - str.erase(::strlen(str.c_str())); - return str.c_str(); - } - } - } - } - str.erase(); - return NULL; -} - -CFIndex CFString::GetLength() const { - CFStringRef str = get(); - if (str) - return CFStringGetLength(str); - return 0; -} - -const char *CFString::GlobPath(const char *path, std::string &expanded_path) { - glob_t globbuf; - if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { - expanded_path = globbuf.gl_pathv[0]; - ::globfree(&globbuf); - } else - expanded_path.clear(); - - return expanded_path.c_str(); -} diff --git a/tools/debugserver/source/MacOSX/CFString.h b/tools/debugserver/source/MacOSX/CFString.h deleted file mode 100644 index 18d60a5a74bd..000000000000 --- a/tools/debugserver/source/MacOSX/CFString.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- CFString.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/16/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFString_h__ -#define __CFString_h__ - -#include "CFUtils.h" -#include <iosfwd> - -class CFString : public CFReleaser<CFStringRef> { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFString(CFStringRef cf_str = NULL); - CFString(const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); - CFString(const CFString &rhs); - CFString &operator=(const CFString &rhs); - virtual ~CFString(); - - const char *GetFileSystemRepresentation(std::string &str); - CFStringRef SetFileSystemRepresentation(const char *path); - CFStringRef SetFileSystemRepresentationFromCFType(CFTypeRef cf_type); - CFStringRef SetFileSystemRepresentationAndExpandTilde(const char *path); - const char *UTF8(std::string &str); - CFIndex GetLength() const; - static const char *UTF8(CFStringRef cf_str, std::string &str); - static const char *FileSystemRepresentation(CFStringRef cf_str, - std::string &str); - static const char *GlobPath(const char *path, std::string &expanded_path); -}; - -#endif // #ifndef __CFString_h__ diff --git a/tools/debugserver/source/MacOSX/CFUtils.h b/tools/debugserver/source/MacOSX/CFUtils.h deleted file mode 100644 index a904cd0ea6f0..000000000000 --- a/tools/debugserver/source/MacOSX/CFUtils.h +++ /dev/null @@ -1,78 +0,0 @@ -//===-- CFUtils.h -----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/5/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __CFUtils_h__ -#define __CFUtils_h__ - -#include <CoreFoundation/CoreFoundation.h> - -#ifdef __cplusplus - -//---------------------------------------------------------------------- -// Templatized CF helper class that can own any CF pointer and will -// call CFRelease() on any valid pointer it owns unless that pointer is -// explicitly released using the release() member function. -//---------------------------------------------------------------------- -template <class T> class CFReleaser { -public: - // Type names for the avlue - typedef T element_type; - - // Constructors and destructors - CFReleaser(T ptr = NULL) : _ptr(ptr) {} - CFReleaser(const CFReleaser ©) : _ptr(copy.get()) { - if (get()) - ::CFRetain(get()); - } - virtual ~CFReleaser() { reset(); } - - // Assignments - CFReleaser &operator=(const CFReleaser<T> ©) { - if (copy != *this) { - // Replace our owned pointer with the new one - reset(copy.get()); - // Retain the current pointer that we own - if (get()) - ::CFRetain(get()); - } - } - // Get the address of the contained type - T *ptr_address() { return &_ptr; } - - // Access the pointer itself - const T get() const { return _ptr; } - T get() { return _ptr; } - - // Set a new value for the pointer and CFRelease our old - // value if we had a valid one. - void reset(T ptr = NULL) { - if (ptr != _ptr) { - if (_ptr != NULL) - ::CFRelease(_ptr); - _ptr = ptr; - } - } - - // Release ownership without calling CFRelease - T release() { - T tmp = _ptr; - _ptr = NULL; - return tmp; - } - -private: - element_type _ptr; -}; - -#endif // #ifdef __cplusplus -#endif // #ifndef __CFUtils_h__ diff --git a/tools/debugserver/source/MacOSX/CMakeLists.txt b/tools/debugserver/source/MacOSX/CMakeLists.txt deleted file mode 100644 index 28877d122d94..000000000000 --- a/tools/debugserver/source/MacOSX/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ".*arm.*") - list(APPEND SOURCES arm/DNBArchImpl.cpp arm64/DNBArchImplARM64.cpp) - include_directories(${CURRENT_SOURCE_DIR}/arm ${CURRENT_SOURCE_DIR}/arm64) -endif() - -if(NOT CMAKE_OSX_ARCHITECTURES OR "${CMAKE_OSX_ARCHITECTURES}" MATCHES ".*86.*") - list(APPEND SOURCES i386/DNBArchImplI386.cpp x86_64/DNBArchImplX86_64.cpp) - include_directories(${CURRENT_SOURCE_DIR}/i386 ${CURRENT_SOURCE_DIR}/x86_64) -endif() - -if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ".*ppc.*") - list(APPEND SOURCES ppc/DNBArchImpl.cpp) - include_directories(${CURRENT_SOURCE_DIR}/ppc) -endif() - -add_subdirectory(DarwinLog) - -include_directories(..) - -include_directories(${LLDB_SOURCE_DIR}/tools/debugserver/source) -add_library(lldbDebugserverArchSupport - ${SOURCES} - ) diff --git a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp b/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp deleted file mode 100644 index 2cb653894db4..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//===-- ActivityStore.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ActivityStore.h" - -ActivityStore::ActivityStore() {} - -ActivityStore::~ActivityStore() {} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h b/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h deleted file mode 100644 index 35e0a85ad514..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h +++ /dev/null @@ -1,30 +0,0 @@ -//===-- ActivityStore.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ActivityStore_h -#define ActivityStore_h - -#include <string> - -#include "ActivityStreamSPI.h" - -class ActivityStore { -public: - virtual ~ActivityStore(); - - virtual const char *GetActivityForID(os_activity_id_t activity_id) const = 0; - - virtual std::string - GetActivityChainForID(os_activity_id_t activity_id) const = 0; - -protected: - ActivityStore(); -}; - -#endif /* ActivityStore_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h b/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h deleted file mode 100644 index 8aebc79e6ec8..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h +++ /dev/null @@ -1,191 +0,0 @@ -//===-- ActivityStreamAPI.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ActivityStreamSPI_h -#define ActivityStreamSPI_h - -#include <sys/time.h> -#include <xpc/xpc.h> - -#define OS_ACTIVITY_MAX_CALLSTACK 32 - -// Enums - -enum { - OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004, - OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008, - OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010, - OS_ACTIVITY_STREAM_DEBUG = 0x00000020, - OS_ACTIVITY_STREAM_BUFFERED = 0x00000040, - OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080, - OS_ACTIVITY_STREAM_INFO = 0x00000100, - OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200, - OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200 -}; -typedef uint32_t os_activity_stream_flag_t; - -enum { - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203, - - OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300, - - OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400, - OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480, - - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603, - - OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00, -}; -typedef uint32_t os_activity_stream_type_t; - -enum { - OS_ACTIVITY_STREAM_EVENT_STARTED = 1, - OS_ACTIVITY_STREAM_EVENT_STOPPED = 2, - OS_ACTIVITY_STREAM_EVENT_FAILED = 3, - OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4, - OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5, -}; -typedef uint32_t os_activity_stream_event_t; - -// Types - -typedef uint64_t os_activity_id_t; -typedef struct os_activity_stream_s *os_activity_stream_t; -typedef struct os_activity_stream_entry_s *os_activity_stream_entry_t; - -#define OS_ACTIVITY_STREAM_COMMON() \ - uint64_t trace_id; \ - uint64_t timestamp; \ - uint64_t thread; \ - const uint8_t *image_uuid; \ - const char *image_path; \ - struct timeval tv_gmt; \ - struct timezone tz; \ - uint32_t offset - -typedef struct os_activity_stream_common_s { - OS_ACTIVITY_STREAM_COMMON(); -} * os_activity_stream_common_t; - -struct os_activity_create_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *name; - os_activity_id_t creator_aid; - uint64_t unique_pid; -}; - -struct os_activity_transition_s { - OS_ACTIVITY_STREAM_COMMON(); - os_activity_id_t transition_id; -}; - -typedef struct os_log_message_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint32_t oversize_id; - uint8_t ttl; - bool persisted; -} * os_log_message_t; - -typedef struct os_trace_message_v2_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const void *buffer; - size_t bufferLen; - xpc_object_t __unsafe_unretained payload; -} * os_trace_message_v2_t; - -typedef struct os_activity_useraction_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *action; - bool persisted; -} * os_activity_useraction_t; - -typedef struct os_signpost_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint64_t duration_nsec; - uint32_t callstack_depth; - uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK]; -} * os_signpost_t; - -typedef struct os_activity_statedump_s { - OS_ACTIVITY_STREAM_COMMON(); - char *message; - size_t message_size; - char image_path_buffer[PATH_MAX]; -} * os_activity_statedump_t; - -struct os_activity_stream_entry_s { - os_activity_stream_type_t type; - - // information about the process streaming the data - pid_t pid; - uint64_t proc_id; - const uint8_t *proc_imageuuid; - const char *proc_imagepath; - - // the activity associated with this streamed event - os_activity_id_t activity_id; - os_activity_id_t parent_id; - - union { - struct os_activity_stream_common_s common; - struct os_activity_create_s activity_create; - struct os_activity_transition_s activity_transition; - struct os_log_message_s log_message; - struct os_trace_message_v2_s trace_message; - struct os_activity_useraction_s useraction; - struct os_signpost_s signpost; - struct os_activity_statedump_s statedump; - }; -}; - -// Blocks - -typedef bool (^os_activity_stream_block_t)(os_activity_stream_entry_t entry, - int error); - -typedef void (^os_activity_stream_event_block_t)( - os_activity_stream_t stream, os_activity_stream_event_t event); - -// SPI entry point prototypes - -typedef os_activity_stream_t (*os_activity_stream_for_pid_t)( - pid_t pid, os_activity_stream_flag_t flags, - os_activity_stream_block_t stream_block); - -typedef void (*os_activity_stream_resume_t)(os_activity_stream_t stream); - -typedef void (*os_activity_stream_cancel_t)(os_activity_stream_t stream); - -typedef char *(*os_log_copy_formatted_message_t)(os_log_message_t log_message); - -typedef void (*os_activity_stream_set_event_handler_t)( - os_activity_stream_t stream, os_activity_stream_event_block_t block); - -#endif /* ActivityStreamSPI_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/CMakeLists.txt b/tools/debugserver/source/MacOSX/DarwinLog/CMakeLists.txt deleted file mode 100644 index dffa357f1e68..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Due to sources including headers like: -# #include "MacOSX/i386/DNBArchImplI386.h" -# we must include the grandparent directory... -include_directories(${LLDB_SOURCE_DIR}/tools/debugserver/source) - -add_library(lldbDebugserverDarwin_DarwinLog - ActivityStore.cpp - DarwinLogCollector.cpp - LogFilter.cpp - LogFilterChain.cpp - LogFilterExactMatch.cpp - LogFilterRegex.cpp - LogMessage.cpp - LogMessageOsLog.cpp - ) diff --git a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp b/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp deleted file mode 100644 index 1e833c4cb165..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp +++ /dev/null @@ -1,698 +0,0 @@ -//===-- DarwinLogCollector.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DarwinLogCollector.h" -#include "ActivityStreamSPI.h" - -#include <dlfcn.h> - -#include <cinttypes> -#include <mutex> -#include <vector> - -#include "DNB.h" -#include "DNBLog.h" -#include "DarwinLogTypes.h" -#include "LogFilterChain.h" -#include "LogFilterExactMatch.h" -#include "LogFilterRegex.h" -#include "LogMessageOsLog.h" -#include "MachProcess.h" -#include "RNBContext.h" -#include "RNBDefs.h" -#include "RNBRemote.h" - -// Use an anonymous namespace for variables and methods that have no -// reason to leak out through the interface. -namespace { -/// Specify max depth that the activity parent-child chain will search -/// back to get the full activity chain name. If we do more than this, -/// we assume either we hit a loop or it's just too long. -static const size_t MAX_ACTIVITY_CHAIN_DEPTH = 10; - -// Used to tap into and retrieve logs from target process. -// (Consumer of os_log). -static os_activity_stream_for_pid_t s_os_activity_stream_for_pid; -static os_activity_stream_resume_t s_os_activity_stream_resume; -static os_activity_stream_cancel_t s_os_activity_stream_cancel; -static os_log_copy_formatted_message_t s_os_log_copy_formatted_message; -static os_activity_stream_set_event_handler_t - s_os_activity_stream_set_event_handler; - -bool LookupSPICalls() { - static std::once_flag s_once_flag; - static bool s_has_spi; - - std::call_once(s_once_flag, [] { - dlopen ("/System/Library/PrivateFrameworks/LoggingSupport.framework/LoggingSupport", RTLD_NOW); - s_os_activity_stream_for_pid = (os_activity_stream_for_pid_t)dlsym( - RTLD_DEFAULT, "os_activity_stream_for_pid"); - s_os_activity_stream_resume = (os_activity_stream_resume_t)dlsym( - RTLD_DEFAULT, "os_activity_stream_resume"); - s_os_activity_stream_cancel = (os_activity_stream_cancel_t)dlsym( - RTLD_DEFAULT, "os_activity_stream_cancel"); - s_os_log_copy_formatted_message = (os_log_copy_formatted_message_t)dlsym( - RTLD_DEFAULT, "os_log_copy_formatted_message"); - s_os_activity_stream_set_event_handler = - (os_activity_stream_set_event_handler_t)dlsym( - RTLD_DEFAULT, "os_activity_stream_set_event_handler"); - - // We'll indicate we're all set if every function entry point - // was found. - s_has_spi = (s_os_activity_stream_for_pid != nullptr) && - (s_os_activity_stream_resume != nullptr) && - (s_os_activity_stream_cancel != nullptr) && - (s_os_log_copy_formatted_message != nullptr) && - (s_os_activity_stream_set_event_handler != nullptr); - if (s_has_spi) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Found os_log SPI calls."); - // Tell LogMessageOsLog how to format messages when search - // criteria requires it. - LogMessageOsLog::SetFormatterFunction(s_os_log_copy_formatted_message); - } else { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Failed to find os_log SPI " - "calls."); - } - }); - - return s_has_spi; -} - -using Mutex = std::mutex; -static Mutex s_collector_mutex; -static std::vector<DarwinLogCollectorSP> s_collectors; - -static void TrackCollector(const DarwinLogCollectorSP &collector_sp) { - std::lock_guard<Mutex> locker(s_collector_mutex); - if (std::find(s_collectors.begin(), s_collectors.end(), collector_sp) != - s_collectors.end()) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "attempted to add same collector multiple times"); - return; - } - s_collectors.push_back(collector_sp); -} - -static void StopTrackingCollector(const DarwinLogCollectorSP &collector_sp) { - std::lock_guard<Mutex> locker(s_collector_mutex); - s_collectors.erase( - std::remove(s_collectors.begin(), s_collectors.end(), collector_sp), - s_collectors.end()); -} - -static DarwinLogCollectorSP FindCollectorForProcess(pid_t pid) { - std::lock_guard<Mutex> locker(s_collector_mutex); - for (const auto &collector_sp : s_collectors) { - if (collector_sp && (collector_sp->GetProcessID() == pid)) - return collector_sp; - } - return DarwinLogCollectorSP(); -} - -static FilterTarget TargetStringToEnum(const std::string &filter_target_name) { - if (filter_target_name == "activity") - return eFilterTargetActivity; - else if (filter_target_name == "activity-chain") - return eFilterTargetActivityChain; - else if (filter_target_name == "category") - return eFilterTargetCategory; - else if (filter_target_name == "message") - return eFilterTargetMessage; - else if (filter_target_name == "subsystem") - return eFilterTargetSubsystem; - else - return eFilterTargetInvalid; -} - -class Configuration { -public: - Configuration(const JSONObject &config) - : m_is_valid(false), - m_activity_stream_flags(OS_ACTIVITY_STREAM_PROCESS_ONLY), - m_filter_chain_sp(nullptr) { - // Parse out activity stream flags - if (!ParseSourceFlags(config)) { - m_is_valid = false; - return; - } - - // Parse filter rules - if (!ParseFilterRules(config)) { - m_is_valid = false; - return; - } - - // Everything worked. - m_is_valid = true; - } - - bool ParseSourceFlags(const JSONObject &config) { - // Get the source-flags dictionary. - auto source_flags_sp = config.GetObject("source-flags"); - if (!source_flags_sp) - return false; - if (!JSONObject::classof(source_flags_sp.get())) - return false; - - const JSONObject &source_flags = - *static_cast<JSONObject *>(source_flags_sp.get()); - - // Parse out the flags. - bool include_any_process = false; - bool include_callstacks = false; - bool include_info_level = false; - bool include_debug_level = false; - bool live_stream = false; - - if (!source_flags.GetObjectAsBool("any-process", include_any_process)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'any-process' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("callstacks", include_callstacks)) { - // We currently suppress the availability of this on the lldb - // side. We include here for devices when we enable in the - // future. - // DNBLogThreadedIf(LOG_DARWIN_LOG, - // "Source-flag 'callstacks' missing from " - // "configuration."); - - // OK. We just skip callstacks. - // return false; - } - if (!source_flags.GetObjectAsBool("info-level", include_info_level)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'info-level' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("debug-level", include_debug_level)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'debug-level' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("live-stream", live_stream)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'live-stream' missing from " - "configuration."); - return false; - } - - // Setup the SPI flags based on this. - m_activity_stream_flags = 0; - if (!include_any_process) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY; - if (include_callstacks) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_CALLSTACK; - if (include_info_level) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_INFO; - if (include_debug_level) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_DEBUG; - if (!live_stream) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_BUFFERED; - - DNBLogThreadedIf(LOG_DARWIN_LOG, "m_activity_stream_flags = 0x%03x", - m_activity_stream_flags); - - return true; - } - - bool ParseFilterRules(const JSONObject &config) { - // Retrieve the default rule. - bool filter_default_accept = true; - if (!config.GetObjectAsBool("filter-fall-through-accepts", - filter_default_accept)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Setting 'filter-fall-through-accepts' " - "missing from configuration."); - return false; - } - m_filter_chain_sp.reset(new LogFilterChain(filter_default_accept)); - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog no-match rule: %s.", - filter_default_accept ? "accept" : "reject"); - - // If we don't have the filter-rules array, we're done. - auto filter_rules_sp = config.GetObject("filter-rules"); - if (!filter_rules_sp) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "No 'filter-rules' config element, all log " - "entries will use the no-match action (%s).", - filter_default_accept ? "accept" : "reject"); - return true; - } - if (!JSONArray::classof(filter_rules_sp.get())) - return false; - const JSONArray &rules_config = - *static_cast<JSONArray *>(filter_rules_sp.get()); - - // Create the filters. - for (auto &rule_sp : rules_config.m_elements) { - if (!JSONObject::classof(rule_sp.get())) - return false; - const JSONObject &rule_config = *static_cast<JSONObject *>(rule_sp.get()); - - // Get whether this filter accepts or rejects. - bool filter_accepts = true; - if (!rule_config.GetObjectAsBool("accept", filter_accepts)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'accept' element missing."); - return false; - } - - // Grab the target log field attribute for the match. - std::string target_attribute; - if (!rule_config.GetObjectAsString("attribute", target_attribute)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'attribute' element missing."); - return false; - } - auto target_enum = TargetStringToEnum(target_attribute); - if (target_enum == eFilterTargetInvalid) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter attribute '%s' unsupported.", - target_attribute.c_str()); - return false; - } - - // Handle operation-specific fields and filter creation. - std::string filter_type; - if (!rule_config.GetObjectAsString("type", filter_type)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'type' element missing."); - return false; - } - DNBLogThreadedIf(LOG_DARWIN_LOG, "Reading filter of type '%s'", - filter_type.c_str()); - - LogFilterSP filter_sp; - if (filter_type == "regex") { - // Grab the regex for the match. - std::string regex; - if (!rule_config.GetObjectAsString("regex", regex)) { - DNBLogError("Regex filter missing 'regex' element."); - return false; - } - DNBLogThreadedIf(LOG_DARWIN_LOG, "regex for filter: \"%s\"", - regex.c_str()); - - // Create the regex filter. - auto regex_filter = - new LogFilterRegex(filter_accepts, target_enum, regex); - filter_sp.reset(regex_filter); - - // Validate that the filter is okay. - if (!regex_filter->IsValid()) { - DNBLogError("Invalid regex in filter: " - "regex=\"%s\", error=%s", - regex.c_str(), regex_filter->GetErrorAsCString()); - return false; - } - } else if (filter_type == "match") { - // Grab the regex for the match. - std::string exact_text; - if (!rule_config.GetObjectAsString("exact_text", exact_text)) { - DNBLogError("Exact match filter missing " - "'exact_text' element."); - return false; - } - - // Create the filter. - filter_sp.reset( - new LogFilterExactMatch(filter_accepts, target_enum, exact_text)); - } - - // Add the filter to the chain. - m_filter_chain_sp->AppendFilter(filter_sp); - } - return true; - } - - bool IsValid() const { return m_is_valid; } - - os_activity_stream_flag_t GetActivityStreamFlags() const { - return m_activity_stream_flags; - } - - const LogFilterChainSP &GetLogFilterChain() const { - return m_filter_chain_sp; - } - -private: - bool m_is_valid; - os_activity_stream_flag_t m_activity_stream_flags; - LogFilterChainSP m_filter_chain_sp; -}; -} - -bool DarwinLogCollector::IsSupported() { - // We're supported if we have successfully looked up the SPI entry points. - return LookupSPICalls(); -} - -bool DarwinLogCollector::StartCollectingForProcess(nub_process_t pid, - const JSONObject &config) { - // If we're currently collecting for this process, kill the existing - // collector. - if (CancelStreamForProcess(pid)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() killed existing DarwinLog collector for pid %d.", - __FUNCTION__, pid); - } - - // If the process isn't alive, we're done. - if (!DNBProcessIsAlive(pid)) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() cannot collect for pid %d: process not alive.", - __FUNCTION__, pid); - return false; - } - - // Validate the configuration. - auto spi_config = Configuration(config); - if (!spi_config.IsValid()) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() invalid configuration, will not enable log " - "collection", - __FUNCTION__); - return false; - } - - // Create the stream collector that will manage collected data - // for this pid. - DarwinLogCollectorSP collector_sp( - new DarwinLogCollector(pid, spi_config.GetLogFilterChain())); - std::weak_ptr<DarwinLogCollector> collector_wp(collector_sp); - - // Setup the stream handling block. - os_activity_stream_block_t block = - ^bool(os_activity_stream_entry_t entry, int error) { - // Check if our collector is still alive. - DarwinLogCollectorSP inner_collector_sp = collector_wp.lock(); - if (!inner_collector_sp) - return false; - return inner_collector_sp->HandleStreamEntry(entry, error); - }; - - os_activity_stream_event_block_t stream_event_block = ^void( - os_activity_stream_t stream, os_activity_stream_event_t event) { - switch (event) { - case OS_ACTIVITY_STREAM_EVENT_STARTED: - DNBLogThreadedIf(LOG_DARWIN_LOG, - "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_STARTED, stream %p.", - (void *)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_STOPPED: - DNBLogThreadedIf(LOG_DARWIN_LOG, - "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_STOPPED, stream %p.", - (void *)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_FAILED: - DNBLogThreadedIf(LOG_DARWIN_LOG, - "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_FAILED, stream %p.", - (void *)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED: - DNBLogThreadedIf(LOG_DARWIN_LOG, - "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED, stream %p.", - (void *)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED: - DNBLogThreadedIf(LOG_DARWIN_LOG, - "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED, stream %p.", - (void *)stream); - break; - } - }; - - // Create the stream. - os_activity_stream_t activity_stream = (*s_os_activity_stream_for_pid)( - pid, spi_config.GetActivityStreamFlags(), block); - collector_sp->SetActivityStream(activity_stream); - - // Specify the stream-related event handler. - (*s_os_activity_stream_set_event_handler)(activity_stream, - stream_event_block); - - // Start the stream. - (*s_os_activity_stream_resume)(activity_stream); - - TrackCollector(collector_sp); - return true; -} - -DarwinLogEventVector -DarwinLogCollector::GetEventsForProcess(nub_process_t pid) { - auto collector_sp = FindCollectorForProcess(pid); - if (!collector_sp) { - // We're not tracking a stream for this process. - return DarwinLogEventVector(); - } - - return collector_sp->RemoveEvents(); -} - -bool DarwinLogCollector::CancelStreamForProcess(nub_process_t pid) { - auto collector_sp = FindCollectorForProcess(pid); - if (!collector_sp) { - // We're not tracking a stream for this process. - return false; - } - - collector_sp->CancelActivityStream(); - StopTrackingCollector(collector_sp); - - return true; -} - -const char * -DarwinLogCollector::GetActivityForID(os_activity_id_t activity_id) const { - auto find_it = m_activity_map.find(activity_id); - return (find_it != m_activity_map.end()) ? find_it->second.m_name.c_str() - : nullptr; -} - -/// Retrieve the full parent-child chain for activity names. These -/// can be arbitrarily deep. This method assumes the caller has already -/// locked the activity mutex. -void DarwinLogCollector::GetActivityChainForID_internal( - os_activity_id_t activity_id, std::string &result, size_t depth) const { - if (depth > MAX_ACTIVITY_CHAIN_DEPTH) { - // Terminating condition - too deeply nested. - return; - } else if (activity_id == 0) { - // Terminating condition - no activity. - return; - } - - auto find_it = m_activity_map.find(activity_id); - if (find_it == m_activity_map.end()) { - // Terminating condition - no data for activity_id. - return; - } - - // Activity name becomes parent activity name chain + ':' + our activity - // name. - GetActivityChainForID_internal(find_it->second.m_parent_id, result, - depth + 1); - if (!result.empty()) - result += ':'; - result += find_it->second.m_name; -} - -std::string -DarwinLogCollector::GetActivityChainForID(os_activity_id_t activity_id) const { - std::string result; - { - std::lock_guard<std::mutex> locker(m_activity_info_mutex); - GetActivityChainForID_internal(activity_id, result, 1); - } - return result; -} - -DarwinLogCollector::DarwinLogCollector(nub_process_t pid, - const LogFilterChainSP &filter_chain_sp) - : ActivityStore(), m_pid(pid), m_activity_stream(0), m_events(), - m_events_mutex(), m_filter_chain_sp(filter_chain_sp), - m_activity_info_mutex(), m_activity_map() {} - -DarwinLogCollector::~DarwinLogCollector() { - // Cancel the stream. - if (m_activity_stream) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "tearing down activity stream " - "collector for %d", - m_pid); - (*s_os_activity_stream_cancel)(m_activity_stream); - m_activity_stream = 0; - } else { - DNBLogThreadedIf(LOG_DARWIN_LOG, "no stream to tear down for %d", m_pid); - } -} - -void DarwinLogCollector::SignalDataAvailable() { - RNBRemoteSP remoteSP(g_remoteSP); - if (!remoteSP) { - // We're done. This is unexpected. - StopTrackingCollector(shared_from_this()); - return; - } - - RNBContext &ctx = remoteSP->Context(); - ctx.Events().SetEvents(RNBContext::event_darwin_log_data_available); - // Wait for the main thread to consume this notification if it requested - // we wait for it. - ctx.Events().WaitForResetAck(RNBContext::event_darwin_log_data_available); -} - -void DarwinLogCollector::SetActivityStream( - os_activity_stream_t activity_stream) { - m_activity_stream = activity_stream; -} - -bool DarwinLogCollector::HandleStreamEntry(os_activity_stream_entry_t entry, - int error) { - if ((error == 0) && (entry != nullptr)) { - if (entry->pid != m_pid) { - // For now, skip messages not originating from our process. - // Later we might want to keep all messages related to an event - // that we're tracking, even when it came from another process, - // possibly doing work on our behalf. - return true; - } - - switch (entry->type) { - case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE: - DNBLogThreadedIf( - LOG_DARWIN_LOG, "received activity create: " - "%s, creator aid %" PRIu64 ", unique_pid %" PRIu64 - "(activity id=%" PRIu64 ", parent id=%" PRIu64 ")", - entry->activity_create.name, entry->activity_create.creator_aid, - entry->activity_create.unique_pid, entry->activity_id, - entry->parent_id); - { - std::lock_guard<std::mutex> locker(m_activity_info_mutex); - m_activity_map.insert( - std::make_pair(entry->activity_id, - ActivityInfo(entry->activity_create.name, - entry->activity_id, entry->parent_id))); - } - break; - - case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION: - DNBLogThreadedIf( - LOG_DARWIN_LOG, "received activity transition:" - "new aid: %" PRIu64 "(activity id=%" PRIu64 - ", parent id=%" PRIu64 ", tid %" PRIu64 ")", - entry->activity_transition.transition_id, entry->activity_id, - entry->parent_id, entry->activity_transition.thread); - break; - - case OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE: { - DNBLogThreadedIf( - LOG_DARWIN_LOG, "received log message: " - "(activity id=%" PRIu64 ", parent id=%" PRIu64 ", " - "tid %" PRIu64 "): format %s", - entry->activity_id, entry->parent_id, entry->log_message.thread, - entry->log_message.format ? entry->log_message.format - : "<invalid-format>"); - - // Do the real work here. - { - // Ensure our process is still alive. If not, we can - // cancel the collection. - if (!DNBProcessIsAlive(m_pid)) { - // We're outta here. This is the manner in which we - // stop collecting for a process. - StopTrackingCollector(shared_from_this()); - return false; - } - - LogMessageOsLog os_log_message(*this, *entry); - if (!m_filter_chain_sp || - !m_filter_chain_sp->GetAcceptMessage(os_log_message)) { - // This log message was rejected by the filter, - // so stop processing it now. - return true; - } - - // Copy over the relevant bits from the message. - const struct os_log_message_s &log_message = entry->log_message; - - DarwinLogEventSP message_sp(new DarwinLogEvent()); - // Indicate this event is a log message event. - message_sp->AddStringItem("type", "log"); - - // Add the message contents (fully expanded). - // Consider expanding on the remote side. - // Then we don't pay for expansion until when it is - // used. - const char *message_text = os_log_message.GetMessage(); - if (message_text) - message_sp->AddStringItem("message", message_text); - - // Add some useful data fields. - message_sp->AddIntegerItem("timestamp", log_message.timestamp); - - // Do we want to do all activity name resolution on this - // side? Maybe. For now, send IDs and ID->name mappings - // and fix this up on that side. Later, when we add - // debugserver-side filtering, we'll want to get the - // activity names over here, so we should probably - // just send them as resolved strings. - message_sp->AddIntegerItem("activity_id", entry->activity_id); - message_sp->AddIntegerItem("parent_id", entry->parent_id); - message_sp->AddIntegerItem("thread_id", log_message.thread); - if (log_message.subsystem && strlen(log_message.subsystem) > 0) - message_sp->AddStringItem("subsystem", log_message.subsystem); - if (log_message.category && strlen(log_message.category) > 0) - message_sp->AddStringItem("category", log_message.category); - if (entry->activity_id != 0) { - std::string activity_chain = - GetActivityChainForID(entry->activity_id); - if (!activity_chain.empty()) - message_sp->AddStringItem("activity-chain", activity_chain); - } - - // Add it to the list for later collection. - { - std::lock_guard<std::mutex> locker(m_events_mutex); - m_events.push_back(message_sp); - } - SignalDataAvailable(); - } - break; - } - } - } else { - DNBLogThreadedIf(LOG_DARWIN_LOG, "HandleStreamEntry: final call, " - "error %d", - error); - } - return true; -} - -DarwinLogEventVector DarwinLogCollector::RemoveEvents() { - DarwinLogEventVector returned_events; - { - std::lock_guard<std::mutex> locker(m_events_mutex); - returned_events.swap(m_events); - } - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): removing %lu " - "queued log entries", - __FUNCTION__, returned_events.size()); - return returned_events; -} - -void DarwinLogCollector::CancelActivityStream() { - if (!m_activity_stream) - return; - - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): canceling " - "activity stream %p", - __FUNCTION__, reinterpret_cast<void *>(m_activity_stream)); - (*s_os_activity_stream_cancel)(m_activity_stream); - m_activity_stream = nullptr; -} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h b/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h deleted file mode 100644 index a7d4e8a774c2..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-- DarwinLogCollector.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef DarwinLogCollector_h -#define DarwinLogCollector_h - -#include <sys/types.h> - -#include <memory> -#include <mutex> -#include <unordered_map> - -#include "ActivityStore.h" -#include "ActivityStreamSPI.h" -#include "DNBDefs.h" -#include "DarwinLogEvent.h" -#include "DarwinLogInterfaces.h" -#include "JSON.h" - -class DarwinLogCollector; -typedef std::shared_ptr<DarwinLogCollector> DarwinLogCollectorSP; - -class DarwinLogCollector - : public std::enable_shared_from_this<DarwinLogCollector>, - public ActivityStore { -public: - //------------------------------------------------------------------ - /// Return whether the os_log and activity tracing SPI is available. - /// - /// @return \b true if the activity stream support is available, - /// \b false otherwise. - //------------------------------------------------------------------ - static bool IsSupported(); - - //------------------------------------------------------------------ - /// Return a log function suitable for DNBLog to use as the internal - /// logging function. - /// - /// @return a DNBLog-style logging function if IsSupported() returns - /// true; otherwise, returns nullptr. - //------------------------------------------------------------------ - static DNBCallbackLog GetLogFunction(); - - static bool StartCollectingForProcess(nub_process_t pid, - const JSONObject &config); - - static bool CancelStreamForProcess(nub_process_t pid); - - static DarwinLogEventVector GetEventsForProcess(nub_process_t pid); - - ~DarwinLogCollector(); - - pid_t GetProcessID() const { return m_pid; } - - //------------------------------------------------------------------ - // ActivityStore API - //------------------------------------------------------------------ - const char *GetActivityForID(os_activity_id_t activity_id) const override; - - std::string - GetActivityChainForID(os_activity_id_t activity_id) const override; - -private: - DarwinLogCollector() = delete; - DarwinLogCollector(const DarwinLogCollector &) = delete; - DarwinLogCollector &operator=(const DarwinLogCollector &) = delete; - - explicit DarwinLogCollector(nub_process_t pid, - const LogFilterChainSP &filter_chain_sp); - - void SignalDataAvailable(); - - void SetActivityStream(os_activity_stream_t activity_stream); - - bool HandleStreamEntry(os_activity_stream_entry_t entry, int error); - - DarwinLogEventVector RemoveEvents(); - - void CancelActivityStream(); - - void GetActivityChainForID_internal(os_activity_id_t activity_id, - std::string &result, size_t depth) const; - - struct ActivityInfo { - ActivityInfo(const char *name, os_activity_id_t activity_id, - os_activity_id_t parent_activity_id) - : m_name(name), m_id(activity_id), m_parent_id(parent_activity_id) {} - - const std::string m_name; - const os_activity_id_t m_id; - const os_activity_id_t m_parent_id; - }; - - using ActivityMap = std::unordered_map<os_activity_id_t, ActivityInfo>; - - const nub_process_t m_pid; - os_activity_stream_t m_activity_stream; - DarwinLogEventVector m_events; - std::mutex m_events_mutex; - LogFilterChainSP m_filter_chain_sp; - - /// Mutex to protect activity info (activity name and parent structures) - mutable std::mutex m_activity_info_mutex; - /// Map of activity id to ActivityInfo - ActivityMap m_activity_map; -}; - -#endif /* LogStreamCollector_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogEvent.h b/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogEvent.h deleted file mode 100644 index 6be3b81f3e10..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogEvent.h +++ /dev/null @@ -1,27 +0,0 @@ -//===-- DarwinLogEvent.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef DarwinLogEvent_h -#define DarwinLogEvent_h - -#include <memory> -#include <vector> - -#include "JSONGenerator.h" - -// ============================================================================= -/// Each discrete unit of information is described as an event, such as -/// the emission of a single log message. -// ============================================================================= - -using DarwinLogEvent = JSONGenerator::Dictionary; -using DarwinLogEventSP = std::shared_ptr<DarwinLogEvent>; -using DarwinLogEventVector = std::vector<DarwinLogEventSP>; - -#endif diff --git a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogInterfaces.h b/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogInterfaces.h deleted file mode 100644 index afb979f6cfe4..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogInterfaces.h +++ /dev/null @@ -1,25 +0,0 @@ -//===-- DarwinLogInterfaces.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef DarwinLogInterfaces_h -#define DarwinLogInterfaces_h - -#include <memory> - -class ActivityStore; - -class LogFilter; -using LogFilterSP = std::shared_ptr<LogFilter>; - -class LogFilterChain; -using LogFilterChainSP = std::shared_ptr<LogFilterChain>; - -class LogMessage; - -#endif /* DarwinLogInterfaces_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h b/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h deleted file mode 100644 index e285e732e565..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- DarwinLogTypes.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef DarwinLogTypes_h -#define DarwinLogTypes_h - -enum FilterTarget { - eFilterTargetInvalid, - eFilterTargetActivity, - eFilterTargetActivityChain, - eFilterTargetCategory, - eFilterTargetMessage, - eFilterTargetSubsystem -}; - -#endif /* DarwinLogTypes_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp deleted file mode 100644 index d78419d46617..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp +++ /dev/null @@ -1,12 +0,0 @@ -//===-- LogFilter.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogFilter.h" - -LogFilter::~LogFilter() {} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h b/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h deleted file mode 100644 index 92caac297258..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h +++ /dev/null @@ -1,30 +0,0 @@ -//===-- LogFilter.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogFilter_h -#define LogFilter_h - -#include "DarwinLogInterfaces.h" - -class LogFilter { -public: - virtual ~LogFilter(); - - virtual bool DoesMatch(const LogMessage &message) const = 0; - - bool MatchesAreAccepted() const { return m_matches_accept; } - -protected: - LogFilter(bool matches_accept) : m_matches_accept(matches_accept) {} - -private: - bool m_matches_accept; -}; - -#endif /* LogFilter_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp deleted file mode 100644 index 12fbe77a9069..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===-- LogFilterChain.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogFilterChain.h" - -#include "LogFilter.h" - -LogFilterChain::LogFilterChain(bool default_accept) - : m_filters(), m_default_accept(default_accept) {} - -void LogFilterChain::AppendFilter(const LogFilterSP &filter_sp) { - if (filter_sp) - m_filters.push_back(filter_sp); -} - -void LogFilterChain::ClearFilterChain() { m_filters.clear(); } - -bool LogFilterChain::GetDefaultAccepts() const { return m_default_accept; } - -void LogFilterChain::SetDefaultAccepts(bool default_accept) { - m_default_accept = default_accept; -} - -bool LogFilterChain::GetAcceptMessage(const LogMessage &message) const { - for (auto filter_sp : m_filters) { - if (filter_sp->DoesMatch(message)) { - // This message matches this filter. If the filter accepts matches, - // this message matches; otherwise, it rejects matches. - return filter_sp->MatchesAreAccepted(); - } - } - - // None of the filters matched. Therefore, we do whatever the - // default fall-through rule says. - return m_default_accept; -} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h deleted file mode 100644 index e4888361e71f..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- LogFilterChain.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogFilterChain_h -#define LogFilterChain_h - -#include <vector> - -#include "DarwinLogInterfaces.h" - -class LogFilterChain { -public: - LogFilterChain(bool default_accept); - - void AppendFilter(const LogFilterSP &filter_sp); - - void ClearFilterChain(); - - bool GetDefaultAccepts() const; - - void SetDefaultAccepts(bool default_accepts); - - bool GetAcceptMessage(const LogMessage &message) const; - -private: - using FilterVector = std::vector<LogFilterSP>; - - FilterVector m_filters; - bool m_default_accept; -}; - -#endif /* LogFilterChain_hpp */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp deleted file mode 100644 index c8034fe1f222..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===-- LogFilterExactMatch.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogFilterExactMatch.h" -#include "LogMessage.h" - -LogFilterExactMatch::LogFilterExactMatch(bool match_accepts, - FilterTarget filter_target, - const std::string &match_text) - : LogFilter(match_accepts), m_filter_target(filter_target), - m_match_text(match_text) {} - -bool LogFilterExactMatch::DoesMatch(const LogMessage &message) const { - switch (m_filter_target) { - case eFilterTargetActivity: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return m_match_text == message.GetActivity(); - case eFilterTargetActivityChain: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return m_match_text == message.GetActivityChain(); - case eFilterTargetCategory: - // Empty fields never match a condition. - if (!message.HasCategory()) - return false; - return m_match_text == message.GetCategory(); - case eFilterTargetMessage: { - const char *message_text = message.GetMessage(); - return (message_text != nullptr) && (m_match_text == message_text); - } - case eFilterTargetSubsystem: - // Empty fields never match a condition. - if (!message.HasSubsystem()) - return false; - return m_match_text == message.GetSubsystem(); - default: - // We don't know this type. - return false; - } -} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h deleted file mode 100644 index dd514bc82744..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- LogFilterExactMatch.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogFilterExactMatch_h -#define LogFilterExactMatch_h - -#include <string> - -#include "DarwinLogInterfaces.h" -#include "DarwinLogTypes.h" -#include "LogFilter.h" - -class LogFilterExactMatch : public LogFilter { -public: - LogFilterExactMatch(bool match_accepts, FilterTarget filter_target, - const std::string &match_text); - - bool DoesMatch(const LogMessage &message) const override; - -private: - const FilterTarget m_filter_target; - const std::string m_match_text; -}; - -#endif diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp deleted file mode 100644 index d21ce81c832c..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===-- LogFilterRegex.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogFilterRegex.h" - -#include "DNBLog.h" -#include "LogMessage.h" - -//---------------------------------------------------------------------- -// Enable enhanced mode if it is available. This allows for things like -// \d for digit, \s for space, and many more, but it isn't available -// everywhere. -//---------------------------------------------------------------------- -#if defined(REG_ENHANCED) -#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED) -#else -#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) -#endif - -LogFilterRegex::LogFilterRegex(bool match_accepts, FilterTarget filter_target, - const std::string ®ex) - : LogFilter(match_accepts), m_filter_target(filter_target), - m_regex_text(regex), m_regex(), m_is_valid(false), m_error_text() { - // Clear it. - memset(&m_regex, 0, sizeof(m_regex)); - - // Compile it. - if (!regex.empty()) { - auto comp_err = ::regcomp(&m_regex, regex.c_str(), DEFAULT_COMPILE_FLAGS); - m_is_valid = (comp_err == 0); - if (!m_is_valid) { - char buffer[256]; - buffer[0] = '\0'; - ::regerror(comp_err, &m_regex, buffer, sizeof(buffer)); - m_error_text = buffer; - } - } -} - -LogFilterRegex::~LogFilterRegex() { - if (m_is_valid) { - // Free the regex internals. - regfree(&m_regex); - } -} - -bool LogFilterRegex::DoesMatch(const LogMessage &message) const { - switch (m_filter_target) { - case eFilterTargetActivity: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0) == 0; - case eFilterTargetActivityChain: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0, nullptr, - 0) == 0; - case eFilterTargetCategory: - // Empty fields never match a condition. - if (!message.HasCategory()) - return false; - return ::regexec(&m_regex, message.GetCategory(), 0, nullptr, 0) == 0; - case eFilterTargetMessage: { - const char *message_text = message.GetMessage(); - if (!message_text) { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "LogFilterRegex: regex " - "\"%s\" no match due to nullptr message.", - m_regex_text.c_str()); - return false; - } - - bool match = ::regexec(&m_regex, message_text, 0, nullptr, 0) == 0; - DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex " - "\"%s\" %s message \"%s\".", - m_regex_text.c_str(), match ? "matches" : "does not match", - message_text); - return match; - } - case eFilterTargetSubsystem: - // Empty fields never match a condition. - if (!message.HasSubsystem()) - return false; - return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr, 0) == 0; - default: - // We don't know this type. - return false; - } -} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h b/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h deleted file mode 100644 index 4a5939217f07..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- LogFilterRegex.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogFilterRegex_h -#define LogFilterRegex_h - -// C includes -#include <regex.h> - -// C++ includes -#include <string> - -#include "DarwinLogInterfaces.h" -#include "DarwinLogTypes.h" -#include "LogFilter.h" - -class LogFilterRegex : public LogFilter { -public: - LogFilterRegex(bool match_accepts, FilterTarget filter_target, - const std::string ®ex); - - virtual ~LogFilterRegex(); - - bool IsValid() const { return m_is_valid; } - - const char *GetErrorAsCString() const { return m_error_text.c_str(); } - - bool DoesMatch(const LogMessage &message) const override; - -private: - const FilterTarget m_filter_target; - const std::string m_regex_text; - regex_t m_regex; - bool m_is_valid; - std::string m_error_text; -}; - -#endif /* LogFilterSubsystemRegex_hpp */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp deleted file mode 100644 index 5a31087f2316..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//===-- LogMessage.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogMessage.h" - -LogMessage::LogMessage() {} - -LogMessage::~LogMessage() {} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h b/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h deleted file mode 100644 index bbc975133ece..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- LogMessage.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogMessage_h -#define LogMessage_h - -#include <string> - -class LogMessage { -public: - virtual ~LogMessage(); - - virtual bool HasActivity() const = 0; - - virtual const char *GetActivity() const = 0; - - virtual std::string GetActivityChain() const = 0; - - virtual bool HasCategory() const = 0; - - virtual const char *GetCategory() const = 0; - - virtual bool HasSubsystem() const = 0; - - virtual const char *GetSubsystem() const = 0; - - // This can be expensive, so once we ask for it, we'll cache the result. - virtual const char *GetMessage() const = 0; - -protected: - LogMessage(); -}; - -#endif /* LogMessage_h */ diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp b/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp deleted file mode 100644 index 91347eaf12c7..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===-- LogMessageOsLog.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LogMessageOsLog.h" - -#include "ActivityStore.h" -#include "ActivityStreamSPI.h" - -namespace { -static os_log_copy_formatted_message_t s_log_copy_formatted_message; -} - -void LogMessageOsLog::SetFormatterFunction( - os_log_copy_formatted_message_t format_func) { - s_log_copy_formatted_message = format_func; -} - -LogMessageOsLog::LogMessageOsLog(const ActivityStore &activity_store, - ActivityStreamEntry &entry) - : LogMessage(), m_activity_store(activity_store), m_entry(entry), - m_message() {} - -bool LogMessageOsLog::HasActivity() const { return m_entry.activity_id != 0; } - -const char *LogMessageOsLog::GetActivity() const { - return m_activity_store.GetActivityForID(m_entry.activity_id); -} - -std::string LogMessageOsLog::GetActivityChain() const { - return m_activity_store.GetActivityChainForID(m_entry.activity_id); -} - -bool LogMessageOsLog::HasCategory() const { - return m_entry.log_message.category && (m_entry.log_message.category[0] != 0); -} - -const char *LogMessageOsLog::GetCategory() const { - return m_entry.log_message.category; -} - -bool LogMessageOsLog::HasSubsystem() const { - return m_entry.log_message.subsystem && - (m_entry.log_message.subsystem[0] != 0); -} - -const char *LogMessageOsLog::GetSubsystem() const { - return m_entry.log_message.subsystem; -} - -const char *LogMessageOsLog::GetMessage() const { - if (m_message.empty()) { - std::unique_ptr<char[]> formatted_message( - s_log_copy_formatted_message(&m_entry.log_message)); - if (formatted_message) - m_message = formatted_message.get(); - // else - // TODO log - } - - // This is safe to return as we're not modifying it once we've formatted it. - return m_message.c_str(); -} diff --git a/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h b/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h deleted file mode 100644 index 18103e031592..000000000000 --- a/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h +++ /dev/null @@ -1,59 +0,0 @@ -//===-- LogMessageOsLog.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LogMessageOsLog_h -#define LogMessageOsLog_h - -#include "DarwinLogInterfaces.h" - -#include "ActivityStreamSPI.h" -#include "LogMessage.h" - -using ActivityStreamEntry = struct os_activity_stream_entry_s; - -// ----------------------------------------------------------------------------- -/// Provides a unified wrapper around os_log()-style log messages. -/// -/// The lifetime of this class is intended to be very short. The caller -/// must ensure that the passed in ActivityStore and ActivityStreamEntry -/// outlive this LogMessageOsLog entry. -// ----------------------------------------------------------------------------- - -class LogMessageOsLog : public LogMessage { -public: - static void SetFormatterFunction(os_log_copy_formatted_message_t format_func); - - LogMessageOsLog(const ActivityStore &activity_store, - ActivityStreamEntry &entry); - - // API methods - - bool HasActivity() const override; - - const char *GetActivity() const override; - - std::string GetActivityChain() const override; - - bool HasCategory() const override; - - const char *GetCategory() const override; - - bool HasSubsystem() const override; - - const char *GetSubsystem() const override; - - const char *GetMessage() const override; - -private: - const ActivityStore &m_activity_store; - ActivityStreamEntry &m_entry; - mutable std::string m_message; -}; - -#endif /* LogMessageOsLog_h */ diff --git a/tools/debugserver/source/MacOSX/Genealogy.cpp b/tools/debugserver/source/MacOSX/Genealogy.cpp deleted file mode 100644 index 1473a53fcbea..000000000000 --- a/tools/debugserver/source/MacOSX/Genealogy.cpp +++ /dev/null @@ -1,318 +0,0 @@ -///===-- Activity.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <Availability.h> -#include <dlfcn.h> -#include <string> -#include <uuid/uuid.h> - -#include "DNBDefs.h" -#include "Genealogy.h" -#include "GenealogySPI.h" -#include "MachThreadList.h" - -//--------------------------- -/// Constructor -//--------------------------- - -Genealogy::Genealogy() - : m_os_activity_diagnostic_for_pid(nullptr), - m_os_activity_iterate_processes(nullptr), - m_os_activity_iterate_breadcrumbs(nullptr), - m_os_activity_iterate_messages(nullptr), - m_os_activity_iterate_activities(nullptr), m_os_trace_get_type(nullptr), - m_os_trace_copy_formatted_message(nullptr), - m_os_activity_for_thread(nullptr), m_os_activity_for_task_thread(nullptr), - m_thread_activities(), m_process_executable_infos(), - m_diagnosticd_call_timed_out(false) { - m_os_activity_diagnostic_for_pid = - (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym( - RTLD_DEFAULT, "os_activity_diagnostic_for_pid"); - m_os_activity_iterate_processes = - (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t))) - dlsym(RTLD_DEFAULT, "os_activity_iterate_processes"); - m_os_activity_iterate_breadcrumbs = - (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t))) - dlsym(RTLD_DEFAULT, "os_activity_iterate_breadcrumbs"); - m_os_activity_iterate_messages = (void (*)( - os_trace_message_list_t, os_activity_process_t, - bool (^)(os_trace_message_t)))dlsym(RTLD_DEFAULT, - "os_activity_iterate_messages"); - m_os_activity_iterate_activities = (void (*)( - os_activity_list_t, os_activity_process_t, - bool (^)(os_activity_entry_t)))dlsym(RTLD_DEFAULT, - "os_activity_iterate_activities"); - m_os_trace_get_type = - (uint8_t(*)(os_trace_message_t))dlsym(RTLD_DEFAULT, "os_trace_get_type"); - m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t))dlsym( - RTLD_DEFAULT, "os_trace_copy_formatted_message"); - m_os_activity_for_thread = - (os_activity_t(*)(os_activity_process_t, uint64_t))dlsym( - RTLD_DEFAULT, "os_activity_for_thread"); - m_os_activity_for_task_thread = (os_activity_t(*)(task_t, uint64_t))dlsym( - RTLD_DEFAULT, "os_activity_for_task_thread"); - m_os_activity_messages_for_thread = (os_trace_message_list_t(*)( - os_activity_process_t process, os_activity_t activity, - uint64_t thread_id))dlsym(RTLD_DEFAULT, - "os_activity_messages_for_thread"); -} - -Genealogy::ThreadActivitySP -Genealogy::GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid, - const MachThreadList &thread_list, - task_t task, bool &timed_out) { - ThreadActivitySP activity; - // - // if we've timed out trying to get the activities, don't try again at this - // process stop. - // (else we'll need to hit the timeout for every thread we're asked about.) - // We'll try again at the next public stop. - - if (m_thread_activities.size() == 0 && !m_diagnosticd_call_timed_out) { - GetActivities(pid, thread_list, task); - } - std::map<nub_thread_t, ThreadActivitySP>::const_iterator search; - search = m_thread_activities.find(tid); - if (search != m_thread_activities.end()) { - activity = search->second; - } - timed_out = m_diagnosticd_call_timed_out; - return activity; -} - -void Genealogy::Clear() { - m_thread_activities.clear(); - m_diagnosticd_call_timed_out = false; -} - -void Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list, - task_t task) { - if (m_os_activity_diagnostic_for_pid != nullptr && - m_os_activity_iterate_processes != nullptr && - m_os_activity_iterate_breadcrumbs != nullptr && - m_os_activity_iterate_messages != nullptr && - m_os_activity_iterate_activities != nullptr && - m_os_trace_get_type != nullptr && - m_os_trace_copy_formatted_message != nullptr && - (m_os_activity_for_thread != nullptr || - m_os_activity_for_task_thread != nullptr)) { - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block BreadcrumbList breadcrumbs; - __block ActivityList activities; - __block MessageList messages; - __block std::map<nub_thread_t, uint64_t> thread_activity_mapping; - - os_activity_diagnostic_flag_t flags = - OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES | - OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY; - if (m_os_activity_diagnostic_for_pid( - pid, 0, flags, ^(os_activity_process_list_t processes, int error) { - if (error == 0) { - m_os_activity_iterate_processes(processes, ^bool( - os_activity_process_t - process_info) { - if (pid == process_info->pid) { - // Collect all the Breadcrumbs - m_os_activity_iterate_breadcrumbs( - process_info, - ^bool(os_activity_breadcrumb_t breadcrumb) { - Breadcrumb bc; - bc.breadcrumb_id = breadcrumb->breadcrumb_id; - bc.activity_id = breadcrumb->activity_id; - bc.timestamp = breadcrumb->timestamp; - if (breadcrumb->name) - bc.name = breadcrumb->name; - breadcrumbs.push_back(bc); - return true; - }); - - // Collect all the Activites - m_os_activity_iterate_activities( - process_info->activities, process_info, - ^bool(os_activity_entry_t activity) { - Activity ac; - ac.activity_start = activity->activity_start; - ac.activity_id = activity->activity_id; - ac.parent_id = activity->parent_id; - if (activity->activity_name) - ac.activity_name = activity->activity_name; - if (activity->reason) - ac.reason = activity->reason; - activities.push_back(ac); - return true; - }); - - // Collect all the Messages -- messages not associated with - // any thread - m_os_activity_iterate_messages( - process_info->messages, process_info, - ^bool(os_trace_message_t trace_msg) { - Message msg; - msg.timestamp = trace_msg->timestamp; - msg.trace_id = trace_msg->trace_id; - msg.thread = trace_msg->thread; - msg.type = m_os_trace_get_type(trace_msg); - msg.activity_id = 0; - if (trace_msg->image_uuid && trace_msg->image_path) { - ProcessExecutableInfoSP process_info_sp( - new ProcessExecutableInfo()); - uuid_copy(process_info_sp->image_uuid, - trace_msg->image_uuid); - process_info_sp->image_path = trace_msg->image_path; - msg.process_info_index = - AddProcessExecutableInfo(process_info_sp); - } - const char *message_text = - m_os_trace_copy_formatted_message(trace_msg); - if (message_text) - msg.message = message_text; - messages.push_back(msg); - return true; - }); - - // Discover which activities are said to be running on - // threads currently - const nub_size_t num_threads = thread_list.NumThreads(); - for (nub_size_t i = 0; i < num_threads; ++i) { - nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i); - os_activity_t act = 0; - if (m_os_activity_for_task_thread != nullptr) { - act = m_os_activity_for_task_thread(task, thread_id); - } else if (m_os_activity_for_thread != nullptr) { - act = m_os_activity_for_thread(process_info, thread_id); - } - if (act != 0) - thread_activity_mapping[thread_id] = act; - } - - // Collect all Messages -- messages associated with a thread - - // When there's no genealogy information, an early version - // of os_activity_messages_for_thread - // can crash in rare circumstances. Check to see if this - // process has any activities before - // making the call to get messages. - if (process_info->activities != nullptr && - thread_activity_mapping.size() > 0) { - std::map<nub_thread_t, uint64_t>::const_iterator iter; - for (iter = thread_activity_mapping.begin(); - iter != thread_activity_mapping.end(); ++iter) { - nub_thread_t thread_id = iter->first; - os_activity_t act = iter->second; - os_trace_message_list_t this_thread_messages = - m_os_activity_messages_for_thread(process_info, act, - thread_id); - m_os_activity_iterate_messages( - this_thread_messages, process_info, - ^bool(os_trace_message_t trace_msg) { - Message msg; - msg.timestamp = trace_msg->timestamp; - msg.trace_id = trace_msg->trace_id; - msg.thread = trace_msg->thread; - msg.type = m_os_trace_get_type(trace_msg); - msg.activity_id = act; - if (trace_msg->image_uuid && - trace_msg->image_path) { - ProcessExecutableInfoSP process_info_sp( - new ProcessExecutableInfo()); - uuid_copy(process_info_sp->image_uuid, - trace_msg->image_uuid); - process_info_sp->image_path = - trace_msg->image_path; - msg.process_info_index = - AddProcessExecutableInfo(process_info_sp); - } - const char *message_text = - m_os_trace_copy_formatted_message(trace_msg); - if (message_text) - msg.message = message_text; - messages.push_back(msg); - return true; - }); - } - } - } - return true; - }); - } - dispatch_semaphore_signal(semaphore); - }) == true) { - // Wait for the diagnosticd xpc calls to all finish up -- or half a second - // to elapse. - dispatch_time_t timeout = - dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2); - bool success = dispatch_semaphore_wait(semaphore, timeout) == 0; - if (!success) { - m_diagnosticd_call_timed_out = true; - return; - } - } - - // breadcrumbs, activities, and messages have all now been filled in. - - std::map<nub_thread_t, uint64_t>::const_iterator iter; - for (iter = thread_activity_mapping.begin(); - iter != thread_activity_mapping.end(); ++iter) { - nub_thread_t thread_id = iter->first; - uint64_t activity_id = iter->second; - ActivityList::const_iterator activity_search; - for (activity_search = activities.begin(); - activity_search != activities.end(); ++activity_search) { - if (activity_search->activity_id == activity_id) { - ThreadActivitySP thread_activity_sp(new ThreadActivity()); - thread_activity_sp->current_activity = *activity_search; - - BreadcrumbList::const_iterator breadcrumb_search; - for (breadcrumb_search = breadcrumbs.begin(); - breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search) { - if (breadcrumb_search->activity_id == activity_id) { - thread_activity_sp->breadcrumbs.push_back(*breadcrumb_search); - } - } - MessageList::const_iterator message_search; - for (message_search = messages.begin(); - message_search != messages.end(); ++message_search) { - if (message_search->thread == thread_id) { - thread_activity_sp->messages.push_back(*message_search); - } - } - - m_thread_activities[thread_id] = thread_activity_sp; - break; - } - } - } - } -} - -uint32_t -Genealogy::AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info) { - const uint32_t info_size = - static_cast<uint32_t>(m_process_executable_infos.size()); - for (uint32_t idx = 0; idx < info_size; ++idx) { - if (uuid_compare(m_process_executable_infos[idx]->image_uuid, - process_exe_info->image_uuid) == 0) { - return idx + 1; - } - } - m_process_executable_infos.push_back(process_exe_info); - return info_size + 1; -} - -Genealogy::ProcessExecutableInfoSP -Genealogy::GetProcessExecutableInfosAtIndex(size_t idx) { - ProcessExecutableInfoSP info_sp; - if (idx > 0) { - idx--; - if (idx <= m_process_executable_infos.size()) { - info_sp = m_process_executable_infos[idx]; - } - } - return info_sp; -} diff --git a/tools/debugserver/source/MacOSX/Genealogy.h b/tools/debugserver/source/MacOSX/Genealogy.h deleted file mode 100644 index f398b63c6d92..000000000000 --- a/tools/debugserver/source/MacOSX/Genealogy.h +++ /dev/null @@ -1,120 +0,0 @@ -//===-- Activity.h -----------------------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __Genealogy_h__ -#define __Genealogy_h__ - -#include <mach/task.h> -#include <map> -#include <pthread.h> -#include <string> -#include <vector> - -#include "GenealogySPI.h" -#include "MachThreadList.h" - -class Genealogy { -public: - Genealogy(); - - ~Genealogy() {} - - void Clear(); - - struct Breadcrumb { - uint32_t breadcrumb_id; - uint64_t activity_id; - uint64_t timestamp; - std::string name; - }; - - struct Activity { - uint64_t activity_start; - uint64_t activity_id; - uint64_t parent_id; - std::string activity_name; - std::string reason; - }; - - struct Message { - uint64_t timestamp; - uint64_t activity_id; - uint64_t trace_id; - uint64_t thread; - uint8_t type; // OS_TRACE_TYPE_RELEASE, OS_TRACE_TYPE_DEBUG, - // OS_TRACE_TYPE_ERROR, OS_TRACE_TYPE_FAULT - uint32_t process_info_index; // index # of the image uuid/file path, 0 means - // unknown - std::string message; - }; - - typedef std::vector<Message> MessageList; - typedef std::vector<Breadcrumb> BreadcrumbList; - typedef std::vector<Activity> ActivityList; - - struct ThreadActivity { - Activity current_activity; - MessageList messages; - BreadcrumbList breadcrumbs; // should be 0 or 1 breadcrumbs; no more than 1 - // BC for any given activity - }; - - typedef std::shared_ptr<ThreadActivity> ThreadActivitySP; - - ThreadActivitySP GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid, - const MachThreadList &thread_list, - task_t task, bool &timed_out); - - struct ProcessExecutableInfo { - std::string image_path; - uuid_t image_uuid; - }; - - typedef std::shared_ptr<ProcessExecutableInfo> ProcessExecutableInfoSP; - - ProcessExecutableInfoSP GetProcessExecutableInfosAtIndex(size_t idx); - - uint32_t AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info); - -private: - void GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task); - - // the spi we need to call into libtrace - look them up via dlsym at runtime - bool (*m_os_activity_diagnostic_for_pid)(pid_t pid, os_activity_t activity, - uint32_t flags, - os_diagnostic_block_t block); - void (*m_os_activity_iterate_processes)( - os_activity_process_list_t processes, - bool (^iterator)(os_activity_process_t process_info)); - void (*m_os_activity_iterate_breadcrumbs)( - os_activity_process_t process_info, - bool (^iterator)(os_activity_breadcrumb_t breadcrumb)); - void (*m_os_activity_iterate_messages)( - os_trace_message_list_t messages, os_activity_process_t process_info, - bool (^iterator)(os_trace_message_t tracemsg)); - void (*m_os_activity_iterate_activities)( - os_activity_list_t activities, os_activity_process_t process_info, - bool (^iterator)(os_activity_entry_t activity)); - uint8_t (*m_os_trace_get_type)(os_trace_message_t trace_msg); - char *(*m_os_trace_copy_formatted_message)(os_trace_message_t trace_msg); - os_activity_t (*m_os_activity_for_thread)(os_activity_process_t process, - uint64_t thread_id); - os_activity_t (*m_os_activity_for_task_thread)(task_t target, - uint64_t thread_id); - os_trace_message_list_t (*m_os_activity_messages_for_thread)( - os_activity_process_t process, os_activity_t activity, - uint64_t thread_id); - - std::map<nub_thread_t, ThreadActivitySP> m_thread_activities; - std::vector<ProcessExecutableInfoSP> m_process_executable_infos; - bool m_diagnosticd_call_timed_out; -}; - -#endif // __Genealogy_h__ diff --git a/tools/debugserver/source/MacOSX/GenealogySPI.h b/tools/debugserver/source/MacOSX/GenealogySPI.h deleted file mode 100644 index de9db2d2e64a..000000000000 --- a/tools/debugserver/source/MacOSX/GenealogySPI.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- ActivitySPI.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// - -#ifndef __GenealogySPI_h__ -#define __GenealogySPI_h__ - -#include <xpc/xpc.h> - -typedef void *os_activity_process_list_t; -typedef void *os_activity_list_t; -typedef void *os_trace_message_list_t; -typedef struct os_activity_watch_s *os_activity_watch_t; -typedef uint64_t os_activity_t; - -struct os_activity_breadcrumb_s { - uint32_t breadcrumb_id; - uint64_t activity_id; - uint64_t timestamp; - const char *name; -}; - -typedef struct os_activity_breadcrumb_s *os_activity_breadcrumb_t; - -typedef struct os_trace_message_s { - uint64_t trace_id; - uint64_t thread; - uint64_t timestamp; - uint32_t offset; - xpc_object_t __unsafe_unretained payload; - const uint8_t *image_uuid; - const char *image_path; - const char *format; - const void *buffer; - size_t bufferLen; -} * os_trace_message_t; - -typedef struct os_activity_process_s { - os_activity_process_list_t child_procs; - os_trace_message_list_t messages; - os_activity_list_t activities; - void *breadcrumbs; - uint64_t proc_id; - const uint8_t *image_uuid; - const char *image_path; - pid_t pid; -} * os_activity_process_t; - -typedef struct os_activity_entry_s { - uint64_t activity_start; - os_activity_t activity_id; - os_activity_t parent_id; - const char *activity_name; - const char *reason; - os_trace_message_list_t messages; -} * os_activity_entry_t; - -enum { - OS_ACTIVITY_DIAGNOSTIC_DEFAULT = 0x00000000, - OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_DIAGNOSTIC_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_DIAGNOSTIC_FLATTENED = 0x00000004, - OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES = 0x00000008, - OS_ACTIVITY_DIAGNOSTIC_MAX = 0x0000000f -}; -typedef uint32_t os_activity_diagnostic_flag_t; - -enum { - OS_ACTIVITY_WATCH_DEFAULT = 0x00000000, - OS_ACTIVITY_WATCH_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_WATCH_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_WATCH_PAYLOAD = 0x00000004, - OS_ACTIVITY_WATCH_ERRORS = 0x00000008, - OS_ACTIVITY_WATCH_FAULTS = 0x00000010, - OS_ACTIVITY_WATCH_MAX = 0x0000001f -}; -typedef uint32_t os_activity_watch_flag_t; - -// Return values from os_trace_get_type() -#define OS_TRACE_TYPE_RELEASE (1u << 0) -#define OS_TRACE_TYPE_DEBUG (1u << 1) -#define OS_TRACE_TYPE_ERROR ((1u << 6) | (1u << 0)) -#define OS_TRACE_TYPE_FAULT ((1u << 7) | (1u << 6) | (1u << 0)) - -typedef void (^os_activity_watch_block_t)(os_activity_watch_t watch, - os_activity_process_t process_info, - bool canceled); -typedef void (^os_diagnostic_block_t)(os_activity_process_list_t processes, - int error); - -#endif diff --git a/tools/debugserver/source/MacOSX/MachException.cpp b/tools/debugserver/source/MacOSX/MachException.cpp deleted file mode 100644 index 01e5892d487d..000000000000 --- a/tools/debugserver/source/MacOSX/MachException.cpp +++ /dev/null @@ -1,513 +0,0 @@ -//===-- MachException.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#include "MachException.h" -#include "DNB.h" -#include "DNBError.h" -#include "DNBLog.h" -#include "MachProcess.h" -#include "PThreadMutex.h" -#include "SysSignal.h" -#include <errno.h> -#include <sys/ptrace.h> -#include <sys/types.h> - -// Routine mach_exception_raise -extern "C" kern_return_t -catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, - mach_port_t task, exception_type_t exception, - mach_exception_data_t code, - mach_msg_type_number_t codeCnt); - -extern "C" kern_return_t catch_mach_exception_raise_state( - mach_port_t exception_port, exception_type_t exception, - const mach_exception_data_t code, mach_msg_type_number_t codeCnt, - int *flavor, const thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt); - -// Routine mach_exception_raise_state_identity -extern "C" kern_return_t catch_mach_exception_raise_state_identity( - mach_port_t exception_port, mach_port_t thread, mach_port_t task, - exception_type_t exception, mach_exception_data_t code, - mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt); - -extern "C" boolean_t mach_exc_server(mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP); - -// Note: g_message points to the storage allocated to catch the data from -// catching the current exception raise. It's populated when we catch a raised -// exception which can't immediately be replied to. -// -// If it becomes possible to catch exceptions from multiple threads -// simultaneously, accesses to g_message would need to be mutually exclusive. -static MachException::Data *g_message = NULL; - -extern "C" kern_return_t catch_mach_exception_raise_state( - mach_port_t exc_port, exception_type_t exc_type, - const mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count, - int *flavor, const thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt) { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { - DNBLogThreaded("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data " - "= 0x%llx, exc_data_count = %d)", - __FUNCTION__, exc_port, exc_type, - MachException::Name(exc_type), (uint64_t)exc_data, - exc_data_count); - } - return KERN_FAILURE; -} - -extern "C" kern_return_t catch_mach_exception_raise_state_identity( - mach_port_t exc_port, mach_port_t thread_port, mach_port_t task_port, - exception_type_t exc_type, mach_exception_data_t exc_data, - mach_msg_type_number_t exc_data_count, int *flavor, - thread_state_t old_state, mach_msg_type_number_t old_stateCnt, - thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { - DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = " - "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, " - "0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); - } - - return KERN_FAILURE; -} - -extern "C" kern_return_t -catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, - mach_port_t task_port, exception_type_t exc_type, - mach_exception_data_t exc_data, - mach_msg_type_number_t exc_data_count) { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { - DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = " - "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, " - "0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); - } - g_message->exc_type = 0; - g_message->exc_data.clear(); - - if (task_port == g_message->task_port) { - g_message->task_port = task_port; - g_message->thread_port = thread_port; - g_message->exc_type = exc_type; - g_message->AppendExceptionData(exc_data, exc_data_count); - return KERN_SUCCESS; - } else if (!MachTask::IsValid(g_message->task_port)) { - // Our original exception port isn't valid anymore check for a SIGTRAP - if (exc_type == EXC_SOFTWARE && exc_data_count == 2 && - exc_data[0] == EXC_SOFT_SIGNAL && exc_data[1] == SIGTRAP) { - // We got a SIGTRAP which indicates we might have exec'ed and possibly - // lost our old task port during the exec, so we just need to switch over - // to using this new task port - g_message->task_port = task_port; - g_message->thread_port = thread_port; - g_message->exc_type = exc_type; - g_message->AppendExceptionData(exc_data, exc_data_count); - return KERN_SUCCESS; - } - } - return KERN_FAILURE; -} - -void MachException::Message::Dump() const { - DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_msg { bits = 0x%8.8x size = 0x%8.8x " - "remote-port = 0x%8.8x local-port = 0x%8.8x " - "reserved = 0x%8.8x id = 0x%8.8x } ", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id); - - DNBLogThreadedIf(LOG_EXCEPTIONS, "reply_msg { bits = 0x%8.8x size = 0x%8.8x " - "remote-port = 0x%8.8x local-port = 0x%8.8x " - "reserved = 0x%8.8x id = 0x%8.8x }", - reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, - reply_msg.hdr.msgh_local_port, reply_msg.hdr.msgh_reserved, - reply_msg.hdr.msgh_id); - - state.Dump(); -} - -bool MachException::Data::GetStopInfo( - struct DNBThreadStopInfo *stop_info) const { - // Zero out the structure. - memset(stop_info, 0, sizeof(struct DNBThreadStopInfo)); - - if (exc_type == 0) { - stop_info->reason = eStopTypeInvalid; - return true; - } - - // We always stop with a mach exceptions - stop_info->reason = eStopTypeException; - // Save the EXC_XXXX exception type - stop_info->details.exception.type = exc_type; - - // Fill in a text description - const char *exc_name = MachException::Name(exc_type); - char *desc = stop_info->description; - const char *end_desc = desc + DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH; - if (exc_name) - desc += - snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%s", exc_name); - else - desc += - snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%i", exc_type); - - stop_info->details.exception.data_count = exc_data.size(); - - int soft_signal = SoftSignal(); - if (soft_signal) { - if (desc < end_desc) { - const char *sig_str = SysSignal::Name(soft_signal); - snprintf(desc, end_desc - desc, " EXC_SOFT_SIGNAL( %i ( %s ))", - soft_signal, sig_str ? sig_str : "unknown signal"); - } - } else { - // No special disassembly for exception data, just - size_t idx; - if (desc < end_desc) { - desc += snprintf(desc, end_desc - desc, " data[%llu] = {", - (uint64_t)stop_info->details.exception.data_count); - - for (idx = 0; - desc < end_desc && idx < stop_info->details.exception.data_count; - ++idx) - desc += snprintf( - desc, end_desc - desc, "0x%llx%c", (uint64_t)exc_data[idx], - ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ',')); - } - } - - // Copy the exception data - size_t i; - for (i = 0; i < stop_info->details.exception.data_count; i++) - stop_info->details.exception.data[i] = exc_data[i]; - - return true; -} - -void MachException::Data::DumpStopReason() const { - int soft_signal = SoftSignal(); - if (soft_signal) { - const char *signal_str = SysSignal::Name(soft_signal); - if (signal_str) - DNBLog("signal(%s)", signal_str); - else - DNBLog("signal(%i)", soft_signal); - return; - } - DNBLog("%s", Name(exc_type)); -} - -kern_return_t MachException::Message::Receive(mach_port_t port, - mach_msg_option_t options, - mach_msg_timeout_t timeout, - mach_port_t notify_port) { - DNBError err; - const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS); - mach_msg_timeout_t mach_msg_timeout = - options & MACH_RCV_TIMEOUT ? timeout : 0; - if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0)) { - // Dump this log message if we have no timeout in case it never returns - DNBLogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = " - "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option " - "= %#x, send_size = 0, rcv_size = %llu, rcv_name = %#x, " - "timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, - (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, - notify_port); - } - - err = ::mach_msg(&exc_msg.hdr, - options, // options - 0, // Send size - sizeof(exc_msg.data), // Receive size - port, // exception port to watch for exception on - mach_msg_timeout, // timeout in msec (obeyed only if - // MACH_RCV_TIMEOUT is ORed into the - // options parameter) - notify_port); - - // Dump any errors we get - if (log_exceptions) { - err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = " - "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %u, rcv_name = " - "%#x, timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, - sizeof(exc_msg.data), port, mach_msg_timeout, notify_port); - } - return err.Status(); -} - -bool MachException::Message::CatchExceptionRaise(task_t task) { - bool success = false; - state.task_port = task; - g_message = &state; - // The exc_server function is the MIG generated server handling function - // to handle messages from the kernel relating to the occurrence of an - // exception in a thread. Such messages are delivered to the exception port - // set via thread_set_exception_ports or task_set_exception_ports. When an - // exception occurs in a thread, the thread sends an exception message to - // its exception port, blocking in the kernel waiting for the receipt of a - // reply. The exc_server function performs all necessary argument handling - // for this kernel message and calls catch_exception_raise, - // catch_exception_raise_state or catch_exception_raise_state_identity, - // which should handle the exception. If the called routine returns - // KERN_SUCCESS, a reply message will be sent, allowing the thread to - // continue from the point of the exception; otherwise, no reply message - // is sent and the called routine must have dealt with the exception - // thread directly. - if (mach_exc_server(&exc_msg.hdr, &reply_msg.hdr)) { - success = true; - } else if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { - DNBLogThreaded("mach_exc_server returned zero..."); - } - g_message = NULL; - return success; -} - -kern_return_t MachException::Message::Reply(MachProcess *process, int signal) { - // Reply to the exception... - DNBError err; - - // If we had a soft signal, we need to update the thread first so it can - // continue without signaling - int soft_signal = state.SoftSignal(); - if (soft_signal) { - int state_pid = -1; - if (process->Task().TaskPort() == state.task_port) { - // This is our task, so we can update the signal to send to it - state_pid = process->ProcessID(); - soft_signal = signal; - } else { - err = ::pid_for_task(state.task_port, &state_pid); - } - - assert(state_pid != -1); - if (state_pid != -1) { - errno = 0; - if (::ptrace(PT_THUPDATE, state_pid, - (caddr_t)((uintptr_t)state.thread_port), soft_signal) != 0) - err.SetError(errno, DNBError::POSIX); - else - err.Clear(); - - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::ptrace (request = PT_THUPDATE, pid = 0x%4.4x, tid = " - "0x%4.4x, signal = %i)", - state_pid, state.thread_port, soft_signal); - } - } - - DNBLogThreadedIf( - LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = " - "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %u, rcv_name = " - "%#x, timeout = %u, notify = %#x)", - reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, - MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, - MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - - err = ::mach_msg(&reply_msg.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT, - reply_msg.hdr.msgh_size, 0, MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - - if (err.Fail()) { - if (err.Status() == MACH_SEND_INTERRUPTED) { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreaded("::mach_msg() - send interrupted"); - // TODO: keep retrying to reply??? - } else { - if (state.task_port == process->Task().TaskPort()) { - DNBLogThreaded("error: mach_msg() returned an error when replying to a " - "mach exception: error = %u", - err.Status()); - } else { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreaded("::mach_msg() - failed (child of task)"); - } - } - } - - return err.Status(); -} - -void MachException::Data::Dump() const { - const char *exc_type_name = MachException::Name(exc_type); - DNBLogThreadedIf( - LOG_EXCEPTIONS, " state { task_port = 0x%4.4x, thread_port = " - "0x%4.4x, exc_type = %i (%s) ...", - task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???"); - - const size_t exc_data_count = exc_data.size(); - // Dump any special exception data contents - int soft_signal = SoftSignal(); - if (soft_signal != 0) { - const char *sig_str = SysSignal::Name(soft_signal); - DNBLogThreadedIf(LOG_EXCEPTIONS, - " exc_data: EXC_SOFT_SIGNAL (%i (%s))", - soft_signal, sig_str ? sig_str : "unknown signal"); - } else { - // No special disassembly for this data, just dump the data - size_t idx; - for (idx = 0; idx < exc_data_count; ++idx) { - DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data[%llu]: 0x%llx", - (uint64_t)idx, (uint64_t)exc_data[idx]); - } - } -} - -// The EXC_MASK_ALL value hard-coded here so that lldb can be built -// on a new OS with an older deployment target . The new OS may have -// an addition to its EXC_MASK_ALL that the old OS will not recognize - -// <mach/exception_types.h> doesn't vary the value based on the deployment -// target. So we need a known set of masks that can be assumed to be -// valid when running on an older OS. We'll fall back to trying -// PREV_EXC_MASK_ALL if the EXC_MASK_ALL value lldb was compiled with is -// not recognized. - -#define PREV_EXC_MASK_ALL (EXC_MASK_BAD_ACCESS | \ - EXC_MASK_BAD_INSTRUCTION | \ - EXC_MASK_ARITHMETIC | \ - EXC_MASK_EMULATION | \ - EXC_MASK_SOFTWARE | \ - EXC_MASK_BREAKPOINT | \ - EXC_MASK_SYSCALL | \ - EXC_MASK_MACH_SYSCALL | \ - EXC_MASK_RPC_ALERT | \ - EXC_MASK_RESOURCE | \ - EXC_MASK_GUARD | \ - EXC_MASK_MACHINE) - -#define LLDB_EXC_MASK EXC_MASK_ALL - -kern_return_t MachException::PortInfo::Save(task_t task) { - DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, - "MachException::PortInfo::Save ( task = 0x%4.4x )", task); - // Be careful to be able to have debugserver built on a newer OS than what - // it is currently running on by being able to start with all exceptions - // and back off to just what is supported on the current system - DNBError err; - - mask = LLDB_EXC_MASK; - - count = (sizeof(ports) / sizeof(ports[0])); - err = ::task_get_exception_ports(task, mask, masks, &count, ports, behaviors, - flavors); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, " - "maskCnt => %u, ports, behaviors, flavors )", - task, mask, count); - - if (err.Status() == KERN_INVALID_ARGUMENT && mask != PREV_EXC_MASK_ALL) { - mask = PREV_EXC_MASK_ALL; - count = (sizeof(ports) / sizeof(ports[0])); - err = ::task_get_exception_ports(task, mask, masks, &count, ports, - behaviors, flavors); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors )", - task, mask, count); - } - if (err.Fail()) { - mask = 0; - count = 0; - } - return err.Status(); -} - -kern_return_t MachException::PortInfo::Restore(task_t task) { - DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, - "MachException::PortInfo::Restore( task = 0x%4.4x )", task); - uint32_t i = 0; - DNBError err; - if (count > 0) { - for (i = 0; i < count; i++) { - err = ::task_set_exception_ports(task, masks[i], ports[i], behaviors[i], - flavors[i]); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { - err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x )", - task, masks[i], ports[i], behaviors[i], flavors[i]); - // Bail if we encounter any errors - } - - if (err.Fail()) - break; - } - } - count = 0; - return err.Status(); -} - -const char *MachException::Name(exception_type_t exc_type) { - switch (exc_type) { - case EXC_BAD_ACCESS: - return "EXC_BAD_ACCESS"; - case EXC_BAD_INSTRUCTION: - return "EXC_BAD_INSTRUCTION"; - case EXC_ARITHMETIC: - return "EXC_ARITHMETIC"; - case EXC_EMULATION: - return "EXC_EMULATION"; - case EXC_SOFTWARE: - return "EXC_SOFTWARE"; - case EXC_BREAKPOINT: - return "EXC_BREAKPOINT"; - case EXC_SYSCALL: - return "EXC_SYSCALL"; - case EXC_MACH_SYSCALL: - return "EXC_MACH_SYSCALL"; - case EXC_RPC_ALERT: - return "EXC_RPC_ALERT"; - case EXC_CRASH: - return "EXC_CRASH"; - case EXC_RESOURCE: - return "EXC_RESOURCE"; -#ifdef EXC_GUARD - case EXC_GUARD: - return "EXC_GUARD"; -#endif -#ifdef EXC_CORPSE_NOTIFY - case EXC_CORPSE_NOTIFY: - return "EXC_CORPSE_NOTIFY"; -#endif -#ifdef EXC_CORPSE_VARIANT_BIT - case EXC_CORPSE_VARIANT_BIT: - return "EXC_CORPSE_VARIANT_BIT"; -#endif - default: - break; - } - return NULL; -} diff --git a/tools/debugserver/source/MacOSX/MachException.h b/tools/debugserver/source/MacOSX/MachException.h deleted file mode 100644 index e1af12def10a..000000000000 --- a/tools/debugserver/source/MacOSX/MachException.h +++ /dev/null @@ -1,133 +0,0 @@ -//===-- MachException.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachException_h__ -#define __MachException_h__ - -#include <mach/mach.h> -#include <vector> - -class MachProcess; -class PThreadMutex; - -typedef union MachMessageTag { - mach_msg_header_t hdr; - char data[1024]; -} MachMessage; - -class MachException { -public: - struct PortInfo { - exception_mask_t mask; // the exception mask for this device which may be a - // subset of EXC_MASK_ALL... - exception_mask_t masks[EXC_TYPES_COUNT]; - mach_port_t ports[EXC_TYPES_COUNT]; - exception_behavior_t behaviors[EXC_TYPES_COUNT]; - thread_state_flavor_t flavors[EXC_TYPES_COUNT]; - mach_msg_type_number_t count; - - kern_return_t Save(task_t task); - kern_return_t Restore(task_t task); - }; - - struct Data { - task_t task_port; - thread_t thread_port; - exception_type_t exc_type; - std::vector<mach_exception_data_type_t> exc_data; - Data() - : task_port(TASK_NULL), thread_port(THREAD_NULL), exc_type(0), - exc_data() {} - - void Clear() { - task_port = TASK_NULL; - thread_port = THREAD_NULL; - exc_type = 0; - exc_data.clear(); - } - bool IsValid() const { - return task_port != TASK_NULL && thread_port != THREAD_NULL && - exc_type != 0; - } - // Return the SoftSignal for this MachException data, or zero if there is - // none - int SoftSignal() const { - if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && - exc_data[0] == EXC_SOFT_SIGNAL) - return static_cast<int>(exc_data[1]); - return 0; - } - bool IsBreakpoint() const { - return (exc_type == EXC_BREAKPOINT || - ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1)); - } - void AppendExceptionData(mach_exception_data_t Data, - mach_msg_type_number_t Count) { - mach_exception_data_type_t Buf; - for (mach_msg_type_number_t i = 0; i < Count; ++i) { - // Perform an unaligned copy. - memcpy(&Buf, Data + i, sizeof(mach_exception_data_type_t)); - exc_data.push_back(Buf); - } - } - void Dump() const; - void DumpStopReason() const; - bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const; - }; - - struct Message { - MachMessage exc_msg; - MachMessage reply_msg; - Data state; - - Message() : state() { - memset(&exc_msg, 0, sizeof(exc_msg)); - memset(&reply_msg, 0, sizeof(reply_msg)); - } - bool CatchExceptionRaise(task_t task); - void Dump() const; - kern_return_t Reply(MachProcess *process, int signal); - kern_return_t Receive(mach_port_t receive_port, mach_msg_option_t options, - mach_msg_timeout_t timeout, - mach_port_t notify_port = MACH_PORT_NULL); - - typedef std::vector<Message> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - }; - - enum { - e_actionForward, // Forward signal to inferior process - e_actionStop, // Stop when this signal is received - }; - struct Action { - task_t task_port; // Set to TASK_NULL for any TASK - thread_t thread_port; // Set to THREAD_NULL for any thread - exception_type_t exc_mask; // Mach exception mask to watch for - std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to - // exception data, or - // empty to ignore - // exc_data value for - // exception - std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare - // to exception data - // after masking, or - // empty to ignore - // exc_data value - // for exception - uint8_t flags; // Action flags describing what to do with the exception - }; - static const char *Name(exception_type_t exc_type); -}; - -#endif diff --git a/tools/debugserver/source/MacOSX/MachProcess.h b/tools/debugserver/source/MacOSX/MachProcess.h deleted file mode 100644 index 2fb4dc5dbb6e..000000000000 --- a/tools/debugserver/source/MacOSX/MachProcess.h +++ /dev/null @@ -1,448 +0,0 @@ -//===-- MachProcess.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/15/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachProcess_h__ -#define __MachProcess_h__ - -#include <CoreFoundation/CoreFoundation.h> -#include <mach-o/loader.h> -#include <mach/mach.h> -#include <pthread.h> -#include <sys/signal.h> -#include <uuid/uuid.h> -#include <vector> - -#include "DNBBreakpoint.h" -#include "DNBDefs.h" -#include "DNBError.h" -#include "DNBThreadResumeActions.h" -#include "Genealogy.h" -#include "JSONGenerator.h" -#include "MachException.h" -#include "MachTask.h" -#include "MachThreadList.h" -#include "MachVMMemory.h" -#include "PThreadCondition.h" -#include "PThreadEvent.h" -#include "PThreadMutex.h" -#include "ThreadInfo.h" - -class DNBThreadResumeActions; - -class MachProcess { -public: - //---------------------------------------------------------------------- - // Constructors and Destructors - //---------------------------------------------------------------------- - MachProcess(); - ~MachProcess(); - - // A structure that can hold everything debugserver needs to know from - // a binary's Mach-O header / load commands. - - struct mach_o_segment { - std::string name; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - uint64_t maxprot; - uint64_t initprot; - uint64_t nsects; - uint64_t flags; - }; - - struct mach_o_information { - struct mach_header_64 mach_header; - std::vector<struct mach_o_segment> segments; - uuid_t uuid; - std::string min_version_os_name; - std::string min_version_os_version; - }; - - struct binary_image_information { - std::string filename; - uint64_t load_address; - uint64_t mod_date; // may not be available - 0 if so - struct mach_o_information macho_info; - - binary_image_information() - : filename(), load_address(INVALID_NUB_ADDRESS), mod_date(0) {} - }; - - //---------------------------------------------------------------------- - // Child process control - //---------------------------------------------------------------------- - pid_t AttachForDebug(pid_t pid, char *err_str, size_t err_len); - pid_t LaunchForDebug(const char *path, char const *argv[], char const *envp[], - const char *working_directory, const char *stdin_path, - const char *stdout_path, const char *stderr_path, - bool no_stdio, nub_launch_flavor_t launch_flavor, - int disable_aslr, const char *event_data, DNBError &err); - - static uint32_t GetCPUTypeForLocalProcess(pid_t pid); - static pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[], - char const *envp[], - MachProcess *process, DNBError &err); - static pid_t PosixSpawnChildForPTraceDebugging( - const char *path, cpu_type_t cpu_type, char const *argv[], - char const *envp[], const char *working_directory, const char *stdin_path, - const char *stdout_path, const char *stderr_path, bool no_stdio, - MachProcess *process, int disable_aslr, DNBError &err); - nub_addr_t GetDYLDAllImageInfosAddress(); - static const void *PrepareForAttach(const char *path, - nub_launch_flavor_t launch_flavor, - bool waitfor, DNBError &err_str); - static void CleanupAfterAttach(const void *attach_token, - nub_launch_flavor_t launch_flavor, - bool success, DNBError &err_str); - static nub_process_t CheckForProcess(const void *attach_token, - nub_launch_flavor_t launch_flavor); -#if defined(WITH_BKS) || defined(WITH_FBS) - pid_t BoardServiceLaunchForDebug(const char *app_bundle_path, - char const *argv[], char const *envp[], - bool no_stdio, bool disable_aslr, - const char *event_data, - DNBError &launch_err); - pid_t BoardServiceForkChildForPTraceDebugging( - const char *path, char const *argv[], char const *envp[], bool no_stdio, - bool disable_aslr, const char *event_data, DNBError &launch_err); - bool BoardServiceSendEvent(const char *event, DNBError &error); -#endif - static bool GetOSVersionNumbers(uint64_t *major, uint64_t *minor, - uint64_t *patch); -#ifdef WITH_BKS - static void BKSCleanupAfterAttach(const void *attach_token, - DNBError &err_str); -#endif // WITH_BKS -#ifdef WITH_FBS - static void FBSCleanupAfterAttach(const void *attach_token, - DNBError &err_str); -#endif // WITH_FBS -#ifdef WITH_SPRINGBOARD - pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[], - char const *envp[], bool no_stdio, bool disable_aslr, - DNBError &launch_err); - static pid_t SBForkChildForPTraceDebugging(const char *path, - char const *argv[], - char const *envp[], bool no_stdio, - MachProcess *process, - DNBError &launch_err); -#endif // WITH_SPRINGBOARD - nub_addr_t LookupSymbol(const char *name, const char *shlib); - void SetNameToAddressCallback(DNBCallbackNameToAddress callback, - void *baton) { - m_name_to_addr_callback = callback; - m_name_to_addr_baton = baton; - } - void - SetSharedLibraryInfoCallback(DNBCallbackCopyExecutableImageInfos callback, - void *baton) { - m_image_infos_callback = callback; - m_image_infos_baton = baton; - } - - bool Resume(const DNBThreadResumeActions &thread_actions); - bool Signal(int signal, const struct timespec *timeout_abstime = NULL); - bool Interrupt(); - bool SendEvent(const char *event, DNBError &send_err); - bool Kill(const struct timespec *timeout_abstime = NULL); - bool Detach(); - nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf); - nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf); - - //---------------------------------------------------------------------- - // Path and arg accessors - //---------------------------------------------------------------------- - const char *Path() const { return m_path.c_str(); } - size_t ArgumentCount() const { return m_args.size(); } - const char *ArgumentAtIndex(size_t arg_idx) const { - if (arg_idx < m_args.size()) - return m_args[arg_idx].c_str(); - return NULL; - } - - //---------------------------------------------------------------------- - // Breakpoint functions - //---------------------------------------------------------------------- - DNBBreakpoint *CreateBreakpoint(nub_addr_t addr, nub_size_t length, - bool hardware); - bool DisableBreakpoint(nub_addr_t addr, bool remove); - void DisableAllBreakpoints(bool remove); - bool EnableBreakpoint(nub_addr_t addr); - DNBBreakpointList &Breakpoints() { return m_breakpoints; } - const DNBBreakpointList &Breakpoints() const { return m_breakpoints; } - - //---------------------------------------------------------------------- - // Watchpoint functions - //---------------------------------------------------------------------- - DNBBreakpoint *CreateWatchpoint(nub_addr_t addr, nub_size_t length, - uint32_t watch_type, bool hardware); - bool DisableWatchpoint(nub_addr_t addr, bool remove); - void DisableAllWatchpoints(bool remove); - bool EnableWatchpoint(nub_addr_t addr); - uint32_t GetNumSupportedHardwareWatchpoints() const; - DNBBreakpointList &Watchpoints() { return m_watchpoints; } - const DNBBreakpointList &Watchpoints() const { return m_watchpoints; } - - //---------------------------------------------------------------------- - // Exception thread functions - //---------------------------------------------------------------------- - bool StartSTDIOThread(); - static void *STDIOThread(void *arg); - void ExceptionMessageReceived(const MachException::Message &exceptionMessage); - task_t ExceptionMessageBundleComplete(); - void SharedLibrariesUpdated(); - nub_size_t CopyImageInfos(struct DNBExecutableImageInfo **image_infos, - bool only_changed); - - //---------------------------------------------------------------------- - // Profile functions - //---------------------------------------------------------------------- - void SetEnableAsyncProfiling(bool enable, uint64_t internal_usec, - DNBProfileDataScanType scan_type); - bool IsProfilingEnabled() { return m_profile_enabled; } - useconds_t ProfileInterval() { return m_profile_interval_usec; } - bool StartProfileThread(); - static void *ProfileThread(void *arg); - void SignalAsyncProfileData(const char *info); - size_t GetAsyncProfileData(char *buf, size_t buf_size); - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - pid_t ProcessID() const { return m_pid; } - bool ProcessIDIsValid() const { return m_pid > 0; } - pid_t SetProcessID(pid_t pid); - MachTask &Task() { return m_task; } - const MachTask &Task() const { return m_task; } - - PThreadEvent &Events() { return m_events; } - const DNBRegisterSetInfo *GetRegisterSetInfo(nub_thread_t tid, - nub_size_t *num_reg_sets) const; - bool GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - DNBRegisterValue *reg_value) const; - bool SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - const DNBRegisterValue *value) const; - nub_bool_t SyncThreadState(nub_thread_t tid); - const char *ThreadGetName(nub_thread_t tid); - nub_state_t ThreadGetState(nub_thread_t tid); - ThreadInfo::QoS GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, - uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT(nub_thread_t tid); - nub_addr_t GetDispatchQueueT(nub_thread_t tid); - nub_addr_t - GetTSDAddressForThread(nub_thread_t tid, - uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size); - const char * - GetDeploymentInfo(const struct load_command&, uint64_t load_command_address, - uint32_t& major_version, uint32_t& minor_version, - uint32_t& patch_version); - bool GetMachOInformationFromMemory(nub_addr_t mach_o_header_addr, - int wordsize, - struct mach_o_information &inf); - JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON( - const std::vector<struct binary_image_information> &image_infos); - void GetAllLoadedBinariesViaDYLDSPI( - std::vector<struct binary_image_information> &image_infos); - JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos( - nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); - JSONGenerator::ObjectSP - GetLibrariesInfoForAddresses(nub_process_t pid, - std::vector<uint64_t> &macho_addresses); - JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos(nub_process_t pid); - JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid); - - nub_size_t GetNumThreads() const; - nub_thread_t GetThreadAtIndex(nub_size_t thread_idx) const; - nub_thread_t GetCurrentThread(); - nub_thread_t GetCurrentThreadMachPort(); - nub_thread_t SetCurrentThread(nub_thread_t tid); - MachThreadList &GetThreadList() { return m_thread_list; } - bool GetThreadStoppedReason(nub_thread_t tid, - struct DNBThreadStopInfo *stop_info); - void DumpThreadStoppedReason(nub_thread_t tid) const; - const char *GetThreadInfo(nub_thread_t tid) const; - - nub_thread_t GetThreadIDForMachPortNumber(thread_t mach_port_number) const; - - uint32_t GetCPUType(); - nub_state_t GetState(); - void SetState(nub_state_t state); - bool IsRunning(nub_state_t state) { - return state == eStateRunning || IsStepping(state); - } - bool IsStepping(nub_state_t state) { return state == eStateStepping; } - bool CanResume(nub_state_t state) { return state == eStateStopped; } - - bool GetExitStatus(int *status) { - if (GetState() == eStateExited) { - if (status) - *status = m_exit_status; - return true; - } - return false; - } - void SetExitStatus(int status) { - m_exit_status = status; - SetState(eStateExited); - } - const char *GetExitInfo() { return m_exit_info.c_str(); } - - void SetExitInfo(const char *info); - - uint32_t StopCount() const { return m_stop_count; } - void SetChildFileDescriptors(int stdin_fileno, int stdout_fileno, - int stderr_fileno) { - m_child_stdin = stdin_fileno; - m_child_stdout = stdout_fileno; - m_child_stderr = stderr_fileno; - } - - int GetStdinFileDescriptor() const { return m_child_stdin; } - int GetStdoutFileDescriptor() const { return m_child_stdout; } - int GetStderrFileDescriptor() const { return m_child_stderr; } - void AppendSTDOUT(char *s, size_t len); - size_t GetAvailableSTDOUT(char *buf, size_t buf_size); - size_t GetAvailableSTDERR(char *buf, size_t buf_size); - void CloseChildFileDescriptors() { - if (m_child_stdin >= 0) { - ::close(m_child_stdin); - m_child_stdin = -1; - } - if (m_child_stdout >= 0) { - ::close(m_child_stdout); - m_child_stdout = -1; - } - if (m_child_stderr >= 0) { - ::close(m_child_stderr); - m_child_stderr = -1; - } - } - - bool ProcessUsingSpringBoard() const { - return (m_flags & eMachProcessFlagsUsingSBS) != 0; - } - bool ProcessUsingBackBoard() const { - return (m_flags & eMachProcessFlagsUsingBKS) != 0; - } - - Genealogy::ThreadActivitySP GetGenealogyInfoForThread(nub_thread_t tid, - bool &timed_out); - - Genealogy::ProcessExecutableInfoSP GetGenealogyImageInfo(size_t idx); - - DNBProfileDataScanType GetProfileScanType() { return m_profile_scan_type; } - -private: - enum { - eMachProcessFlagsNone = 0, - eMachProcessFlagsAttached = (1 << 0), - eMachProcessFlagsUsingSBS = (1 << 1), - eMachProcessFlagsUsingBKS = (1 << 2), - eMachProcessFlagsUsingFBS = (1 << 3) - }; - void Clear(bool detaching = false); - void ReplyToAllExceptions(); - void PrivateResume(); - - uint32_t Flags() const { return m_flags; } - nub_state_t DoSIGSTOP(bool clear_bps_and_wps, bool allow_running, - uint32_t *thread_idx_ptr); - - pid_t m_pid; // Process ID of child process - cpu_type_t m_cpu_type; // The CPU type of this process - int m_child_stdin; - int m_child_stdout; - int m_child_stderr; - std::string m_path; // A path to the executable if we have one - std::vector<std::string> - m_args; // The arguments with which the process was lauched - int m_exit_status; // The exit status for the process - std::string m_exit_info; // Any extra info that we may have about the exit - MachTask m_task; // The mach task for this process - uint32_t m_flags; // Process specific flags (see eMachProcessFlags enums) - uint32_t m_stop_count; // A count of many times have we stopped - pthread_t m_stdio_thread; // Thread ID for the thread that watches for child - // process stdio - PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio - std::string m_stdout_data; - - bool m_profile_enabled; // A flag to indicate if profiling is enabled - useconds_t m_profile_interval_usec; // If enable, the profiling interval in - // microseconds - DNBProfileDataScanType - m_profile_scan_type; // Indicates what needs to be profiled - pthread_t - m_profile_thread; // Thread ID for the thread that profiles the inferior - PThreadMutex - m_profile_data_mutex; // Multithreaded protection for profile info data - std::vector<std::string> - m_profile_data; // Profile data, must be protected by m_profile_data_mutex - - DNBThreadResumeActions m_thread_actions; // The thread actions for the current - // MachProcess::Resume() call - MachException::Message::collection m_exception_messages; // A collection of - // exception messages - // caught when - // listening to the - // exception port - PThreadMutex m_exception_messages_mutex; // Multithreaded protection for - // m_exception_messages - - MachThreadList m_thread_list; // A list of threads that is maintained/updated - // after each stop - Genealogy m_activities; // A list of activities that is updated after every - // stop lazily - nub_state_t m_state; // The state of our process - PThreadMutex m_state_mutex; // Multithreaded protection for m_state - PThreadEvent m_events; // Process related events in the child processes - // lifetime can be waited upon - PThreadEvent m_private_events; // Used to coordinate running and stopping the - // process without affecting m_events - DNBBreakpointList m_breakpoints; // Breakpoint list for this process - DNBBreakpointList m_watchpoints; // Watchpoint list for this process - DNBCallbackNameToAddress m_name_to_addr_callback; - void *m_name_to_addr_baton; - DNBCallbackCopyExecutableImageInfos m_image_infos_callback; - void *m_image_infos_baton; - std::string - m_bundle_id; // If we are a SB or BKS process, this will be our bundle ID. - int m_sent_interrupt_signo; // When we call MachProcess::Interrupt(), we want - // to send a single signal - // to the inferior and only send the signal if we aren't already stopped. - // If we end up sending a signal to stop the process we store it until we - // receive an exception with this signal. This helps us to verify we got - // the signal that interrupted the process. We might stop due to another - // reason after an interrupt signal is sent, so this helps us ensure that - // we don't report a spurious stop on the next resume. - int m_auto_resume_signo; // If we resume the process and still haven't - // received our interrupt signal - // acknownledgement, we will shortly after the next resume. We store the - // interrupt signal in this variable so when we get the interrupt signal - // as the sole reason for the process being stopped, we can auto resume - // the process. - bool m_did_exec; - - void *(*m_dyld_process_info_create)(task_t task, uint64_t timestamp, - kern_return_t *kernelError); - void (*m_dyld_process_info_for_each_image)( - void *info, void (^callback)(uint64_t machHeaderAddress, - const uuid_t uuid, const char *path)); - void (*m_dyld_process_info_release)(void *info); - void (*m_dyld_process_info_get_cache)(void *info, void *cacheInfo); -}; - -#endif // __MachProcess_h__ diff --git a/tools/debugserver/source/MacOSX/MachProcess.mm b/tools/debugserver/source/MacOSX/MachProcess.mm deleted file mode 100644 index a3b905d05150..000000000000 --- a/tools/debugserver/source/MacOSX/MachProcess.mm +++ /dev/null @@ -1,3919 +0,0 @@ -//===-- MachProcess.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/15/07. -// -//===----------------------------------------------------------------------===// - -#include "DNB.h" -#include "MacOSX/CFUtils.h" -#include "SysSignal.h" -#include <dlfcn.h> -#include <inttypes.h> -#include <mach-o/loader.h> -#include <mach/mach.h> -#include <mach/task.h> -#include <pthread.h> -#include <signal.h> -#include <spawn.h> -#include <sys/fcntl.h> -#include <sys/ptrace.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <sys/types.h> -#include <unistd.h> -#include <uuid/uuid.h> - -#include <algorithm> -#include <map> - -#import <Foundation/Foundation.h> - -#include "DNBDataRef.h" -#include "DNBLog.h" -#include "DNBThreadResumeActions.h" -#include "DNBTimer.h" -#include "MachProcess.h" -#include "PseudoTerminal.h" - -#include "CFBundle.h" -#include "CFString.h" - -#ifdef WITH_SPRINGBOARD - -#include <CoreFoundation/CoreFoundation.h> -#include <SpringBoardServices/SBSWatchdogAssertion.h> -#include <SpringBoardServices/SpringBoardServer.h> - -static bool IsSBProcess(nub_process_t pid) { - CFReleaser<CFArrayRef> appIdsForPID( - ::SBSCopyDisplayIdentifiersForProcessID(pid)); - return appIdsForPID.get() != NULL; -} - -#endif // WITH_SPRINGBOARD - -#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) -// This returns a CFRetained pointer to the Bundle ID for app_bundle_path, -// or NULL if there was some problem getting the bundle id. -static CFStringRef CopyBundleIDForPath(const char *app_bundle_path, - DNBError &err_str); -#endif - -#if defined(WITH_BKS) || defined(WITH_FBS) -#import <Foundation/Foundation.h> -static const int OPEN_APPLICATION_TIMEOUT_ERROR = 111; -typedef void (*SetErrorFunction)(NSInteger, DNBError &); -typedef bool (*CallOpenApplicationFunction)(NSString *bundleIDNSStr, - NSDictionary *options, - DNBError &error, pid_t *return_pid); -// This function runs the BKSSystemService (or FBSSystemService) method -// openApplication:options:clientPort:withResult, -// messaging the app passed in bundleIDNSStr. -// The function should be run inside of an NSAutoReleasePool. -// -// It will use the "options" dictionary passed in, and fill the error passed in -// if there is an error. -// If return_pid is not NULL, we'll fetch the pid that was made for the -// bundleID. -// If bundleIDNSStr is NULL, then the system application will be messaged. - -template <typename OpenFlavor, typename ErrorFlavor, - ErrorFlavor no_error_enum_value, SetErrorFunction error_function> -static bool CallBoardSystemServiceOpenApplication(NSString *bundleIDNSStr, - NSDictionary *options, - DNBError &error, - pid_t *return_pid) { - // Now make our systemService: - OpenFlavor *system_service = [[OpenFlavor alloc] init]; - - if (bundleIDNSStr == nil) { - bundleIDNSStr = [system_service systemApplicationBundleIdentifier]; - if (bundleIDNSStr == nil) { - // Okay, no system app... - error.SetErrorString("No system application to message."); - return false; - } - } - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block ErrorFlavor open_app_error = no_error_enum_value; - bool wants_pid = (return_pid != NULL); - __block pid_t pid_in_block; - - const char *cstr = [bundleIDNSStr UTF8String]; - if (!cstr) - cstr = "<Unknown Bundle ID>"; - - NSString *description = [options description]; - DNBLog("About to launch process for bundle ID: %s - options:\n%s", cstr, - [description UTF8String]); - [system_service - openApplication:bundleIDNSStr - options:options - clientPort:client_port - withResult:^(NSError *bks_error) { - // The system service will cleanup the client port we created for - // us. - if (bks_error) - open_app_error = (ErrorFlavor)[bks_error code]; - - if (open_app_error == no_error_enum_value) { - if (wants_pid) { - pid_in_block = - [system_service pidForApplication:bundleIDNSStr]; - DNBLog( - "In completion handler, got pid for bundle id, pid: %d.", - pid_in_block); - DNBLogThreadedIf( - LOG_PROCESS, - "In completion handler, got pid for bundle id, pid: %d.", - pid_in_block); - } else - DNBLogThreadedIf(LOG_PROCESS, - "In completion handler: success."); - } else { - const char *error_str = - [(NSString *)[bks_error localizedDescription] UTF8String]; - DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send " - "event, got error \"%s\"(%ld).", - error_str ? error_str : "<unknown error>", - open_app_error); - // REMOVE ME - DNBLogError("In completion handler for send event, got error " - "\"%s\"(%ld).", - error_str ? error_str : "<unknown error>", - open_app_error); - } - - [system_service release]; - dispatch_semaphore_signal(semaphore); - } - - ]; - - const uint32_t timeout_secs = 30; - - dispatch_time_t timeout = - dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - dispatch_release(semaphore); - - if (!success) { - DNBLogError("timed out trying to send openApplication to %s.", cstr); - error.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - error.SetErrorString("timed out trying to launch app"); - } else if (open_app_error != no_error_enum_value) { - error_function(open_app_error, error); - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' " - "bks_error = %u", - cstr, open_app_error); - success = false; - } else if (wants_pid) { - *return_pid = pid_in_block; - DNBLogThreadedIf( - LOG_PROCESS, - "Out of completion handler, pid from block %d and passing out: %d", - pid_in_block, *return_pid); - } - - return success; -} -#endif - -#if defined(WITH_BKS) || defined(WITH_FBS) -static void SplitEventData(const char *data, std::vector<std::string> &elements) -{ - elements.clear(); - if (!data) - return; - - const char *start = data; - - while (*start != '\0') { - const char *token = strchr(start, ':'); - if (!token) { - elements.push_back(std::string(start)); - return; - } - if (token != start) - elements.push_back(std::string(start, token - start)); - start = ++token; - } -} -#endif - -#ifdef WITH_BKS -#import <Foundation/Foundation.h> -extern "C" { -#import <BackBoardServices/BKSOpenApplicationConstants_Private.h> -#import <BackBoardServices/BKSSystemService_LaunchServices.h> -#import <BackBoardServices/BackBoardServices.h> -} - -static bool IsBKSProcess(nub_process_t pid) { - BKSApplicationStateMonitor *state_monitor = - [[BKSApplicationStateMonitor alloc] init]; - BKSApplicationState app_state = - [state_monitor mostElevatedApplicationStateForPID:pid]; - return app_state != BKSApplicationStateUnknown; -} - -static void SetBKSError(NSInteger error_code, DNBError &error) { - error.SetError(error_code, DNBError::BackBoard); - NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString( - (BKSOpenApplicationErrorCode)error_code); - const char *err_str = NULL; - if (err_nsstr == NULL) - err_str = "unknown BKS error"; - else { - err_str = [err_nsstr UTF8String]; - if (err_str == NULL) - err_str = "unknown BKS error"; - } - error.SetErrorString(err_str); -} - -static bool BKSAddEventDataToOptions(NSMutableDictionary *options, - const char *event_data, - DNBError &option_error) { - std::vector<std::string> values; - SplitEventData(event_data, values); - bool found_one = false; - for (std::string value : values) - { - if (value.compare("BackgroundContentFetching") == 0) { - DNBLog("Setting ActivateForEvent key in options dictionary."); - NSDictionary *event_details = [NSDictionary dictionary]; - NSDictionary *event_dictionary = [NSDictionary - dictionaryWithObject:event_details - forKey: - BKSActivateForEventOptionTypeBackgroundContentFetching]; - [options setObject:event_dictionary - forKey:BKSOpenApplicationOptionKeyActivateForEvent]; - found_one = true; - } else if (value.compare("ActivateSuspended") == 0) { - DNBLog("Setting ActivateSuspended key in options dictionary."); - [options setObject:@YES forKey: BKSOpenApplicationOptionKeyActivateSuspended]; - found_one = true; - } else { - DNBLogError("Unrecognized event type: %s. Ignoring.", value.c_str()); - option_error.SetErrorString("Unrecognized event data"); - } - } - return found_one; -} - -static NSMutableDictionary *BKSCreateOptionsDictionary( - const char *app_bundle_path, NSMutableArray *launch_argv, - NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, - const char *event_data) { - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - if (launch_argv != nil) - [debug_options setObject:launch_argv forKey:BKSDebugOptionKeyArguments]; - if (launch_envp != nil) - [debug_options setObject:launch_envp forKey:BKSDebugOptionKeyEnvironment]; - - [debug_options setObject:stdio_path forKey:BKSDebugOptionKeyStandardOutPath]; - [debug_options setObject:stdio_path - forKey:BKSDebugOptionKeyStandardErrorPath]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:BKSDebugOptionKeyWaitForDebugger]; - if (disable_aslr) - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:BKSDebugOptionKeyDisableASLR]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject:debug_options - forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; - // And there are some other options at the top level in this dictionary: - [options setObject:[NSNumber numberWithBool:YES] - forKey:BKSOpenApplicationOptionKeyUnlockDevice]; - - DNBError error; - BKSAddEventDataToOptions(options, event_data, error); - - return options; -} - -static CallOpenApplicationFunction BKSCallOpenApplicationFunction = - CallBoardSystemServiceOpenApplication< - BKSSystemService, BKSOpenApplicationErrorCode, - BKSOpenApplicationErrorCodeNone, SetBKSError>; -#endif // WITH_BKS - -#ifdef WITH_FBS -#import <Foundation/Foundation.h> -extern "C" { -#import <FrontBoardServices/FBSOpenApplicationConstants_Private.h> -#import <FrontBoardServices/FBSSystemService_LaunchServices.h> -#import <FrontBoardServices/FrontBoardServices.h> -#import <MobileCoreServices/LSResourceProxy.h> -#import <MobileCoreServices/MobileCoreServices.h> -} - -#ifdef WITH_BKS -static bool IsFBSProcess(nub_process_t pid) { - BKSApplicationStateMonitor *state_monitor = - [[BKSApplicationStateMonitor alloc] init]; - BKSApplicationState app_state = - [state_monitor mostElevatedApplicationStateForPID:pid]; - return app_state != BKSApplicationStateUnknown; -} -#else -static bool IsFBSProcess(nub_process_t pid) { - // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor - return true; -} -#endif - -static void SetFBSError(NSInteger error_code, DNBError &error) { - error.SetError((DNBError::ValueType)error_code, DNBError::FrontBoard); - NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString( - (FBSOpenApplicationErrorCode)error_code); - const char *err_str = NULL; - if (err_nsstr == NULL) - err_str = "unknown FBS error"; - else { - err_str = [err_nsstr UTF8String]; - if (err_str == NULL) - err_str = "unknown FBS error"; - } - error.SetErrorString(err_str); -} - -static bool FBSAddEventDataToOptions(NSMutableDictionary *options, - const char *event_data, - DNBError &option_error) { - std::vector<std::string> values; - SplitEventData(event_data, values); - bool found_one = false; - for (std::string value : values) - { - if (value.compare("BackgroundContentFetching") == 0) { - DNBLog("Setting ActivateForEvent key in options dictionary."); - NSDictionary *event_details = [NSDictionary dictionary]; - NSDictionary *event_dictionary = [NSDictionary - dictionaryWithObject:event_details - forKey: - FBSActivateForEventOptionTypeBackgroundContentFetching]; - [options setObject:event_dictionary - forKey:FBSOpenApplicationOptionKeyActivateForEvent]; - found_one = true; - } else if (value.compare("ActivateSuspended") == 0) { - DNBLog("Setting ActivateSuspended key in options dictionary."); - [options setObject:@YES forKey: FBSOpenApplicationOptionKeyActivateSuspended]; - found_one = true; - } else { - DNBLogError("Unrecognized event type: %s. Ignoring.", value.c_str()); - option_error.SetErrorString("Unrecognized event data."); - } - } - return found_one; -} - -static NSMutableDictionary * -FBSCreateOptionsDictionary(const char *app_bundle_path, - NSMutableArray *launch_argv, - NSDictionary *launch_envp, NSString *stdio_path, - bool disable_aslr, const char *event_data) { - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - - if (launch_argv != nil) - [debug_options setObject:launch_argv forKey:FBSDebugOptionKeyArguments]; - if (launch_envp != nil) - [debug_options setObject:launch_envp forKey:FBSDebugOptionKeyEnvironment]; - - [debug_options setObject:stdio_path forKey:FBSDebugOptionKeyStandardOutPath]; - [debug_options setObject:stdio_path - forKey:FBSDebugOptionKeyStandardErrorPath]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:FBSDebugOptionKeyWaitForDebugger]; - if (disable_aslr) - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:FBSDebugOptionKeyDisableASLR]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject:debug_options - forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; - // And there are some other options at the top level in this dictionary: - [options setObject:[NSNumber numberWithBool:YES] - forKey:FBSOpenApplicationOptionKeyUnlockDevice]; - - // We have to get the "sequence ID & UUID" for this app bundle path and send - // them to FBS: - - NSURL *app_bundle_url = - [NSURL fileURLWithPath:[NSString stringWithUTF8String:app_bundle_path] - isDirectory:YES]; - LSApplicationProxy *app_proxy = - [LSApplicationProxy applicationProxyForBundleURL:app_bundle_url]; - if (app_proxy) { - DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.", - app_proxy.sequenceNumber, - [app_proxy.cacheGUID.UUIDString UTF8String]); - [options - setObject:[NSNumber numberWithUnsignedInteger:app_proxy.sequenceNumber] - forKey:FBSOpenApplicationOptionKeyLSSequenceNumber]; - [options setObject:app_proxy.cacheGUID.UUIDString - forKey:FBSOpenApplicationOptionKeyLSCacheGUID]; - } - - DNBError error; - FBSAddEventDataToOptions(options, event_data, error); - - return options; -} -static CallOpenApplicationFunction FBSCallOpenApplicationFunction = - CallBoardSystemServiceOpenApplication< - FBSSystemService, FBSOpenApplicationErrorCode, - FBSOpenApplicationErrorCodeNone, SetFBSError>; -#endif // WITH_FBS - -#if 0 -#define DEBUG_LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define DEBUG_LOG(fmt, ...) -#endif - -#ifndef MACH_PROCESS_USE_POSIX_SPAWN -#define MACH_PROCESS_USE_POSIX_SPAWN 1 -#endif - -#ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 -#endif - -MachProcess::MachProcess() - : m_pid(0), m_cpu_type(0), m_child_stdin(-1), m_child_stdout(-1), - m_child_stderr(-1), m_path(), m_args(), m_task(this), - m_flags(eMachProcessFlagsNone), m_stdio_thread(0), - m_stdio_mutex(PTHREAD_MUTEX_RECURSIVE), m_stdout_data(), - m_profile_enabled(false), m_profile_interval_usec(0), m_profile_thread(0), - m_profile_data_mutex(PTHREAD_MUTEX_RECURSIVE), m_profile_data(), - m_thread_actions(), m_exception_messages(), - m_exception_messages_mutex(PTHREAD_MUTEX_RECURSIVE), m_thread_list(), - m_activities(), m_state(eStateUnloaded), - m_state_mutex(PTHREAD_MUTEX_RECURSIVE), m_events(0, kAllEventsMask), - m_private_events(0, kAllEventsMask), m_breakpoints(), m_watchpoints(), - m_name_to_addr_callback(NULL), m_name_to_addr_baton(NULL), - m_image_infos_callback(NULL), m_image_infos_baton(NULL), - m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_did_exec(false), - m_dyld_process_info_create(nullptr), - m_dyld_process_info_for_each_image(nullptr), - m_dyld_process_info_release(nullptr), - m_dyld_process_info_get_cache(nullptr) { - m_dyld_process_info_create = - (void *(*)(task_t task, uint64_t timestamp, kern_return_t * kernelError)) - dlsym(RTLD_DEFAULT, "_dyld_process_info_create"); - m_dyld_process_info_for_each_image = - (void (*)(void *info, void (^)(uint64_t machHeaderAddress, - const uuid_t uuid, const char *path))) - dlsym(RTLD_DEFAULT, "_dyld_process_info_for_each_image"); - m_dyld_process_info_release = - (void (*)(void *info))dlsym(RTLD_DEFAULT, "_dyld_process_info_release"); - m_dyld_process_info_get_cache = (void (*)(void *info, void *cacheInfo))dlsym( - RTLD_DEFAULT, "_dyld_process_info_get_cache"); - - DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); -} - -MachProcess::~MachProcess() { - DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); - Clear(); -} - -pid_t MachProcess::SetProcessID(pid_t pid) { - // Free any previous process specific data or resources - Clear(); - // Set the current PID appropriately - if (pid == 0) - m_pid = ::getpid(); - else - m_pid = pid; - return m_pid; // Return actually PID in case a zero pid was passed in -} - -nub_state_t MachProcess::GetState() { - // If any other threads access this we will need a mutex for it - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - return m_state; -} - -const char *MachProcess::ThreadGetName(nub_thread_t tid) { - return m_thread_list.GetName(tid); -} - -nub_state_t MachProcess::ThreadGetState(nub_thread_t tid) { - return m_thread_list.GetState(tid); -} - -nub_size_t MachProcess::GetNumThreads() const { - return m_thread_list.NumThreads(); -} - -nub_thread_t MachProcess::GetThreadAtIndex(nub_size_t thread_idx) const { - return m_thread_list.ThreadIDAtIndex(thread_idx); -} - -nub_thread_t -MachProcess::GetThreadIDForMachPortNumber(thread_t mach_port_number) const { - return m_thread_list.GetThreadIDByMachPortNumber(mach_port_number); -} - -nub_bool_t MachProcess::SyncThreadState(nub_thread_t tid) { - MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid)); - if (!thread_sp) - return false; - kern_return_t kret = ::thread_abort_safely(thread_sp->MachPortNumber()); - DNBLogThreadedIf(LOG_THREAD, "thread = 0x%8.8" PRIx32 - " calling thread_abort_safely (tid) => %u " - "(GetGPRState() for stop_count = %u)", - thread_sp->MachPortNumber(), kret, - thread_sp->Process()->StopCount()); - - if (kret == KERN_SUCCESS) - return true; - else - return false; -} - -ThreadInfo::QoS MachProcess::GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, - uint64_t dti_qos_class_index) { - return m_thread_list.GetRequestedQoS(tid, tsd, dti_qos_class_index); -} - -nub_addr_t MachProcess::GetPThreadT(nub_thread_t tid) { - return m_thread_list.GetPThreadT(tid); -} - -nub_addr_t MachProcess::GetDispatchQueueT(nub_thread_t tid) { - return m_thread_list.GetDispatchQueueT(tid); -} - -nub_addr_t MachProcess::GetTSDAddressForThread( - nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) { - return m_thread_list.GetTSDAddressForThread( - tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, - plo_pthread_tsd_entry_size); -} - - -const char *MachProcess::GetDeploymentInfo(const struct load_command& lc, - uint64_t load_command_address, - uint32_t& major_version, - uint32_t& minor_version, - uint32_t& patch_version) { - uint32_t cmd = lc.cmd & ~LC_REQ_DYLD; - bool lc_cmd_known = - cmd == LC_VERSION_MIN_IPHONEOS || cmd == LC_VERSION_MIN_MACOSX || - cmd == LC_VERSION_MIN_TVOS || cmd == LC_VERSION_MIN_WATCHOS; - - if (lc_cmd_known) { - struct version_min_command vers_cmd; - if (ReadMemory(load_command_address, sizeof(struct version_min_command), - &vers_cmd) != sizeof(struct version_min_command)) { - return nullptr; - } - major_version = vers_cmd.sdk >> 16; - minor_version = (vers_cmd.sdk >> 8) & 0xffu; - patch_version = vers_cmd.sdk & 0xffu; - - switch (cmd) { - case LC_VERSION_MIN_IPHONEOS: - return "ios"; - case LC_VERSION_MIN_MACOSX: - return "macosx"; - case LC_VERSION_MIN_TVOS: - return "tvos"; - case LC_VERSION_MIN_WATCHOS: - return "watchos"; - default: - return nullptr; - } - } -#if defined (LC_BUILD_VERSION) -#ifndef PLATFORM_IOSSIMULATOR -#define PLATFORM_IOSSIMULATOR 7 -#define PLATFORM_TVOSSIMULATOR 8 -#define PLATFORM_WATCHOSSIMULATOR 9 -#endif - if (cmd == LC_BUILD_VERSION) { - struct build_version_command build_vers; - if (ReadMemory(load_command_address, sizeof(struct build_version_command), - &build_vers) != sizeof(struct build_version_command)) { - return nullptr; - } - major_version = build_vers.sdk >> 16;; - minor_version = (build_vers.sdk >> 8) & 0xffu; - patch_version = build_vers.sdk & 0xffu; - - switch (build_vers.platform) { - case PLATFORM_MACOS: - return "macosx"; - case PLATFORM_IOS: - case PLATFORM_IOSSIMULATOR: - return "ios"; - case PLATFORM_TVOS: - case PLATFORM_TVOSSIMULATOR: - return "tvos"; - case PLATFORM_WATCHOS: - case PLATFORM_WATCHOSSIMULATOR: - return "watchos"; - case PLATFORM_BRIDGEOS: - return "bridgeos"; - } - } -#endif - return nullptr; -} - -// Given an address, read the mach-o header and load commands out of memory to -// fill in -// the mach_o_information "inf" object. -// -// Returns false if there was an error in reading this mach-o file header/load -// commands. - -bool MachProcess::GetMachOInformationFromMemory( - nub_addr_t mach_o_header_addr, int wordsize, - struct mach_o_information &inf) { - uint64_t load_cmds_p; - if (wordsize == 4) { - struct mach_header header; - if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header), &header) != - sizeof(struct mach_header)) { - return false; - } - load_cmds_p = mach_o_header_addr + sizeof(struct mach_header); - inf.mach_header.magic = header.magic; - inf.mach_header.cputype = header.cputype; - // high byte of cpusubtype is used for "capability bits", v. - // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h - inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; - inf.mach_header.filetype = header.filetype; - inf.mach_header.ncmds = header.ncmds; - inf.mach_header.sizeofcmds = header.sizeofcmds; - inf.mach_header.flags = header.flags; - } else { - struct mach_header_64 header; - if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header_64), - &header) != sizeof(struct mach_header_64)) { - return false; - } - load_cmds_p = mach_o_header_addr + sizeof(struct mach_header_64); - inf.mach_header.magic = header.magic; - inf.mach_header.cputype = header.cputype; - // high byte of cpusubtype is used for "capability bits", v. - // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h - inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; - inf.mach_header.filetype = header.filetype; - inf.mach_header.ncmds = header.ncmds; - inf.mach_header.sizeofcmds = header.sizeofcmds; - inf.mach_header.flags = header.flags; - } - for (uint32_t j = 0; j < inf.mach_header.ncmds; j++) { - struct load_command lc; - if (ReadMemory(load_cmds_p, sizeof(struct load_command), &lc) != - sizeof(struct load_command)) { - return false; - } - if (lc.cmd == LC_SEGMENT) { - struct segment_command seg; - if (ReadMemory(load_cmds_p, sizeof(struct segment_command), &seg) != - sizeof(struct segment_command)) { - return false; - } - struct mach_o_segment this_seg; - char name[17]; - ::memset(name, 0, sizeof(name)); - memcpy(name, seg.segname, sizeof(seg.segname)); - this_seg.name = name; - this_seg.vmaddr = seg.vmaddr; - this_seg.vmsize = seg.vmsize; - this_seg.fileoff = seg.fileoff; - this_seg.filesize = seg.filesize; - this_seg.maxprot = seg.maxprot; - this_seg.initprot = seg.initprot; - this_seg.nsects = seg.nsects; - this_seg.flags = seg.flags; - inf.segments.push_back(this_seg); - } - if (lc.cmd == LC_SEGMENT_64) { - struct segment_command_64 seg; - if (ReadMemory(load_cmds_p, sizeof(struct segment_command_64), &seg) != - sizeof(struct segment_command_64)) { - return false; - } - struct mach_o_segment this_seg; - char name[17]; - ::memset(name, 0, sizeof(name)); - memcpy(name, seg.segname, sizeof(seg.segname)); - this_seg.name = name; - this_seg.vmaddr = seg.vmaddr; - this_seg.vmsize = seg.vmsize; - this_seg.fileoff = seg.fileoff; - this_seg.filesize = seg.filesize; - this_seg.maxprot = seg.maxprot; - this_seg.initprot = seg.initprot; - this_seg.nsects = seg.nsects; - this_seg.flags = seg.flags; - inf.segments.push_back(this_seg); - } - if (lc.cmd == LC_UUID) { - struct uuid_command uuidcmd; - if (ReadMemory(load_cmds_p, sizeof(struct uuid_command), &uuidcmd) == - sizeof(struct uuid_command)) - uuid_copy(inf.uuid, uuidcmd.uuid); - } - - uint32_t major_version, minor_version, patch_version; - if (const char *platform = GetDeploymentInfo(lc, load_cmds_p, - major_version, minor_version, - patch_version)) { - inf.min_version_os_name = platform; - inf.min_version_os_version = ""; - inf.min_version_os_version += std::to_string(major_version); - inf.min_version_os_version += "."; - inf.min_version_os_version += std::to_string(minor_version); - if (patch_version != 0) { - inf.min_version_os_version += "."; - inf.min_version_os_version += std::to_string(patch_version); - } - } - - load_cmds_p += lc.cmdsize; - } - return true; -} - -// Given completely filled in array of binary_image_information structures, -// create a JSONGenerator object -// with all the details we want to send to lldb. -JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON( - const std::vector<struct binary_image_information> &image_infos) { - - JSONGenerator::ArraySP image_infos_array_sp(new JSONGenerator::Array()); - - const size_t image_count = image_infos.size(); - - for (size_t i = 0; i < image_count; i++) { - JSONGenerator::DictionarySP image_info_dict_sp( - new JSONGenerator::Dictionary()); - image_info_dict_sp->AddIntegerItem("load_address", - image_infos[i].load_address); - image_info_dict_sp->AddIntegerItem("mod_date", image_infos[i].mod_date); - image_info_dict_sp->AddStringItem("pathname", image_infos[i].filename); - - uuid_string_t uuidstr; - uuid_unparse_upper(image_infos[i].macho_info.uuid, uuidstr); - image_info_dict_sp->AddStringItem("uuid", uuidstr); - - if (!image_infos[i].macho_info.min_version_os_name.empty() && - !image_infos[i].macho_info.min_version_os_version.empty()) { - image_info_dict_sp->AddStringItem( - "min_version_os_name", image_infos[i].macho_info.min_version_os_name); - image_info_dict_sp->AddStringItem( - "min_version_os_sdk", - image_infos[i].macho_info.min_version_os_version); - } - - JSONGenerator::DictionarySP mach_header_dict_sp( - new JSONGenerator::Dictionary()); - mach_header_dict_sp->AddIntegerItem( - "magic", image_infos[i].macho_info.mach_header.magic); - mach_header_dict_sp->AddIntegerItem( - "cputype", (uint32_t)image_infos[i].macho_info.mach_header.cputype); - mach_header_dict_sp->AddIntegerItem( - "cpusubtype", - (uint32_t)image_infos[i].macho_info.mach_header.cpusubtype); - mach_header_dict_sp->AddIntegerItem( - "filetype", image_infos[i].macho_info.mach_header.filetype); - mach_header_dict_sp->AddIntegerItem ("flags", - image_infos[i].macho_info.mach_header.flags); - - // DynamicLoaderMacOSX doesn't currently need these fields, so - // don't send them. - // mach_header_dict_sp->AddIntegerItem ("ncmds", - // image_infos[i].macho_info.mach_header.ncmds); - // mach_header_dict_sp->AddIntegerItem ("sizeofcmds", - // image_infos[i].macho_info.mach_header.sizeofcmds); - image_info_dict_sp->AddItem("mach_header", mach_header_dict_sp); - - JSONGenerator::ArraySP segments_sp(new JSONGenerator::Array()); - for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++) { - JSONGenerator::DictionarySP segment_sp(new JSONGenerator::Dictionary()); - segment_sp->AddStringItem("name", - image_infos[i].macho_info.segments[j].name); - segment_sp->AddIntegerItem("vmaddr", - image_infos[i].macho_info.segments[j].vmaddr); - segment_sp->AddIntegerItem("vmsize", - image_infos[i].macho_info.segments[j].vmsize); - segment_sp->AddIntegerItem("fileoff", - image_infos[i].macho_info.segments[j].fileoff); - segment_sp->AddIntegerItem( - "filesize", image_infos[i].macho_info.segments[j].filesize); - segment_sp->AddIntegerItem("maxprot", - image_infos[i].macho_info.segments[j].maxprot); - - // DynamicLoaderMacOSX doesn't currently need these fields, - // so don't send them. - // segment_sp->AddIntegerItem ("initprot", - // image_infos[i].macho_info.segments[j].initprot); - // segment_sp->AddIntegerItem ("nsects", - // image_infos[i].macho_info.segments[j].nsects); - // segment_sp->AddIntegerItem ("flags", - // image_infos[i].macho_info.segments[j].flags); - segments_sp->AddItem(segment_sp); - } - image_info_dict_sp->AddItem("segments", segments_sp); - - image_infos_array_sp->AddItem(image_info_dict_sp); - } - - JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary()); - ; - reply_sp->AddItem("images", image_infos_array_sp); - - return reply_sp; -} - -// Get the shared library information using the old (pre-macOS 10.12, pre-iOS -// 10, pre-tvOS 10, pre-watchOS 3) -// code path. We'll be given the address of an array of structures in the form -// {void* load_addr, void* mod_date, void* pathname} -// -// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this -// information. -JSONGenerator::ObjectSP MachProcess::GetLoadedDynamicLibrariesInfos( - nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) { - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, - NULL, 0) == 0 && - bufsize > 0) { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> image_infos; - size_t image_infos_size = image_count * 3 * pointer_size; - - uint8_t *image_info_buf = (uint8_t *)malloc(image_infos_size); - if (image_info_buf == NULL) { - return reply_sp; - } - if (ReadMemory(image_list_address, image_infos_size, image_info_buf) != - image_infos_size) { - return reply_sp; - } - - //// First the image_infos array with (load addr, pathname, mod date) - ///tuples - - for (size_t i = 0; i < image_count; i++) { - struct binary_image_information info; - nub_addr_t pathname_address; - if (pointer_size == 4) { - uint32_t load_address_32; - uint32_t pathname_address_32; - uint32_t mod_date_32; - ::memcpy(&load_address_32, image_info_buf + (i * 3 * pointer_size), 4); - ::memcpy(&pathname_address_32, - image_info_buf + (i * 3 * pointer_size) + pointer_size, 4); - ::memcpy(&mod_date_32, image_info_buf + (i * 3 * pointer_size) + - pointer_size + pointer_size, - 4); - info.load_address = load_address_32; - info.mod_date = mod_date_32; - pathname_address = pathname_address_32; - } else { - uint64_t load_address_64; - uint64_t pathname_address_64; - uint64_t mod_date_64; - ::memcpy(&load_address_64, image_info_buf + (i * 3 * pointer_size), 8); - ::memcpy(&pathname_address_64, - image_info_buf + (i * 3 * pointer_size) + pointer_size, 8); - ::memcpy(&mod_date_64, image_info_buf + (i * 3 * pointer_size) + - pointer_size + pointer_size, - 8); - info.load_address = load_address_64; - info.mod_date = mod_date_64; - pathname_address = pathname_address_64; - } - char strbuf[17]; - info.filename = ""; - uint64_t pathname_ptr = pathname_address; - bool still_reading = true; - while (still_reading && - ReadMemory(pathname_ptr, sizeof(strbuf) - 1, strbuf) == - sizeof(strbuf) - 1) { - strbuf[sizeof(strbuf) - 1] = '\0'; - info.filename += strbuf; - pathname_ptr += sizeof(strbuf) - 1; - // Stop if we found nul byte indicating the end of the string - for (size_t i = 0; i < sizeof(strbuf) - 1; i++) { - if (strbuf[i] == '\0') { - still_reading = false; - break; - } - } - } - uuid_clear(info.macho_info.uuid); - image_infos.push_back(info); - } - if (image_infos.size() == 0) { - return reply_sp; - } - - free(image_info_buf); - - //// Second, read the mach header / load commands for all the dylibs - - for (size_t i = 0; i < image_count; i++) { - if (!GetMachOInformationFromMemory(image_infos[i].load_address, - pointer_size, - image_infos[i].macho_info)) { - return reply_sp; - } - } - - //// Third, format all of the above in the JSONGenerator object. - - return FormatDynamicLibrariesIntoJSON(image_infos); - } - - return reply_sp; -} - -// From dyld SPI header dyld_process_info.h -typedef void *dyld_process_info; -struct dyld_process_cache_info { - uuid_t cacheUUID; // UUID of cache used by process - uint64_t cacheBaseAddress; // load address of dyld shared cache - bool noCache; // process is running without a dyld cache - bool privateCache; // process is using a private copy of its dyld cache -}; - -// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer -// to get -// the load address, uuid, and filenames of all the libraries. -// This only fills in those three fields in the 'struct -// binary_image_information' - call -// GetMachOInformationFromMemory to fill in the mach-o header/load command -// details. -void MachProcess::GetAllLoadedBinariesViaDYLDSPI( - std::vector<struct binary_image_information> &image_infos) { - kern_return_t kern_ret; - if (m_dyld_process_info_create) { - dyld_process_info info = - m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret); - if (info) { - m_dyld_process_info_for_each_image( - info, - ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) { - struct binary_image_information image; - image.filename = path; - uuid_copy(image.macho_info.uuid, uuid); - image.load_address = mach_header_addr; - image_infos.push_back(image); - }); - m_dyld_process_info_release(info); - } - } -} - -// Fetch information about all shared libraries using the dyld SPIs that exist -// in -// macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer. -JSONGenerator::ObjectSP -MachProcess::GetAllLoadedLibrariesInfos(nub_process_t pid) { - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, - NULL, 0) == 0 && - bufsize > 0) { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> image_infos; - GetAllLoadedBinariesViaDYLDSPI(image_infos); - const size_t image_count = image_infos.size(); - for (size_t i = 0; i < image_count; i++) { - GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size, - image_infos[i].macho_info); - } - return FormatDynamicLibrariesIntoJSON(image_infos); - } - return reply_sp; -} - -// Fetch information about the shared libraries at the given load addresses -// using the -// dyld SPIs that exist in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer. -JSONGenerator::ObjectSP MachProcess::GetLibrariesInfoForAddresses( - nub_process_t pid, std::vector<uint64_t> &macho_addresses) { - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, - NULL, 0) == 0 && - bufsize > 0) { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> all_image_infos; - GetAllLoadedBinariesViaDYLDSPI(all_image_infos); - - std::vector<struct binary_image_information> image_infos; - const size_t macho_addresses_count = macho_addresses.size(); - const size_t all_image_infos_count = all_image_infos.size(); - for (size_t i = 0; i < macho_addresses_count; i++) { - for (size_t j = 0; j < all_image_infos_count; j++) { - if (all_image_infos[j].load_address == macho_addresses[i]) { - image_infos.push_back(all_image_infos[j]); - } - } - } - - const size_t image_infos_count = image_infos.size(); - for (size_t i = 0; i < image_infos_count; i++) { - GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size, - image_infos[i].macho_info); - } - return FormatDynamicLibrariesIntoJSON(image_infos); - } - return reply_sp; -} - -// From dyld's internal podyld_process_info.h: - -JSONGenerator::ObjectSP MachProcess::GetSharedCacheInfo(nub_process_t pid) { - JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary()); - ; - kern_return_t kern_ret; - if (m_dyld_process_info_create && m_dyld_process_info_get_cache) { - dyld_process_info info = - m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret); - if (info) { - struct dyld_process_cache_info shared_cache_info; - m_dyld_process_info_get_cache(info, &shared_cache_info); - - reply_sp->AddIntegerItem("shared_cache_base_address", - shared_cache_info.cacheBaseAddress); - - uuid_string_t uuidstr; - uuid_unparse_upper(shared_cache_info.cacheUUID, uuidstr); - reply_sp->AddStringItem("shared_cache_uuid", uuidstr); - - reply_sp->AddBooleanItem("no_shared_cache", shared_cache_info.noCache); - reply_sp->AddBooleanItem("shared_cache_private_cache", - shared_cache_info.privateCache); - - m_dyld_process_info_release(info); - } - } - return reply_sp; -} - -nub_thread_t MachProcess::GetCurrentThread() { - return m_thread_list.CurrentThreadID(); -} - -nub_thread_t MachProcess::GetCurrentThreadMachPort() { - return m_thread_list.GetMachPortNumberByThreadID( - m_thread_list.CurrentThreadID()); -} - -nub_thread_t MachProcess::SetCurrentThread(nub_thread_t tid) { - return m_thread_list.SetCurrentThread(tid); -} - -bool MachProcess::GetThreadStoppedReason(nub_thread_t tid, - struct DNBThreadStopInfo *stop_info) { - if (m_thread_list.GetThreadStoppedReason(tid, stop_info)) { - if (m_did_exec) - stop_info->reason = eStopTypeExec; - return true; - } - return false; -} - -void MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const { - return m_thread_list.DumpThreadStoppedReason(tid); -} - -const char *MachProcess::GetThreadInfo(nub_thread_t tid) const { - return m_thread_list.GetThreadInfo(tid); -} - -uint32_t MachProcess::GetCPUType() { - if (m_cpu_type == 0 && m_pid != 0) - m_cpu_type = MachProcess::GetCPUTypeForLocalProcess(m_pid); - return m_cpu_type; -} - -const DNBRegisterSetInfo * -MachProcess::GetRegisterSetInfo(nub_thread_t tid, - nub_size_t *num_reg_sets) const { - MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid)); - if (thread_sp) { - DNBArchProtocol *arch = thread_sp->GetArchProtocol(); - if (arch) - return arch->GetRegisterSetInfo(num_reg_sets); - } - *num_reg_sets = 0; - return NULL; -} - -bool MachProcess::GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - DNBRegisterValue *value) const { - return m_thread_list.GetRegisterValue(tid, set, reg, value); -} - -bool MachProcess::SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - const DNBRegisterValue *value) const { - return m_thread_list.SetRegisterValue(tid, set, reg, value); -} - -void MachProcess::SetState(nub_state_t new_state) { - // If any other threads access this we will need a mutex for it - uint32_t event_mask = 0; - - // Scope for mutex locker - { - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - const nub_state_t old_state = m_state; - - if (old_state == eStateExited) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring new " - "state since current state is exited", - DNBStateAsString(new_state)); - } else if (old_state == new_state) { - DNBLogThreadedIf( - LOG_PROCESS, - "MachProcess::SetState(%s) ignoring redundant state change...", - DNBStateAsString(new_state)); - } else { - if (NUB_STATE_IS_STOPPED(new_state)) - event_mask = eEventProcessStoppedStateChanged; - else - event_mask = eEventProcessRunningStateChanged; - - DNBLogThreadedIf( - LOG_PROCESS, "MachProcess::SetState(%s) upating state (previous " - "state was %s), event_mask = 0x%8.8x", - DNBStateAsString(new_state), DNBStateAsString(old_state), event_mask); - - m_state = new_state; - if (new_state == eStateStopped) - m_stop_count++; - } - } - - if (event_mask != 0) { - m_events.SetEvents(event_mask); - m_private_events.SetEvents(event_mask); - if (event_mask == eEventProcessStoppedStateChanged) - m_private_events.ResetEvents(eEventProcessRunningStateChanged); - else - m_private_events.ResetEvents(eEventProcessStoppedStateChanged); - - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(event_mask); - } -} - -void MachProcess::Clear(bool detaching) { - // Clear any cached thread list while the pid and task are still valid - - m_task.Clear(); - // Now clear out all member variables - m_pid = INVALID_NUB_PROCESS; - if (!detaching) - CloseChildFileDescriptors(); - - m_path.clear(); - m_args.clear(); - SetState(eStateUnloaded); - m_flags = eMachProcessFlagsNone; - m_stop_count = 0; - m_thread_list.Clear(); - { - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - m_exception_messages.clear(); - } - m_activities.Clear(); - if (m_profile_thread) { - pthread_join(m_profile_thread, NULL); - m_profile_thread = NULL; - } -} - -bool MachProcess::StartSTDIOThread() { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); - // Create the thread that watches for the child STDIO - return ::pthread_create(&m_stdio_thread, NULL, MachProcess::STDIOThread, - this) == 0; -} - -void MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec, - DNBProfileDataScanType scan_type) { - m_profile_enabled = enable; - m_profile_interval_usec = static_cast<useconds_t>(interval_usec); - m_profile_scan_type = scan_type; - - if (m_profile_enabled && (m_profile_thread == NULL)) { - StartProfileThread(); - } else if (!m_profile_enabled && m_profile_thread) { - pthread_join(m_profile_thread, NULL); - m_profile_thread = NULL; - } -} - -bool MachProcess::StartProfileThread() { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); - // Create the thread that profiles the inferior and reports back if enabled - return ::pthread_create(&m_profile_thread, NULL, MachProcess::ProfileThread, - this) == 0; -} - -nub_addr_t MachProcess::LookupSymbol(const char *name, const char *shlib) { - if (m_name_to_addr_callback != NULL && name && name[0]) - return m_name_to_addr_callback(ProcessID(), name, shlib, - m_name_to_addr_baton); - return INVALID_NUB_ADDRESS; -} - -bool MachProcess::Resume(const DNBThreadResumeActions &thread_actions) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Resume ()"); - nub_state_t state = GetState(); - - if (CanResume(state)) { - m_thread_actions = thread_actions; - PrivateResume(); - return true; - } else if (state == eStateRunning) { - DNBLog("Resume() - task 0x%x is already running, ignoring...", - m_task.TaskPort()); - return true; - } - DNBLog("Resume() - task 0x%x has state %s, can't continue...", - m_task.TaskPort(), DNBStateAsString(state)); - return false; -} - -bool MachProcess::Kill(const struct timespec *timeout_abstime) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill ()"); - nub_state_t state = DoSIGSTOP(true, false, NULL); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() state = %s", - DNBStateAsString(state)); - errno = 0; - DNBLog("Sending ptrace PT_KILL to terminate inferior process."); - ::ptrace(PT_KILL, m_pid, 0, 0); - DNBError err; - err.SetErrorToErrno(); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace " - "(PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", - m_pid, err.Status(), err.AsString()); - m_thread_actions = DNBThreadResumeActions(eStateRunning, 0); - PrivateResume(); - - // Try and reap the process without touching our m_events since - // we want the code above this to still get the eStateExited event - const uint32_t reap_timeout_usec = - 1000000; // Wait 1 second and try to reap the process - const uint32_t reap_interval_usec = 10000; // - uint32_t reap_time_elapsed; - for (reap_time_elapsed = 0; reap_time_elapsed < reap_timeout_usec; - reap_time_elapsed += reap_interval_usec) { - if (GetState() == eStateExited) - break; - usleep(reap_interval_usec); - } - DNBLog("Waited %u ms for process to be reaped (state = %s)", - reap_time_elapsed / 1000, DNBStateAsString(GetState())); - return true; -} - -bool MachProcess::Interrupt() { - nub_state_t state = GetState(); - if (IsRunning(state)) { - if (m_sent_interrupt_signo == 0) { - m_sent_interrupt_signo = SIGSTOP; - if (Signal(m_sent_interrupt_signo)) { - DNBLogThreadedIf( - LOG_PROCESS, - "MachProcess::Interrupt() - sent %i signal to interrupt process", - m_sent_interrupt_signo); - return true; - } else { - m_sent_interrupt_signo = 0; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - failed to " - "send %i signal to interrupt process", - m_sent_interrupt_signo); - } - } else { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - previously " - "sent an interrupt signal %i that hasn't " - "been received yet, interrupt aborted", - m_sent_interrupt_signo); - } - } else { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - process already " - "stopped, no interrupt sent"); - } - return false; -} - -bool MachProcess::Signal(int signal, const struct timespec *timeout_abstime) { - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::Signal (signal = %d, timeout = %p)", signal, - reinterpret_cast<const void *>(timeout_abstime)); - nub_state_t state = GetState(); - if (::kill(ProcessID(), signal) == 0) { - // If we were running and we have a timeout, wait for the signal to stop - if (IsRunning(state) && timeout_abstime) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout " - "= %p) waiting for signal to stop " - "process...", - signal, reinterpret_cast<const void *>(timeout_abstime)); - m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged, - timeout_abstime); - state = GetState(); - DNBLogThreadedIf( - LOG_PROCESS, - "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal, - reinterpret_cast<const void *>(timeout_abstime), - DNBStateAsString(state)); - return !IsRunning(state); - } - DNBLogThreadedIf( - LOG_PROCESS, - "MachProcess::Signal (signal = %d, timeout = %p) not waiting...", - signal, reinterpret_cast<const void *>(timeout_abstime)); - return true; - } - DNBError err(errno, DNBError::POSIX); - err.LogThreadedIfError("kill (pid = %d, signo = %i)", ProcessID(), signal); - return false; -} - -bool MachProcess::SendEvent(const char *event, DNBError &send_err) { - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::SendEvent (event = %s) to pid: %d", event, - m_pid); - if (m_pid == INVALID_NUB_PROCESS) - return false; -// FIXME: Shouldn't we use the launch flavor we were started with? -#if defined(WITH_FBS) || defined(WITH_BKS) - return BoardServiceSendEvent(event, send_err); -#endif - return true; -} - -nub_state_t MachProcess::DoSIGSTOP(bool clear_bps_and_wps, bool allow_running, - uint32_t *thread_idx_ptr) { - nub_state_t state = GetState(); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s", - DNBStateAsString(state)); - - if (!IsRunning(state)) { - if (clear_bps_and_wps) { - DisableAllBreakpoints(true); - DisableAllWatchpoints(true); - clear_bps_and_wps = false; - } - - // If we already have a thread stopped due to a SIGSTOP, we don't have - // to do anything... - uint32_t thread_idx = - m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP); - if (thread_idx_ptr) - *thread_idx_ptr = thread_idx; - if (thread_idx != UINT32_MAX) - return GetState(); - - // No threads were stopped with a SIGSTOP, we need to run and halt the - // process with a signal - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::DoSIGSTOP() state = %s -- resuming process", - DNBStateAsString(state)); - if (allow_running) - m_thread_actions = DNBThreadResumeActions(eStateRunning, 0); - else - m_thread_actions = DNBThreadResumeActions(eStateSuspended, 0); - - PrivateResume(); - - // Reset the event that says we were indeed running - m_events.ResetEvents(eEventProcessRunningStateChanged); - state = GetState(); - } - - // We need to be stopped in order to be able to detach, so we need - // to send ourselves a SIGSTOP - - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::DoSIGSTOP() state = %s -- sending SIGSTOP", - DNBStateAsString(state)); - struct timespec sigstop_timeout; - DNBTimer::OffsetTimeOfDay(&sigstop_timeout, 2, 0); - Signal(SIGSTOP, &sigstop_timeout); - if (clear_bps_and_wps) { - DisableAllBreakpoints(true); - DisableAllWatchpoints(true); - // clear_bps_and_wps = false; - } - uint32_t thread_idx = - m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP); - if (thread_idx_ptr) - *thread_idx_ptr = thread_idx; - return GetState(); -} - -bool MachProcess::Detach() { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach()"); - - uint32_t thread_idx = UINT32_MAX; - nub_state_t state = DoSIGSTOP(true, true, &thread_idx); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", - DNBStateAsString(state)); - - { - m_thread_actions.Clear(); - m_activities.Clear(); - DNBThreadResumeAction thread_action; - thread_action.tid = m_thread_list.ThreadIDAtIndex(thread_idx); - thread_action.state = eStateRunning; - thread_action.signal = -1; - thread_action.addr = INVALID_NUB_ADDRESS; - - m_thread_actions.Append(thread_action); - m_thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); - - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - - ReplyToAllExceptions(); - } - - m_task.ShutDownExcecptionThread(); - - // Detach from our process - errno = 0; - nub_process_t pid = m_pid; - int ret = ::ptrace(PT_DETACH, pid, (caddr_t)1, 0); - DNBError err(errno, DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_PROCESS) || err.Fail() || (ret != 0)) - err.LogThreaded("::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid); - - // Resume our task - m_task.Resume(); - - // NULL our task out as we have already restored all exception ports - m_task.Clear(); - - // Clear out any notion of the process we once were - const bool detaching = true; - Clear(detaching); - - SetState(eStateDetached); - - return true; -} - -//---------------------------------------------------------------------- -// ReadMemory from the MachProcess level will always remove any software -// breakpoints from the memory buffer before returning. If you wish to -// read memory and see those traps, read from the MachTask -// (m_task.ReadMemory()) as that version will give you what is actually -// in inferior memory. -//---------------------------------------------------------------------- -nub_size_t MachProcess::ReadMemory(nub_addr_t addr, nub_size_t size, - void *buf) { - // We need to remove any current software traps (enabled software - // breakpoints) that we may have placed in our tasks memory. - - // First just read the memory as is - nub_size_t bytes_read = m_task.ReadMemory(addr, size, buf); - - // Then place any opcodes that fall into this range back into the buffer - // before we return this to callers. - if (bytes_read > 0) - m_breakpoints.RemoveTrapsFromBuffer(addr, bytes_read, buf); - return bytes_read; -} - -//---------------------------------------------------------------------- -// WriteMemory from the MachProcess level will always write memory around -// any software breakpoints. Any software breakpoints will have their -// opcodes modified if they are enabled. Any memory that doesn't overlap -// with software breakpoints will be written to. If you wish to write to -// inferior memory without this interference, then write to the MachTask -// (m_task.WriteMemory()) as that version will always modify inferior -// memory. -//---------------------------------------------------------------------- -nub_size_t MachProcess::WriteMemory(nub_addr_t addr, nub_size_t size, - const void *buf) { - // We need to write any data that would go where any current software traps - // (enabled software breakpoints) any software traps (breakpoints) that we - // may have placed in our tasks memory. - - std::vector<DNBBreakpoint *> bps; - - const size_t num_bps = - m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps); - if (num_bps == 0) - return m_task.WriteMemory(addr, size, buf); - - nub_size_t bytes_written = 0; - nub_addr_t intersect_addr; - nub_size_t intersect_size; - nub_size_t opcode_offset; - const uint8_t *ubuf = (const uint8_t *)buf; - - for (size_t i = 0; i < num_bps; ++i) { - DNBBreakpoint *bp = bps[i]; - - const bool intersects = bp->IntersectsRange( - addr, size, &intersect_addr, &intersect_size, &opcode_offset); - UNUSED_IF_ASSERT_DISABLED(intersects); - assert(intersects); - assert(addr <= intersect_addr && intersect_addr < addr + size); - assert(addr < intersect_addr + intersect_size && - intersect_addr + intersect_size <= addr + size); - assert(opcode_offset + intersect_size <= bp->ByteSize()); - - // Check for bytes before this breakpoint - const nub_addr_t curr_addr = addr + bytes_written; - if (intersect_addr > curr_addr) { - // There are some bytes before this breakpoint that we need to - // just write to memory - nub_size_t curr_size = intersect_addr - curr_addr; - nub_size_t curr_bytes_written = - m_task.WriteMemory(curr_addr, curr_size, ubuf + bytes_written); - bytes_written += curr_bytes_written; - if (curr_bytes_written != curr_size) { - // We weren't able to write all of the requested bytes, we - // are done looping and will return the number of bytes that - // we have written so far. - break; - } - } - - // Now write any bytes that would cover up any software breakpoints - // directly into the breakpoint opcode buffer - ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, - intersect_size); - bytes_written += intersect_size; - } - - // Write any remaining bytes after the last breakpoint if we have any left - if (bytes_written < size) - bytes_written += m_task.WriteMemory( - addr + bytes_written, size - bytes_written, ubuf + bytes_written); - - return bytes_written; -} - -void MachProcess::ReplyToAllExceptions() { - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - if (!m_exception_messages.empty()) { - MachException::Message::iterator pos; - MachException::Message::iterator begin = m_exception_messages.begin(); - MachException::Message::iterator end = m_exception_messages.end(); - for (pos = begin; pos != end; ++pos) { - DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %u...", - (uint32_t)std::distance(begin, pos)); - int thread_reply_signal = 0; - - nub_thread_t tid = - m_thread_list.GetThreadIDByMachPortNumber(pos->state.thread_port); - const DNBThreadResumeAction *action = NULL; - if (tid != INVALID_NUB_THREAD) { - action = m_thread_actions.GetActionForThread(tid, false); - } - - if (action) { - thread_reply_signal = action->signal; - if (thread_reply_signal) - m_thread_actions.SetSignalHandledForThread(tid); - } - - DNBError err(pos->Reply(this, thread_reply_signal)); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreadedIfError("Error replying to exception"); - } - - // Erase all exception message as we should have used and replied - // to them all already. - m_exception_messages.clear(); - } -} -void MachProcess::PrivateResume() { - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - - m_auto_resume_signo = m_sent_interrupt_signo; - if (m_auto_resume_signo) - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x " - "resuming (with unhandled interrupt signal " - "%i)...", - m_task.TaskPort(), m_auto_resume_signo); - else - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::PrivateResume() - task 0x%x resuming...", - m_task.TaskPort()); - - ReplyToAllExceptions(); - // bool stepOverBreakInstruction = step; - - // Let the thread prepare to resume and see if any threads want us to - // step over a breakpoint instruction (ProcessWillResume will modify - // the value of stepOverBreakInstruction). - m_thread_list.ProcessWillResume(this, m_thread_actions); - - // Set our state accordingly - if (m_thread_actions.NumActionsWithState(eStateStepping)) - SetState(eStateStepping); - else - SetState(eStateRunning); - - // Now resume our task. - m_task.Resume(); -} - -DNBBreakpoint *MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, - bool hardware) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = " - "0x%8.8llx, length = %llu, hardware = %i)", - (uint64_t)addr, (uint64_t)length, hardware); - - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) - bp->Retain(); - else - bp = m_breakpoints.Add(addr, length, hardware); - - if (EnableBreakpoint(addr)) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = " - "0x%8.8llx, length = %llu) => %p", - (uint64_t)addr, (uint64_t)length, - reinterpret_cast<void *>(bp)); - return bp; - } else if (bp->Release() == 0) { - m_breakpoints.Remove(addr); - } - // We failed to enable the breakpoint - return NULL; -} - -DNBBreakpoint *MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, - uint32_t watch_flags, - bool hardware) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " - "0x%8.8llx, length = %llu, flags = " - "0x%8.8x, hardware = %i)", - (uint64_t)addr, (uint64_t)length, watch_flags, hardware); - - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - // since the Z packets only send an address, we can only have one watchpoint - // at - // an address. If there is already one, we must refuse to create another - // watchpoint - if (wp) - return NULL; - - wp = m_watchpoints.Add(addr, length, hardware); - wp->SetIsWatchpoint(watch_flags); - - if (EnableWatchpoint(addr)) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " - "0x%8.8llx, length = %llu) => %p", - (uint64_t)addr, (uint64_t)length, - reinterpret_cast<void *>(wp)); - return wp; - } else { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " - "0x%8.8llx, length = %llu) => FAILED", - (uint64_t)addr, (uint64_t)length); - m_watchpoints.Remove(addr); - } - // We failed to enable the watchpoint - return NULL; -} - -void MachProcess::DisableAllBreakpoints(bool remove) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )", - __FUNCTION__, remove); - - m_breakpoints.DisableAllBreakpoints(this); - - if (remove) - m_breakpoints.RemoveDisabled(); -} - -void MachProcess::DisableAllWatchpoints(bool remove) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )", - __FUNCTION__, remove); - - m_watchpoints.DisableAllWatchpoints(this); - - if (remove) - m_watchpoints.RemoveDisabled(); -} - -bool MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) { - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) { - // After "exec" we might end up with a bunch of breakpoints that were - // disabled - // manually, just ignore them - if (!bp->IsEnabled()) { - // Breakpoint might have been disabled by an exec - if (remove && bp->Release() == 0) { - m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(addr); - } - return true; - } - - // We have multiple references to this breakpoint, decrement the ref count - // and if it isn't zero, then return true; - if (remove && bp->Release() > 0) - return true; - - DNBLogThreadedIf( - LOG_BREAKPOINTS | LOG_VERBOSE, - "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )", - (uint64_t)addr, remove); - - if (bp->IsHardware()) { - bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint(bp); - - if (hw_disable_result) { - bp->SetEnabled(false); - // Let the thread list know that a breakpoint has been modified - if (remove) { - m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(addr); - } - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( " - "addr = 0x%8.8llx, remove = %d ) " - "(hardware) => success", - (uint64_t)addr, remove); - return true; - } - - return false; - } - - const nub_size_t break_op_size = bp->ByteSize(); - assert(break_op_size > 0); - const uint8_t *const break_op = - DNBArchProtocol::GetBreakpointOpcode(bp->ByteSize()); - if (break_op_size > 0) { - // Clear a software breakpoint instruction - uint8_t curr_break_op[break_op_size]; - bool break_op_found = false; - - // Read the breakpoint opcode - if (m_task.ReadMemory(addr, break_op_size, curr_break_op) == - break_op_size) { - bool verify = false; - if (bp->IsEnabled()) { - // Make sure a breakpoint opcode exists at this address - if (memcmp(curr_break_op, break_op, break_op_size) == 0) { - break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore - // the saved opcode. - if (m_task.WriteMemory(addr, break_op_size, - bp->SavedOpcodeBytes()) == break_op_size) { - verify = true; - } else { - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " - "remove = %d ) memory write failed when restoring " - "original opcode", - (uint64_t)addr, remove); - } - } else { - DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " - "remove = %d ) expected a breakpoint opcode but " - "didn't find one.", - (uint64_t)addr, remove); - // Set verify to true and so we can check if the original opcode has - // already been restored - verify = true; - } - } else { - DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, - "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " - "remove = %d ) is not enabled", - (uint64_t)addr, remove); - // Set verify to true and so we can check if the original opcode is - // there - verify = true; - } - - if (verify) { - uint8_t verify_opcode[break_op_size]; - // Verify that our original opcode made it back to the inferior - if (m_task.ReadMemory(addr, break_op_size, verify_opcode) == - break_op_size) { - // compare the memory we just read with the original opcode - if (memcmp(bp->SavedOpcodeBytes(), verify_opcode, break_op_size) == - 0) { - // SUCCESS - bp->SetEnabled(false); - // Let the thread list know that a breakpoint has been modified - if (remove && bp->Release() == 0) { - m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(addr); - } - DNBLogThreadedIf(LOG_BREAKPOINTS, - "MachProcess::DisableBreakpoint ( addr = " - "0x%8.8llx, remove = %d ) => success", - (uint64_t)addr, remove); - return true; - } else { - if (break_op_found) - DNBLogError("MachProcess::DisableBreakpoint ( addr = " - "0x%8.8llx, remove = %d ) : failed to restore " - "original opcode", - (uint64_t)addr, remove); - else - DNBLogError("MachProcess::DisableBreakpoint ( addr = " - "0x%8.8llx, remove = %d ) : opcode changed", - (uint64_t)addr, remove); - } - } else { - DNBLogWarning("MachProcess::DisableBreakpoint: unable to disable " - "breakpoint 0x%8.8llx", - (uint64_t)addr); - } - } - } else { - DNBLogWarning("MachProcess::DisableBreakpoint: unable to read memory " - "at 0x%8.8llx", - (uint64_t)addr); - } - } - } else { - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = " - "%d ) invalid breakpoint address", - (uint64_t)addr, remove); - } - return false; -} - -bool MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) { - DNBLogThreadedIf(LOG_WATCHPOINTS, - "MachProcess::%s(addr = 0x%8.8llx, remove = %d)", - __FUNCTION__, (uint64_t)addr, remove); - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - if (wp) { - // If we have multiple references to a watchpoint, removing the watchpoint - // shouldn't clear it - if (remove && wp->Release() > 0) - return true; - - nub_addr_t addr = wp->Address(); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )", - (uint64_t)addr, remove); - - if (wp->IsHardware()) { - bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint(wp); - - if (hw_disable_result) { - wp->SetEnabled(false); - if (remove) - m_watchpoints.Remove(addr); - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( " - "addr = 0x%8.8llx, remove = %d ) " - "(hardware) => success", - (uint64_t)addr, remove); - return true; - } - } - - // TODO: clear software watchpoints if we implement them - } else { - DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = " - "%d ) invalid watchpoint ID", - (uint64_t)addr, remove); - } - return false; -} - -uint32_t MachProcess::GetNumSupportedHardwareWatchpoints() const { - return m_thread_list.NumSupportedHardwareWatchpoints(); -} - -bool MachProcess::EnableBreakpoint(nub_addr_t addr) { - DNBLogThreadedIf(LOG_BREAKPOINTS, - "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )", - (uint64_t)addr); - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) { - if (bp->IsEnabled()) { - DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " - "breakpoint already enabled.", - (uint64_t)addr); - return true; - } else { - if (bp->HardwarePreferred()) { - bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp)); - if (bp->IsHardware()) { - bp->SetEnabled(true); - return true; - } - } - - const nub_size_t break_op_size = bp->ByteSize(); - assert(break_op_size != 0); - const uint8_t *const break_op = - DNBArchProtocol::GetBreakpointOpcode(break_op_size); - if (break_op_size > 0) { - // Save the original opcode by reading it - if (m_task.ReadMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == - break_op_size) { - // Write a software breakpoint in place of the original opcode - if (m_task.WriteMemory(addr, break_op_size, break_op) == - break_op_size) { - uint8_t verify_break_op[4]; - if (m_task.ReadMemory(addr, break_op_size, verify_break_op) == - break_op_size) { - if (memcmp(break_op, verify_break_op, break_op_size) == 0) { - bp->SetEnabled(true); - // Let the thread list know that a breakpoint has been modified - m_thread_list.NotifyBreakpointChanged(bp); - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::" - "EnableBreakpoint ( addr = " - "0x%8.8llx ) : SUCCESS.", - (uint64_t)addr); - return true; - } else { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx " - "): breakpoint opcode verification failed.", - (uint64_t)addr); - } - } else { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " - "unable to read memory to verify breakpoint opcode.", - (uint64_t)addr); - } - } else { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " - "unable to write breakpoint opcode to memory.", - (uint64_t)addr); - } - } else { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " - "unable to read memory at breakpoint address.", - (uint64_t)addr); - } - } else { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no " - "software breakpoint opcode for current architecture.", - (uint64_t)addr); - } - } - } - return false; -} - -bool MachProcess::EnableWatchpoint(nub_addr_t addr) { - DNBLogThreadedIf(LOG_WATCHPOINTS, - "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)", - (uint64_t)addr); - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - if (wp) { - nub_addr_t addr = wp->Address(); - if (wp->IsEnabled()) { - DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): " - "watchpoint already enabled.", - (uint64_t)addr); - return true; - } else { - // Currently only try and set hardware watchpoints. - wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp)); - if (wp->IsHardware()) { - wp->SetEnabled(true); - return true; - } - // TODO: Add software watchpoints by doing page protection tricks. - } - } - return false; -} - -// Called by the exception thread when an exception has been received from -// our process. The exception message is completely filled and the exception -// data has already been copied. -void MachProcess::ExceptionMessageReceived( - const MachException::Message &exceptionMessage) { - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - - if (m_exception_messages.empty()) - m_task.Suspend(); - - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachProcess::ExceptionMessageReceived ( )"); - - // Use a locker to automatically unlock our mutex in case of exceptions - // Add the exception to our internal exception stack - m_exception_messages.push_back(exceptionMessage); -} - -task_t MachProcess::ExceptionMessageBundleComplete() { - // We have a complete bundle of exceptions for our child process. - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", - __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); - bool auto_resume = false; - if (!m_exception_messages.empty()) { - m_did_exec = false; - // First check for any SIGTRAP and make sure we didn't exec - const task_t task = m_task.TaskPort(); - size_t i; - if (m_pid != 0) { - bool received_interrupt = false; - uint32_t num_task_exceptions = 0; - for (i = 0; i < m_exception_messages.size(); ++i) { - if (m_exception_messages[i].state.task_port == task) { - ++num_task_exceptions; - const int signo = m_exception_messages[i].state.SoftSignal(); - if (signo == SIGTRAP) { - // SIGTRAP could mean that we exec'ed. We need to check the - // dyld all_image_infos.infoArray to see if it is NULL and if - // so, say that we exec'ed. - const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress(); - if (aii_addr != INVALID_NUB_ADDRESS) { - const nub_addr_t info_array_count_addr = aii_addr + 4; - uint32_t info_array_count = 0; - if (m_task.ReadMemory(info_array_count_addr, 4, - &info_array_count) == 4) { - if (info_array_count == 0) { - m_did_exec = true; - // Force the task port to update itself in case the task port - // changed after exec - DNBError err; - const task_t old_task = m_task.TaskPort(); - const task_t new_task = - m_task.TaskPortForProcessID(err, true); - if (old_task != new_task) - DNBLogThreadedIf( - LOG_PROCESS, - "exec: task changed from 0x%4.4x to 0x%4.4x", old_task, - new_task); - } - } else { - DNBLog("error: failed to read all_image_infos.infoArrayCount " - "from 0x%8.8llx", - (uint64_t)info_array_count_addr); - } - } - break; - } else if (m_sent_interrupt_signo != 0 && - signo == m_sent_interrupt_signo) { - received_interrupt = true; - } - } - } - - if (m_did_exec) { - cpu_type_t process_cpu_type = - MachProcess::GetCPUTypeForLocalProcess(m_pid); - if (m_cpu_type != process_cpu_type) { - DNBLog("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, - process_cpu_type); - m_cpu_type = process_cpu_type; - DNBArchProtocol::SetArchitecture(process_cpu_type); - } - m_thread_list.Clear(); - m_activities.Clear(); - m_breakpoints.DisableAll(); - } - - if (m_sent_interrupt_signo != 0) { - if (received_interrupt) { - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::ExceptionMessageBundleComplete(): " - "process successfully interrupted with signal %i", - m_sent_interrupt_signo); - - // Mark that we received the interrupt signal - m_sent_interrupt_signo = 0; - // Not check if we had a case where: - // 1 - We called MachProcess::Interrupt() but we stopped for another - // reason - // 2 - We called MachProcess::Resume() (but still haven't gotten the - // interrupt signal) - // 3 - We are now incorrectly stopped because we are handling the - // interrupt signal we missed - // 4 - We might need to resume if we stopped only with the interrupt - // signal that we never handled - if (m_auto_resume_signo != 0) { - // Only auto_resume if we stopped with _only_ the interrupt signal - if (num_task_exceptions == 1) { - auto_resume = true; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::" - "ExceptionMessageBundleComplete(): " - "auto resuming due to unhandled " - "interrupt signal %i", - m_auto_resume_signo); - } - m_auto_resume_signo = 0; - } - } else { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::" - "ExceptionMessageBundleComplete(): " - "didn't get signal %i after " - "MachProcess::Interrupt()", - m_sent_interrupt_signo); - } - } - } - - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - m_thread_list.ProcessDidStop(this); - m_activities.Clear(); - - // Let each thread know of any exceptions - for (i = 0; i < m_exception_messages.size(); ++i) { - // Let the thread list figure use the MachProcess to forward all - // exceptions - // on down to each thread. - if (m_exception_messages[i].state.task_port == task) - m_thread_list.NotifyException(m_exception_messages[i].state); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - m_exception_messages[i].Dump(); - } - - if (DNBLogCheckLogBit(LOG_THREAD)) - m_thread_list.Dump(); - - bool step_more = false; - if (m_thread_list.ShouldStop(step_more) && !auto_resume) { - // Wait for the eEventProcessRunningStateChanged event to be reset - // before changing state to stopped to avoid race condition with - // very fast start/stops - struct timespec timeout; - // DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 - // ms - DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms - m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, &timeout); - SetState(eStateStopped); - } else { - // Resume without checking our current state. - PrivateResume(); - } - } else { - DNBLogThreadedIf( - LOG_EXCEPTIONS, "%s empty exception messages bundle (%llu exceptions).", - __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); - } - return m_task.TaskPort(); -} - -nub_size_t -MachProcess::CopyImageInfos(struct DNBExecutableImageInfo **image_infos, - bool only_changed) { - if (m_image_infos_callback != NULL) - return m_image_infos_callback(ProcessID(), image_infos, only_changed, - m_image_infos_baton); - return 0; -} - -void MachProcess::SharedLibrariesUpdated() { - uint32_t event_bits = eEventSharedLibsStateChange; - // Set the shared library event bit to let clients know of shared library - // changes - m_events.SetEvents(event_bits); - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(event_bits); -} - -void MachProcess::SetExitInfo(const char *info) { - if (info && info[0]) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(\"%s\")", __FUNCTION__, - info); - m_exit_info.assign(info); - } else { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(NULL)", __FUNCTION__); - m_exit_info.clear(); - } -} - -void MachProcess::AppendSTDOUT(char *s, size_t len) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (<%llu> %s) ...", __FUNCTION__, - (uint64_t)len, s); - PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex); - m_stdout_data.append(s, len); - m_events.SetEvents(eEventStdioAvailable); - - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(eEventStdioAvailable); -} - -size_t MachProcess::GetAvailableSTDOUT(char *buf, size_t buf_size) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, - reinterpret_cast<void *>(buf), (uint64_t)buf_size); - PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex); - size_t bytes_available = m_stdout_data.size(); - if (bytes_available > 0) { - if (bytes_available > buf_size) { - memcpy(buf, m_stdout_data.data(), buf_size); - m_stdout_data.erase(0, buf_size); - bytes_available = buf_size; - } else { - memcpy(buf, m_stdout_data.data(), bytes_available); - m_stdout_data.clear(); - } - } - return bytes_available; -} - -nub_addr_t MachProcess::GetDYLDAllImageInfosAddress() { - DNBError err; - return m_task.GetDYLDAllImageInfosAddress(err); -} - -size_t MachProcess::GetAvailableSTDERR(char *buf, size_t buf_size) { return 0; } - -void *MachProcess::STDIOThread(void *arg) { - MachProcess *proc = (MachProcess *)arg; - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::%s ( arg = %p ) thread starting...", - __FUNCTION__, arg); - -#if defined(__APPLE__) - pthread_setname_np("stdio monitoring thread"); -#endif - - // We start use a base and more options so we can control if we - // are currently using a timeout on the mach_msg. We do this to get a - // bunch of related exceptions on our exception port so we can process - // then together. When we have multiple threads, we can get an exception - // per thread and they will come in consecutively. The main thread loop - // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT - // flag set in the options, so we will wait forever for an exception on - // our exception port. After we get one exception, we then will use the - // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current - // exceptions for our process. After we have received the last pending - // exception, we will get a timeout which enables us to then notify - // our main thread that we have an exception bundle available. We then wait - // for the main thread to tell this exception thread to start trying to get - // exceptions messages again and we start again with a mach_msg read with - // infinite timeout. - DNBError err; - int stdout_fd = proc->GetStdoutFileDescriptor(); - int stderr_fd = proc->GetStderrFileDescriptor(); - if (stdout_fd == stderr_fd) - stderr_fd = -1; - - while (stdout_fd >= 0 || stderr_fd >= 0) { - ::pthread_testcancel(); - - fd_set read_fds; - FD_ZERO(&read_fds); - if (stdout_fd >= 0) - FD_SET(stdout_fd, &read_fds); - if (stderr_fd >= 0) - FD_SET(stderr_fd, &read_fds); - int nfds = std::max<int>(stdout_fd, stderr_fd) + 1; - - int num_set_fds = select(nfds, &read_fds, NULL, NULL, NULL); - DNBLogThreadedIf(LOG_PROCESS, - "select (nfds, &read_fds, NULL, NULL, NULL) => %d", - num_set_fds); - - if (num_set_fds < 0) { - int select_errno = errno; - if (DNBLogCheckLogBit(LOG_PROCESS)) { - err.SetError(select_errno, DNBError::POSIX); - err.LogThreadedIfError( - "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds); - } - - switch (select_errno) { - case EAGAIN: // The kernel was (perhaps temporarily) unable to allocate - // the requested number of file descriptors, or we have - // non-blocking IO - break; - case EBADF: // One of the descriptor sets specified an invalid descriptor. - return NULL; - break; - case EINTR: // A signal was delivered before the time limit expired and - // before any of the selected events occurred. - case EINVAL: // The specified time limit is invalid. One of its components - // is negative or too large. - default: // Other unknown error - break; - } - } else if (num_set_fds == 0) { - } else { - char s[1024]; - s[sizeof(s) - 1] = '\0'; // Ensure we have NULL termination - ssize_t bytes_read = 0; - if (stdout_fd >= 0 && FD_ISSET(stdout_fd, &read_fds)) { - do { - bytes_read = ::read(stdout_fd, s, sizeof(s) - 1); - if (bytes_read < 0) { - int read_errno = errno; - DNBLogThreadedIf(LOG_PROCESS, - "read (stdout_fd, ) => %zd errno: %d (%s)", - bytes_read, read_errno, strerror(read_errno)); - } else if (bytes_read == 0) { - // EOF... - DNBLogThreadedIf( - LOG_PROCESS, - "read (stdout_fd, ) => %zd (reached EOF for child STDOUT)", - bytes_read); - stdout_fd = -1; - } else if (bytes_read > 0) { - proc->AppendSTDOUT(s, bytes_read); - } - - } while (bytes_read > 0); - } - - if (stderr_fd >= 0 && FD_ISSET(stderr_fd, &read_fds)) { - do { - bytes_read = ::read(stderr_fd, s, sizeof(s) - 1); - if (bytes_read < 0) { - int read_errno = errno; - DNBLogThreadedIf(LOG_PROCESS, - "read (stderr_fd, ) => %zd errno: %d (%s)", - bytes_read, read_errno, strerror(read_errno)); - } else if (bytes_read == 0) { - // EOF... - DNBLogThreadedIf( - LOG_PROCESS, - "read (stderr_fd, ) => %zd (reached EOF for child STDERR)", - bytes_read); - stderr_fd = -1; - } else if (bytes_read > 0) { - proc->AppendSTDOUT(s, bytes_read); - } - - } while (bytes_read > 0); - } - } - } - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%p): thread exiting...", - __FUNCTION__, arg); - return NULL; -} - -void MachProcess::SignalAsyncProfileData(const char *info) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%s) ...", __FUNCTION__, info); - PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex); - m_profile_data.push_back(info); - m_events.SetEvents(eEventProfileDataAvailable); - - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(eEventProfileDataAvailable); -} - -size_t MachProcess::GetAsyncProfileData(char *buf, size_t buf_size) { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, - reinterpret_cast<void *>(buf), (uint64_t)buf_size); - PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex); - if (m_profile_data.empty()) - return 0; - - size_t bytes_available = m_profile_data.front().size(); - if (bytes_available > 0) { - if (bytes_available > buf_size) { - memcpy(buf, m_profile_data.front().data(), buf_size); - m_profile_data.front().erase(0, buf_size); - bytes_available = buf_size; - } else { - memcpy(buf, m_profile_data.front().data(), bytes_available); - m_profile_data.erase(m_profile_data.begin()); - } - } - return bytes_available; -} - -void *MachProcess::ProfileThread(void *arg) { - MachProcess *proc = (MachProcess *)arg; - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::%s ( arg = %p ) thread starting...", - __FUNCTION__, arg); - -#if defined(__APPLE__) - pthread_setname_np("performance profiling thread"); -#endif - - while (proc->IsProfilingEnabled()) { - nub_state_t state = proc->GetState(); - if (state == eStateRunning) { - std::string data = - proc->Task().GetProfileData(proc->GetProfileScanType()); - if (!data.empty()) { - proc->SignalAsyncProfileData(data.c_str()); - } - } else if ((state == eStateUnloaded) || (state == eStateDetached) || - (state == eStateUnloaded)) { - // Done. Get out of this thread. - break; - } - - // A simple way to set up the profile interval. We can also use select() or - // dispatch timer source if necessary. - usleep(proc->ProfileInterval()); - } - return NULL; -} - -pid_t MachProcess::AttachForDebug(pid_t pid, char *err_str, size_t err_len) { - // Clear out and clean up from any current state - Clear(); - if (pid != 0) { - DNBError err; - // Make sure the process exists... - if (::getpgid(pid) < 0) { - err.SetErrorToErrno(); - const char *err_cstr = err.AsString(); - ::snprintf(err_str, err_len, "%s", - err_cstr ? err_cstr : "No such process"); - return INVALID_NUB_PROCESS; - } - - SetState(eStateAttaching); - m_pid = pid; -// Let ourselves know we are going to be using SBS or BKS if the correct flag -// bit is set... -#if defined(WITH_FBS) || defined(WITH_BKS) - bool found_app_flavor = false; -#endif - -#if defined(WITH_FBS) - if (!found_app_flavor && IsFBSProcess(pid)) { - found_app_flavor = true; - m_flags |= eMachProcessFlagsUsingFBS; - } -#elif defined(WITH_BKS) - if (!found_app_flavor && IsBKSProcess(pid)) { - found_app_flavor = true; - m_flags |= eMachProcessFlagsUsingBKS; - } -#elif defined(WITH_SPRINGBOARD) - if (IsSBProcess(pid)) - m_flags |= eMachProcessFlagsUsingSBS; -#endif - if (!m_task.StartExceptionThread(err)) { - const char *err_cstr = err.AsString(); - ::snprintf(err_str, err_len, "%s", - err_cstr ? err_cstr : "unable to start the exception thread"); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } - - errno = 0; - if (::ptrace(PT_ATTACHEXC, pid, 0, 0)) - err.SetError(errno); - else - err.Clear(); - - if (err.Success()) { - m_flags |= eMachProcessFlagsAttached; - // Sleep a bit to let the exception get received and set our process - // status - // to stopped. - ::usleep(250000); - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", pid); - return m_pid; - } else { - ::snprintf(err_str, err_len, "%s", err.AsString()); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); - } - } - return INVALID_NUB_PROCESS; -} - -Genealogy::ThreadActivitySP -MachProcess::GetGenealogyInfoForThread(nub_thread_t tid, bool &timed_out) { - return m_activities.GetGenealogyInfoForThread(m_pid, tid, m_thread_list, - m_task.TaskPort(), timed_out); -} - -Genealogy::ProcessExecutableInfoSP -MachProcess::GetGenealogyImageInfo(size_t idx) { - return m_activities.GetProcessExecutableInfosAtIndex(idx); -} - -bool MachProcess::GetOSVersionNumbers(uint64_t *major, uint64_t *minor, - uint64_t *patch) { -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000) - return false; -#else - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSOperatingSystemVersion vers = - [[NSProcessInfo processInfo] operatingSystemVersion]; - if (major) - *major = vers.majorVersion; - if (minor) - *minor = vers.minorVersion; - if (patch) - *patch = vers.patchVersion; - - [pool drain]; - - return true; -#endif -} - -// Do the process specific setup for attach. If this returns NULL, then there's -// no -// platform specific stuff to be done to wait for the attach. If you get -// non-null, -// pass that token to the CheckForProcess method, and then to -// CleanupAfterAttach. - -// Call PrepareForAttach before attaching to a process that has not yet -// launched -// This returns a token that can be passed to CheckForProcess, and to -// CleanupAfterAttach. -// You should call CleanupAfterAttach to free the token, and do whatever other -// cleanup seems good. - -const void *MachProcess::PrepareForAttach(const char *path, - nub_launch_flavor_t launch_flavor, - bool waitfor, DNBError &attach_err) { -#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) - // Tell SpringBoard to halt the next launch of this application on startup. - - if (!waitfor) - return NULL; - - const char *app_ext = strstr(path, ".app"); - const bool is_app = - app_ext != NULL && (app_ext[4] == '\0' || app_ext[4] == '/'); - if (!is_app) { - DNBLogThreadedIf( - LOG_PROCESS, - "MachProcess::PrepareForAttach(): path '%s' doesn't contain .app, " - "we can't tell springboard to wait for launch...", - path); - return NULL; - } - -#if defined(WITH_FBS) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorFBS; - if (launch_flavor != eLaunchFlavorFBS) - return NULL; -#elif defined(WITH_BKS) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorBKS; - if (launch_flavor != eLaunchFlavorBKS) - return NULL; -#elif defined(WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorSpringBoard; - if (launch_flavor != eLaunchFlavorSpringBoard) - return NULL; -#endif - - std::string app_bundle_path(path, app_ext + strlen(".app")); - - CFStringRef bundleIDCFStr = - CopyBundleIDForPath(app_bundle_path.c_str(), attach_err); - std::string bundleIDStr; - CFString::UTF8(bundleIDCFStr, bundleIDStr); - DNBLogThreadedIf(LOG_PROCESS, - "CopyBundleIDForPath (%s, err_str) returned @\"%s\"", - app_bundle_path.c_str(), bundleIDStr.c_str()); - - if (bundleIDCFStr == NULL) { - return NULL; - } - -#if defined(WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; - const char *null_path = "/dev/null"; - stdio_path = - [file_manager stringWithFileSystemRepresentation:null_path - length:strlen(null_path)]; - - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - - DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: " - "@\"%s\",options include stdio path: \"%s\", " - "BKSDebugOptionKeyDebugOnNextLaunch & " - "BKSDebugOptionKeyWaitForDebugger )", - bundleIDStr.c_str(), null_path); - - [debug_options setObject:stdio_path - forKey:FBSDebugOptionKeyStandardOutPath]; - [debug_options setObject:stdio_path - forKey:FBSDebugOptionKeyStandardErrorPath]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:FBSDebugOptionKeyWaitForDebugger]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:FBSDebugOptionKeyDebugOnNextLaunch]; - - [options setObject:debug_options - forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; - - FBSSystemService *system_service = [[FBSSystemService alloc] init]; - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block FBSOpenApplicationErrorCode attach_error_code = - FBSOpenApplicationErrorCodeNone; - - NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - - [system_service openApplication:bundleIDNSStr - options:options - clientPort:client_port - withResult:^(NSError *error) { - // The system service will cleanup the client port we - // created for us. - if (error) - attach_error_code = - (FBSOpenApplicationErrorCode)[error code]; - - [system_service release]; - dispatch_semaphore_signal(semaphore); - }]; - - const uint32_t timeout_secs = 9; - - dispatch_time_t timeout = - dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - if (!success) { - DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); - attach_err.SetErrorString( - "debugserver timed out waiting for openApplication to complete."); - attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - } else if (attach_error_code != FBSOpenApplicationErrorCodeNone) { - SetFBSError(attach_error_code, attach_err); - DNBLogError("unable to launch the application with CFBundleIdentifier " - "'%s' bks_error = %ld", - bundleIDStr.c_str(), (NSInteger)attach_error_code); - } - dispatch_release(semaphore); - [pool drain]; - } -#endif -#if defined(WITH_BKS) - if (launch_flavor == eLaunchFlavorBKS) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; - const char *null_path = "/dev/null"; - stdio_path = - [file_manager stringWithFileSystemRepresentation:null_path - length:strlen(null_path)]; - - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - - DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: " - "@\"%s\",options include stdio path: \"%s\", " - "BKSDebugOptionKeyDebugOnNextLaunch & " - "BKSDebugOptionKeyWaitForDebugger )", - bundleIDStr.c_str(), null_path); - - [debug_options setObject:stdio_path - forKey:BKSDebugOptionKeyStandardOutPath]; - [debug_options setObject:stdio_path - forKey:BKSDebugOptionKeyStandardErrorPath]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:BKSDebugOptionKeyWaitForDebugger]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:BKSDebugOptionKeyDebugOnNextLaunch]; - - [options setObject:debug_options - forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; - - BKSSystemService *system_service = [[BKSSystemService alloc] init]; - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block BKSOpenApplicationErrorCode attach_error_code = - BKSOpenApplicationErrorCodeNone; - - NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - - [system_service openApplication:bundleIDNSStr - options:options - clientPort:client_port - withResult:^(NSError *error) { - // The system service will cleanup the client port we - // created for us. - if (error) - attach_error_code = - (BKSOpenApplicationErrorCode)[error code]; - - [system_service release]; - dispatch_semaphore_signal(semaphore); - }]; - - const uint32_t timeout_secs = 9; - - dispatch_time_t timeout = - dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - if (!success) { - DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); - attach_err.SetErrorString( - "debugserver timed out waiting for openApplication to complete."); - attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - } else if (attach_error_code != BKSOpenApplicationErrorCodeNone) { - SetBKSError(attach_error_code, attach_err); - DNBLogError("unable to launch the application with CFBundleIdentifier " - "'%s' bks_error = %ld", - bundleIDStr.c_str(), attach_error_code); - } - dispatch_release(semaphore); - [pool drain]; - } -#endif - -#if defined(WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorSpringBoard) { - SBSApplicationLaunchError sbs_error = 0; - - const char *stdout_err = "/dev/null"; - CFString stdio_path; - stdio_path.SetFileSystemRepresentation(stdout_err); - - DNBLogThreadedIf(LOG_PROCESS, "SBSLaunchApplicationForDebugging ( @\"%s\" " - ", NULL, NULL, NULL, @\"%s\", @\"%s\", " - "SBSApplicationDebugOnNextLaunch | " - "SBSApplicationLaunchWaitForDebugger )", - bundleIDStr.c_str(), stdout_err, stdout_err); - - sbs_error = SBSLaunchApplicationForDebugging( - bundleIDCFStr, - (CFURLRef)NULL, // openURL - NULL, // launch_argv.get(), - NULL, // launch_envp.get(), // CFDictionaryRef environment - stdio_path.get(), stdio_path.get(), - SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger); - - if (sbs_error != SBSApplicationLaunchErrorSuccess) { - attach_err.SetError(sbs_error, DNBError::SpringBoard); - return NULL; - } - } -#endif // WITH_SPRINGBOARD - - DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch."); - return bundleIDCFStr; -#else // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined - // (WITH_FBS)) - return NULL; -#endif -} - -// Pass in the token you got from PrepareForAttach. If there is a process -// for that token, then the pid will be returned, otherwise INVALID_NUB_PROCESS -// will be returned. - -nub_process_t MachProcess::CheckForProcess(const void *attach_token, - nub_launch_flavor_t launch_flavor) { - if (attach_token == NULL) - return INVALID_NUB_PROCESS; - -#if defined(WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) { - NSString *bundleIDNSStr = (NSString *)attach_token; - FBSSystemService *systemService = [[FBSSystemService alloc] init]; - pid_t pid = [systemService pidForApplication:bundleIDNSStr]; - [systemService release]; - if (pid == 0) - return INVALID_NUB_PROCESS; - else - return pid; - } -#endif - -#if defined(WITH_BKS) - if (launch_flavor == eLaunchFlavorBKS) { - NSString *bundleIDNSStr = (NSString *)attach_token; - BKSSystemService *systemService = [[BKSSystemService alloc] init]; - pid_t pid = [systemService pidForApplication:bundleIDNSStr]; - [systemService release]; - if (pid == 0) - return INVALID_NUB_PROCESS; - else - return pid; - } -#endif - -#if defined(WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorSpringBoard) { - CFStringRef bundleIDCFStr = (CFStringRef)attach_token; - Boolean got_it; - nub_process_t attach_pid; - got_it = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &attach_pid); - if (got_it) - return attach_pid; - else - return INVALID_NUB_PROCESS; - } -#endif - return INVALID_NUB_PROCESS; -} - -// Call this to clean up after you have either attached or given up on the -// attach. -// Pass true for success if you have attached, false if you have not. -// The token will also be freed at this point, so you can't use it after calling -// this method. - -void MachProcess::CleanupAfterAttach(const void *attach_token, - nub_launch_flavor_t launch_flavor, - bool success, DNBError &err_str) { - if (attach_token == NULL) - return; - -#if defined(WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) { - if (!success) { - FBSCleanupAfterAttach(attach_token, err_str); - } - CFRelease((CFStringRef)attach_token); - } -#endif - -#if defined(WITH_BKS) - - if (launch_flavor == eLaunchFlavorBKS) { - if (!success) { - BKSCleanupAfterAttach(attach_token, err_str); - } - CFRelease((CFStringRef)attach_token); - } -#endif - -#if defined(WITH_SPRINGBOARD) - // Tell SpringBoard to cancel the debug on next launch of this application - // if we failed to attach - if (launch_flavor == eMachProcessFlagsUsingSpringBoard) { - if (!success) { - SBSApplicationLaunchError sbs_error = 0; - CFStringRef bundleIDCFStr = (CFStringRef)attach_token; - - sbs_error = SBSLaunchApplicationForDebugging( - bundleIDCFStr, (CFURLRef)NULL, NULL, NULL, NULL, NULL, - SBSApplicationCancelDebugOnNextLaunch); - - if (sbs_error != SBSApplicationLaunchErrorSuccess) { - err_str.SetError(sbs_error, DNBError::SpringBoard); - return; - } - } - - CFRelease((CFStringRef)attach_token); - } -#endif -} - -pid_t MachProcess::LaunchForDebug( - const char *path, char const *argv[], char const *envp[], - const char *working_directory, // NULL => don't change, non-NULL => set - // working directory for inferior to this - const char *stdin_path, const char *stdout_path, const char *stderr_path, - bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, - const char *event_data, DNBError &launch_err) { - // Clear out and clean up from any current state - Clear(); - - DNBLogThreadedIf(LOG_PROCESS, - "%s( path = '%s', argv = %p, envp = %p, " - "launch_flavor = %u, disable_aslr = %d )", - __FUNCTION__, path, reinterpret_cast<const void *>(argv), - reinterpret_cast<const void *>(envp), launch_flavor, - disable_aslr); - - // Fork a child process for debugging - SetState(eStateLaunching); - - switch (launch_flavor) { - case eLaunchFlavorForkExec: - m_pid = MachProcess::ForkChildForPTraceDebugging(path, argv, envp, this, - launch_err); - break; -#ifdef WITH_FBS - case eLaunchFlavorFBS: { - const char *app_ext = strstr(path, ".app"); - if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { - std::string app_bundle_path(path, app_ext + strlen(".app")); - m_flags |= eMachProcessFlagsUsingFBS; - if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, - no_stdio, disable_aslr, event_data, - launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a - // non-zero m_pid. - else - break; // We tried a FBS launch, but didn't succeed lets get out - } - } break; -#endif -#ifdef WITH_BKS - case eLaunchFlavorBKS: { - const char *app_ext = strstr(path, ".app"); - if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { - std::string app_bundle_path(path, app_ext + strlen(".app")); - m_flags |= eMachProcessFlagsUsingBKS; - if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, - no_stdio, disable_aslr, event_data, - launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a - // non-zero m_pid. - else - break; // We tried a BKS launch, but didn't succeed lets get out - } - } break; -#endif -#ifdef WITH_SPRINGBOARD - - case eLaunchFlavorSpringBoard: { - // .../whatever.app/whatever ? - // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in - // "com.apple.whatever" here - const char *app_ext = strstr(path, ".app/"); - if (app_ext == NULL) { - // .../whatever.app ? - int len = strlen(path); - if (len > 5) { - if (strcmp(path + len - 4, ".app") == 0) { - app_ext = path + len - 4; - } - } - } - if (app_ext) { - std::string app_bundle_path(path, app_ext + strlen(".app")); - if (SBLaunchForDebug(app_bundle_path.c_str(), argv, envp, no_stdio, - disable_aslr, launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a - // non-zero m_pid. - else - break; // We tried a springboard launch, but didn't succeed lets get out - } - } break; - -#endif - - case eLaunchFlavorPosixSpawn: - m_pid = MachProcess::PosixSpawnChildForPTraceDebugging( - path, DNBArchProtocol::GetArchitecture(), argv, envp, working_directory, - stdin_path, stdout_path, stderr_path, no_stdio, this, disable_aslr, - launch_err); - break; - - default: - // Invalid launch - launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - return INVALID_NUB_PROCESS; - } - - if (m_pid == INVALID_NUB_PROCESS) { - // If we don't have a valid process ID and no one has set the error, - // then return a generic error - if (launch_err.Success()) - launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - } else { - m_path = path; - size_t i; - char const *arg; - for (i = 0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - - m_task.StartExceptionThread(launch_err); - if (launch_err.Fail()) { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog("Could not get inferior's Mach exception port, sending ptrace " - "PT_KILL and exiting."); - ::ptrace(PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } - - StartSTDIOThread(); - - if (launch_flavor == eLaunchFlavorPosixSpawn) { - - SetState(eStateAttaching); - errno = 0; - int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully spawned pid %d", m_pid); - launch_err.Clear(); - } else { - SetState(eStateExited); - DNBError ptrace_err(errno, DNBError::POSIX); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to spawned pid " - "%d (err = %i, errno = %i (%s))", - m_pid, err, ptrace_err.Status(), - ptrace_err.AsString()); - launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - } - } else { - launch_err.Clear(); - } - } - return m_pid; -} - -pid_t MachProcess::PosixSpawnChildForPTraceDebugging( - const char *path, cpu_type_t cpu_type, char const *argv[], - char const *envp[], const char *working_directory, const char *stdin_path, - const char *stdout_path, const char *stderr_path, bool no_stdio, - MachProcess *process, int disable_aslr, DNBError &err) { - posix_spawnattr_t attr; - short flags; - DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, " - "working_dir=%s, stdin=%s, stdout=%s " - "stderr=%s, no-stdio=%i)", - __FUNCTION__, path, reinterpret_cast<const void *>(argv), - reinterpret_cast<const void *>(envp), working_directory, - stdin_path, stdout_path, stderr_path, no_stdio); - - err.SetError(::posix_spawnattr_init(&attr), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnattr_init ( &attr )"); - if (err.Fail()) - return INVALID_NUB_PROCESS; - - flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF | - POSIX_SPAWN_SETSIGMASK; - if (disable_aslr) - flags |= _POSIX_SPAWN_DISABLE_ASLR; - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset(&no_signals); - sigfillset(&all_signals); - ::posix_spawnattr_setsigmask(&attr, &no_signals); - ::posix_spawnattr_setsigdefault(&attr, &all_signals); - - err.SetError(::posix_spawnattr_setflags(&attr, flags), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded( - "::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED%s )", - flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" - : ""); - if (err.Fail()) - return INVALID_NUB_PROCESS; - -// Don't do this on SnowLeopard, _sometimes_ the TASK_BASIC_INFO will fail -// and we will fail to continue with our process... - -// On SnowLeopard we should set "DYLD_NO_PIE" in the inferior environment.... - -#if !defined(__arm__) - - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - if (cpu_type != 0) { - size_t ocount = 0; - err.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = " - "0x%8.8x, count => %llu )", - cpu_type, (uint64_t)ocount); - - if (err.Fail() != 0 || ocount != 1) - return INVALID_NUB_PROCESS; - } -#endif - - PseudoTerminal pty; - - posix_spawn_file_actions_t file_actions; - err.SetError(::posix_spawn_file_actions_init(&file_actions), DNBError::POSIX); - int file_actions_valid = err.Success(); - if (!file_actions_valid || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawn_file_actions_init ( &file_actions )"); - int pty_error = -1; - pid_t pid = INVALID_NUB_PROCESS; - if (file_actions_valid) { - if (stdin_path == NULL && stdout_path == NULL && stderr_path == NULL && - !no_stdio) { - pty_error = pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); - if (pty_error == PseudoTerminal::success) { - stdin_path = stdout_path = stderr_path = pty.SlaveName(); - } - } - - // if no_stdio or std paths not supplied, then route to "/dev/null". - if (no_stdio || stdin_path == NULL || stdin_path[0] == '\0') - stdin_path = "/dev/null"; - if (no_stdio || stdout_path == NULL || stdout_path[0] == '\0') - stdout_path = "/dev/null"; - if (no_stdio || stderr_path == NULL || stderr_path[0] == '\0') - stderr_path = "/dev/null"; - - err.SetError(::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, - stdin_path, - O_RDONLY | O_NOCTTY, 0), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " - "filedes=STDIN_FILENO, path='%s')", - stdin_path); - - err.SetError(::posix_spawn_file_actions_addopen( - &file_actions, STDOUT_FILENO, stdout_path, - O_WRONLY | O_NOCTTY | O_CREAT, 0640), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " - "filedes=STDOUT_FILENO, path='%s')", - stdout_path); - - err.SetError(::posix_spawn_file_actions_addopen( - &file_actions, STDERR_FILENO, stderr_path, - O_WRONLY | O_NOCTTY | O_CREAT, 0640), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " - "filedes=STDERR_FILENO, path='%s')", - stderr_path); - - // TODO: Verify if we can set the working directory back immediately - // after the posix_spawnp call without creating a race condition??? - if (working_directory) - ::chdir(working_directory); - - err.SetError(::posix_spawnp(&pid, path, &file_actions, &attr, - const_cast<char *const *>(argv), - const_cast<char *const *>(envp)), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = " - "%p, attr = %p, argv = %p, envp = %p )", - pid, path, &file_actions, &attr, argv, envp); - } else { - // TODO: Verify if we can set the working directory back immediately - // after the posix_spawnp call without creating a race condition??? - if (working_directory) - ::chdir(working_directory); - - err.SetError(::posix_spawnp(&pid, path, NULL, &attr, - const_cast<char *const *>(argv), - const_cast<char *const *>(envp)), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = " - "%p, attr = %p, argv = %p, envp = %p )", - pid, path, NULL, &attr, argv, envp); - } - - // We have seen some cases where posix_spawnp was returning a valid - // looking pid even when an error was returned, so clear it out - if (err.Fail()) - pid = INVALID_NUB_PROCESS; - - if (pty_error == 0) { - if (process != NULL) { - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - } - ::posix_spawnattr_destroy(&attr); - - if (pid != INVALID_NUB_PROCESS) { - cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess(pid); - DNBLogThreadedIf(LOG_PROCESS, - "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x", - __FUNCTION__, pid, pid_cpu_type); - if (pid_cpu_type) - DNBArchProtocol::SetArchitecture(pid_cpu_type); - } - - if (file_actions_valid) { - DNBError err2; - err2.SetError(::posix_spawn_file_actions_destroy(&file_actions), - DNBError::POSIX); - if (err2.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err2.LogThreaded("::posix_spawn_file_actions_destroy ( &file_actions )"); - } - - return pid; -} - -uint32_t MachProcess::GetCPUTypeForLocalProcess(pid_t pid) { - int mib[CTL_MAXNAME] = { - 0, - }; - size_t len = CTL_MAXNAME; - if (::sysctlnametomib("sysctl.proc_cputype", mib, &len)) - return 0; - - mib[len] = pid; - len++; - - cpu_type_t cpu; - size_t cpu_len = sizeof(cpu); - if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0)) - cpu = 0; - return cpu; -} - -pid_t MachProcess::ForkChildForPTraceDebugging(const char *path, - char const *argv[], - char const *envp[], - MachProcess *process, - DNBError &launch_err) { - PseudoTerminal::Status pty_error = PseudoTerminal::success; - - // Use a fork that ties the child process's stdin/out/err to a pseudo - // terminal so we can read it in our MachProcess::STDIOThread - // as unbuffered io. - PseudoTerminal pty; - pid_t pid = pty.Fork(pty_error); - - if (pid < 0) { - //-------------------------------------------------------------- - // Status during fork. - //-------------------------------------------------------------- - return pid; - } else if (pid == 0) { - //-------------------------------------------------------------- - // Child process - //-------------------------------------------------------------- - ::ptrace(PT_TRACE_ME, 0, 0, 0); // Debug this process - ::ptrace(PT_SIGEXC, 0, 0, 0); // Get BSD signals as mach exceptions - - // If our parent is setgid, lets make sure we don't inherit those - // extra powers due to nepotism. - if (::setgid(getgid()) == 0) { - - // Let the child have its own process group. We need to execute - // this call in both the child and parent to avoid a race condition - // between the two processes. - ::setpgid(0, 0); // Set the child process group to match its pid - - // Sleep a bit to before the exec call - ::sleep(1); - - // Turn this process into - ::execv(path, const_cast<char *const *>(argv)); - } - // Exit with error code. Child process should have taken - // over in above exec call and if the exec fails it will - // exit the child process below. - ::exit(127); - } else { - //-------------------------------------------------------------- - // Parent process - //-------------------------------------------------------------- - // Let the child have its own process group. We need to execute - // this call in both the child and parent to avoid a race condition - // between the two processes. - ::setpgid(pid, pid); // Set the child process group to match its pid - - if (process != NULL) { - // Release our master pty file descriptor so the pty class doesn't - // close it and so we can continue to use it in our STDIO thread - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - } - return pid; -} - -#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) -// This returns a CFRetained pointer to the Bundle ID for app_bundle_path, -// or NULL if there was some problem getting the bundle id. -static CFStringRef CopyBundleIDForPath(const char *app_bundle_path, - DNBError &err_str) { - CFBundle bundle(app_bundle_path); - CFStringRef bundleIDCFStr = bundle.GetIdentifier(); - std::string bundleID; - if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL) { - struct stat app_bundle_stat; - char err_msg[PATH_MAX]; - - if (::stat(app_bundle_path, &app_bundle_stat) < 0) { - err_str.SetError(errno, DNBError::POSIX); - snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), - app_bundle_path); - err_str.SetErrorString(err_msg); - DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg); - } else { - err_str.SetError(-1, DNBError::Generic); - snprintf(err_msg, sizeof(err_msg), - "failed to extract CFBundleIdentifier from %s", app_bundle_path); - err_str.SetErrorString(err_msg); - DNBLogThreadedIf( - LOG_PROCESS, - "%s() error: failed to extract CFBundleIdentifier from '%s'", - __FUNCTION__, app_bundle_path); - } - return NULL; - } - - DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", - __FUNCTION__, bundleID.c_str()); - CFRetain(bundleIDCFStr); - - return bundleIDCFStr; -} -#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined - // (WITH_FBS) -#ifdef WITH_SPRINGBOARD - -pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[], - char const *envp[], bool no_stdio, - bool disable_aslr, DNBError &launch_err) { - // Clear out and clean up from any current state - Clear(); - - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); - - // Fork a child process for debugging - SetState(eStateLaunching); - m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio, - this, launch_err); - if (m_pid != 0) { - m_flags |= eMachProcessFlagsUsingSBS; - m_path = path; - size_t i; - char const *arg; - for (i = 0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); - - if (launch_err.Fail()) { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog("Could not get inferior's Mach exception port, sending ptrace " - "PT_KILL and exiting."); - ::ptrace(PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } - - StartSTDIOThread(); - SetState(eStateAttaching); - int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); - } else { - SetState(eStateExited); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); - } - } - return m_pid; -} - -#include <servers/bootstrap.h> - -pid_t MachProcess::SBForkChildForPTraceDebugging( - const char *app_bundle_path, char const *argv[], char const *envp[], - bool no_stdio, MachProcess *process, DNBError &launch_err) { - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, - app_bundle_path, process); - CFAllocatorRef alloc = kCFAllocatorDefault; - - if (argv[0] == NULL) - return INVALID_NUB_PROCESS; - - size_t argc = 0; - // Count the number of arguments - while (argv[argc] != NULL) - argc++; - - // Enumerate the arguments - size_t first_launch_arg_idx = 1; - CFReleaser<CFMutableArrayRef> launch_argv; - - if (argv[first_launch_arg_idx]) { - size_t launch_argc = argc > 0 ? argc - 1 : 0; - launch_argv.reset( - ::CFArrayCreateMutable(alloc, launch_argc, &kCFTypeArrayCallBacks)); - size_t i; - char const *arg; - CFString launch_arg; - for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); - i++) { - launch_arg.reset( - ::CFStringCreateWithCString(alloc, arg, kCFStringEncodingUTF8)); - if (launch_arg.get() != NULL) - CFArrayAppendValue(launch_argv.get(), launch_arg.get()); - else - break; - } - } - - // Next fill in the arguments dictionary. Note, the envp array is of the form - // Variable=value but SpringBoard wants a CF dictionary. So we have to - // convert - // this here. - - CFReleaser<CFMutableDictionaryRef> launch_envp; - - if (envp[0]) { - launch_envp.reset( - ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - const char *value; - int name_len; - CFString name_string, value_string; - - for (int i = 0; envp[i] != NULL; i++) { - value = strstr(envp[i], "="); - - // If the name field is empty or there's no =, skip it. Somebody's - // messing with us. - if (value == NULL || value == envp[i]) - continue; - - name_len = value - envp[i]; - - // Now move value over the "=" - value++; - - name_string.reset( - ::CFStringCreateWithBytes(alloc, (const UInt8 *)envp[i], name_len, - kCFStringEncodingUTF8, false)); - value_string.reset( - ::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8)); - CFDictionarySetValue(launch_envp.get(), name_string.get(), - value_string.get()); - } - } - - CFString stdio_path; - - PseudoTerminal pty; - if (!no_stdio) { - PseudoTerminal::Status pty_err = - pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); - if (pty_err == PseudoTerminal::success) { - const char *slave_name = pty.SlaveName(); - DNBLogThreadedIf(LOG_PROCESS, - "%s() successfully opened master pty, slave is %s", - __FUNCTION__, slave_name); - if (slave_name && slave_name[0]) { - ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO); - stdio_path.SetFileSystemRepresentation(slave_name); - } - } - } - - if (stdio_path.get() == NULL) { - stdio_path.SetFileSystemRepresentation("/dev/null"); - } - - CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err); - if (bundleIDCFStr == NULL) - return INVALID_NUB_PROCESS; - - // This is just for logging: - std::string bundleID; - CFString::UTF8(bundleIDCFStr, bundleID); - - DNBLogThreadedIf(LOG_PROCESS, "%s() serialized launch arg array", - __FUNCTION__); - - // Find SpringBoard - SBSApplicationLaunchError sbs_error = 0; - sbs_error = SBSLaunchApplicationForDebugging( - bundleIDCFStr, - (CFURLRef)NULL, // openURL - launch_argv.get(), - launch_envp.get(), // CFDictionaryRef environment - stdio_path.get(), stdio_path.get(), - SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice); - - launch_err.SetError(sbs_error, DNBError::SpringBoard); - - if (sbs_error == SBSApplicationLaunchErrorSuccess) { - static const useconds_t pid_poll_interval = 200000; - static const useconds_t pid_poll_timeout = 30000000; - - useconds_t pid_poll_total = 0; - - nub_process_t pid = INVALID_NUB_PROCESS; - Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); - // Poll until the process is running, as long as we are getting valid - // responses and the timeout hasn't expired - // A return PID of 0 means the process is not running, which may be because - // it hasn't been (asynchronously) started - // yet, or that it died very quickly (if you weren't using waitForDebugger). - while (!pid_found && pid_poll_total < pid_poll_timeout) { - usleep(pid_poll_interval); - pid_poll_total += pid_poll_interval; - DNBLogThreadedIf(LOG_PROCESS, - "%s() polling Springboard for pid for %s...", - __FUNCTION__, bundleID.c_str()); - pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); - } - - CFRelease(bundleIDCFStr); - if (pid_found) { - if (process != NULL) { - // Release our master pty file descriptor so the pty class doesn't - // close it and so we can continue to use it in our STDIO thread - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - DNBLogThreadedIf(LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid); - } else { - DNBLogError("failed to lookup the process ID for CFBundleIdentifier %s.", - bundleID.c_str()); - } - return pid; - } - - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' " - "sbs_error = %u", - bundleID.c_str(), sbs_error); - return INVALID_NUB_PROCESS; -} - -#endif // #ifdef WITH_SPRINGBOARD - -#if defined(WITH_BKS) || defined(WITH_FBS) -pid_t MachProcess::BoardServiceLaunchForDebug( - const char *path, char const *argv[], char const *envp[], bool no_stdio, - bool disable_aslr, const char *event_data, DNBError &launch_err) { - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); - - // Fork a child process for debugging - SetState(eStateLaunching); - m_pid = BoardServiceForkChildForPTraceDebugging( - path, argv, envp, no_stdio, disable_aslr, event_data, launch_err); - if (m_pid != 0) { - m_path = path; - size_t i; - char const *arg; - for (i = 0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); - - if (launch_err.Fail()) { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog("Could not get inferior's Mach exception port, sending ptrace " - "PT_KILL and exiting."); - ::ptrace(PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } - - StartSTDIOThread(); - SetState(eStateAttaching); - int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); - } else { - SetState(eStateExited); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); - } - } - return m_pid; -} - -pid_t MachProcess::BoardServiceForkChildForPTraceDebugging( - const char *app_bundle_path, char const *argv[], char const *envp[], - bool no_stdio, bool disable_aslr, const char *event_data, - DNBError &launch_err) { - if (argv[0] == NULL) - return INVALID_NUB_PROCESS; - - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, - app_bundle_path, this); - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - size_t argc = 0; - // Count the number of arguments - while (argv[argc] != NULL) - argc++; - - // Enumerate the arguments - size_t first_launch_arg_idx = 1; - - NSMutableArray *launch_argv = nil; - - if (argv[first_launch_arg_idx]) { - size_t launch_argc = argc > 0 ? argc - 1 : 0; - launch_argv = [NSMutableArray arrayWithCapacity:launch_argc]; - size_t i; - char const *arg; - NSString *launch_arg; - for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); - i++) { - launch_arg = [NSString stringWithUTF8String:arg]; - // FIXME: Should we silently eat an argument that we can't convert into a - // UTF8 string? - if (launch_arg != nil) - [launch_argv addObject:launch_arg]; - else - break; - } - } - - NSMutableDictionary *launch_envp = nil; - if (envp[0]) { - launch_envp = [[NSMutableDictionary alloc] init]; - const char *value; - int name_len; - NSString *name_string, *value_string; - - for (int i = 0; envp[i] != NULL; i++) { - value = strstr(envp[i], "="); - - // If the name field is empty or there's no =, skip it. Somebody's - // messing with us. - if (value == NULL || value == envp[i]) - continue; - - name_len = value - envp[i]; - - // Now move value over the "=" - value++; - name_string = [[NSString alloc] initWithBytes:envp[i] - length:name_len - encoding:NSUTF8StringEncoding]; - value_string = [NSString stringWithUTF8String:value]; - [launch_envp setObject:value_string forKey:name_string]; - } - } - - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; - - PseudoTerminal pty; - if (!no_stdio) { - PseudoTerminal::Status pty_err = - pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); - if (pty_err == PseudoTerminal::success) { - const char *slave_name = pty.SlaveName(); - DNBLogThreadedIf(LOG_PROCESS, - "%s() successfully opened master pty, slave is %s", - __FUNCTION__, slave_name); - if (slave_name && slave_name[0]) { - ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO); - stdio_path = [file_manager - stringWithFileSystemRepresentation:slave_name - length:strlen(slave_name)]; - } - } - } - - if (stdio_path == nil) { - const char *null_path = "/dev/null"; - stdio_path = - [file_manager stringWithFileSystemRepresentation:null_path - length:strlen(null_path)]; - } - - CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err); - if (bundleIDCFStr == NULL) { - [pool drain]; - return INVALID_NUB_PROCESS; - } - - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use - // toll-free bridging here: - NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - - // Okay, now let's assemble all these goodies into the BackBoardServices - // options mega-dictionary: - - NSMutableDictionary *options = nullptr; - pid_t return_pid = INVALID_NUB_PROCESS; - bool success = false; - -#ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) { - options = - BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, - stdio_path, disable_aslr, event_data); - success = BKSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err, - &return_pid); - } -#endif -#ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) { - options = - FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, - stdio_path, disable_aslr, event_data); - success = FBSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err, - &return_pid); - } -#endif - - if (success) { - int master_fd = pty.ReleaseMasterFD(); - SetChildFileDescriptors(master_fd, master_fd, master_fd); - CFString::UTF8(bundleIDCFStr, m_bundle_id); - } - - [pool drain]; - - return return_pid; -} - -bool MachProcess::BoardServiceSendEvent(const char *event_data, - DNBError &send_err) { - bool return_value = true; - - if (event_data == NULL || *event_data == '\0') { - DNBLogError("SendEvent called with NULL event data."); - send_err.SetErrorString("SendEvent called with empty event data"); - return false; - } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - if (strcmp(event_data, "BackgroundApplication") == 0) { -// This is an event I cooked up. What you actually do is foreground the system -// app, so: -#ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) { - return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL); - } -#endif -#ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) { - return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL); - } -#endif - if (!return_value) { - DNBLogError("Failed to background application, error: %s.", - send_err.AsString()); - } - } else { - if (m_bundle_id.empty()) { - // See if we can figure out the bundle ID for this PID: - - DNBLogError( - "Tried to send event \"%s\" to a process that has no bundle ID.", - event_data); - return false; - } - - NSString *bundleIDNSStr = - [NSString stringWithUTF8String:m_bundle_id.c_str()]; - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - -#ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) { - if (!BKSAddEventDataToOptions(options, event_data, send_err)) { - [pool drain]; - return false; - } - return_value = BKSCallOpenApplicationFunction(bundleIDNSStr, options, - send_err, NULL); - DNBLogThreadedIf(LOG_PROCESS, - "Called BKSCallOpenApplicationFunction to send event."); - } -#endif -#ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) { - if (!FBSAddEventDataToOptions(options, event_data, send_err)) { - [pool drain]; - return false; - } - return_value = FBSCallOpenApplicationFunction(bundleIDNSStr, options, - send_err, NULL); - DNBLogThreadedIf(LOG_PROCESS, - "Called FBSCallOpenApplicationFunction to send event."); - } -#endif - - if (!return_value) { - DNBLogError("Failed to send event: %s, error: %s.", event_data, - send_err.AsString()); - } - } - - [pool drain]; - return return_value; -} -#endif // defined(WITH_BKS) || defined (WITH_FBS) - -#ifdef WITH_BKS -void MachProcess::BKSCleanupAfterAttach(const void *attach_token, - DNBError &err_str) { - bool success; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use - // toll-free bridging here: - NSString *bundleIDNSStr = (NSString *)attach_token; - - // Okay, now let's assemble all these goodies into the BackBoardServices - // options mega-dictionary: - - // First we have the debug sub-dictionary: - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:BKSDebugOptionKeyCancelDebugOnNextLaunch]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject:debug_options - forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; - - success = - BKSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL); - - if (!success) { - DNBLogError("error trying to cancel debug on next launch for %s: %s", - [bundleIDNSStr UTF8String], err_str.AsString()); - } - - [pool drain]; -} -#endif // WITH_BKS - -#ifdef WITH_FBS -void MachProcess::FBSCleanupAfterAttach(const void *attach_token, - DNBError &err_str) { - bool success; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use - // toll-free bridging here: - NSString *bundleIDNSStr = (NSString *)attach_token; - - // Okay, now let's assemble all these goodies into the BackBoardServices - // options mega-dictionary: - - // First we have the debug sub-dictionary: - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - [debug_options setObject:[NSNumber numberWithBool:YES] - forKey:FBSDebugOptionKeyCancelDebugOnNextLaunch]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject:debug_options - forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; - - success = - FBSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL); - - if (!success) { - DNBLogError("error trying to cancel debug on next launch for %s: %s", - [bundleIDNSStr UTF8String], err_str.AsString()); - } - - [pool drain]; -} -#endif // WITH_FBS diff --git a/tools/debugserver/source/MacOSX/MachTask.h b/tools/debugserver/source/MacOSX/MachTask.h deleted file mode 100644 index 1fe74ddec56c..000000000000 --- a/tools/debugserver/source/MacOSX/MachTask.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- MachTask.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -//---------------------------------------------------------------------- -// -// MachTask.h -// debugserver -// -// Created by Greg Clayton on 12/5/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachTask_h__ -#define __MachTask_h__ - -#include <mach/mach.h> -#include <sys/socket.h> -#include <map> -#include <string> -#include "DNBDefs.h" -#include "MachException.h" -#include "MachVMMemory.h" -#include "PThreadMutex.h" - -class MachProcess; - -typedef uint64_t MachMallocEventId; - -enum MachMallocEventType { - eMachMallocEventTypeAlloc = 2, - eMachMallocEventTypeDealloc = 4, - eMachMallocEventTypeOther = 1 -}; - -struct MachMallocEvent { - mach_vm_address_t m_base_address; - uint64_t m_size; - MachMallocEventType m_event_type; - MachMallocEventId m_event_id; -}; - -class MachTask { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - MachTask(MachProcess *process); - virtual ~MachTask(); - - void Clear(); - - kern_return_t Suspend(); - kern_return_t Resume(); - - nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf); - nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf); - int GetMemoryRegionInfo(nub_addr_t addr, DNBRegionInfo *region_info); - std::string GetProfileData(DNBProfileDataScanType scanType); - - nub_addr_t AllocateMemory(nub_size_t size, uint32_t permissions); - nub_bool_t DeallocateMemory(nub_addr_t addr); - - mach_port_t ExceptionPort() const; - bool ExceptionPortIsValid() const; - kern_return_t SaveExceptionPortInfo(); - kern_return_t RestoreExceptionPortInfo(); - kern_return_t ShutDownExcecptionThread(); - - bool StartExceptionThread(DNBError &err); - nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err); - kern_return_t BasicInfo(struct task_basic_info *info); - static kern_return_t BasicInfo(task_t task, struct task_basic_info *info); - bool IsValid() const; - static bool IsValid(task_t task); - static void *ExceptionThread(void *arg); - void TaskPortChanged(task_t task); - task_t TaskPort() const { return m_task; } - task_t TaskPortForProcessID(DNBError &err, bool force = false); - static task_t TaskPortForProcessID(pid_t pid, DNBError &err, - uint32_t num_retries = 10, - uint32_t usec_interval = 10000); - - MachProcess *Process() { return m_process; } - const MachProcess *Process() const { return m_process; } - - nub_size_t PageSize(); - -protected: - MachProcess *m_process; // The mach process that owns this MachTask - task_t m_task; - MachVMMemory m_vm_memory; // Special mach memory reading class that will take - // care of watching for page and region boundaries - MachException::PortInfo - m_exc_port_info; // Saved settings for all exception ports - pthread_t m_exception_thread; // Thread ID for the exception thread in case we - // need it - mach_port_t m_exception_port; // Exception port on which we will receive child - // exceptions - - typedef std::map<mach_vm_address_t, size_t> allocation_collection; - allocation_collection m_allocations; - -private: - MachTask(const MachTask &); // Outlaw - MachTask &operator=(const MachTask &rhs); // Outlaw -}; - -#endif // __MachTask_h__ diff --git a/tools/debugserver/source/MacOSX/MachTask.mm b/tools/debugserver/source/MacOSX/MachTask.mm deleted file mode 100644 index d05f50029f16..000000000000 --- a/tools/debugserver/source/MacOSX/MachTask.mm +++ /dev/null @@ -1,962 +0,0 @@ -//===-- MachTask.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -//---------------------------------------------------------------------- -// -// MachTask.cpp -// debugserver -// -// Created by Greg Clayton on 12/5/08. -// -//===----------------------------------------------------------------------===// - -#include "MachTask.h" - -// C Includes - -#include <mach-o/dyld_images.h> -#include <mach/mach_vm.h> -#import <sys/sysctl.h> - -#if defined(__APPLE__) -#include <pthread.h> -#include <sched.h> -#endif - -// C++ Includes -#include <iomanip> -#include <sstream> - -// Other libraries and framework includes -// Project includes -#include "CFUtils.h" -#include "DNB.h" -#include "DNBDataRef.h" -#include "DNBError.h" -#include "DNBLog.h" -#include "MachProcess.h" - -#ifdef WITH_SPRINGBOARD - -#include <CoreFoundation/CoreFoundation.h> -#include <SpringBoardServices/SBSWatchdogAssertion.h> -#include <SpringBoardServices/SpringBoardServer.h> - -#endif - -#ifdef WITH_BKS -extern "C" { -#import <BackBoardServices/BKSWatchdogAssertion.h> -#import <BackBoardServices/BackBoardServices.h> -#import <Foundation/Foundation.h> -} -#endif - -#include <AvailabilityMacros.h> - -#ifdef LLDB_ENERGY -#include <mach/mach_time.h> -#include <pmenergy.h> -#include <pmsample.h> -#endif - -//---------------------------------------------------------------------- -// MachTask constructor -//---------------------------------------------------------------------- -MachTask::MachTask(MachProcess *process) - : m_process(process), m_task(TASK_NULL), m_vm_memory(), - m_exception_thread(0), m_exception_port(MACH_PORT_NULL) { - memset(&m_exc_port_info, 0, sizeof(m_exc_port_info)); -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -MachTask::~MachTask() { Clear(); } - -//---------------------------------------------------------------------- -// MachTask::Suspend -//---------------------------------------------------------------------- -kern_return_t MachTask::Suspend() { - DNBError err; - task_t task = TaskPort(); - err = ::task_suspend(task); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::task_suspend ( target_task = 0x%4.4x )", task); - return err.Status(); -} - -//---------------------------------------------------------------------- -// MachTask::Resume -//---------------------------------------------------------------------- -kern_return_t MachTask::Resume() { - struct task_basic_info task_info; - task_t task = TaskPort(); - if (task == TASK_NULL) - return KERN_INVALID_ARGUMENT; - - DNBError err; - err = BasicInfo(task, &task_info); - - if (err.Success()) { - // task_resume isn't counted like task_suspend calls are, are, so if the - // task is not suspended, don't try and resume it since it is already - // running - if (task_info.suspend_count > 0) { - err = ::task_resume(task); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::task_resume ( target_task = 0x%4.4x )", task); - } - } - return err.Status(); -} - -//---------------------------------------------------------------------- -// MachTask::ExceptionPort -//---------------------------------------------------------------------- -mach_port_t MachTask::ExceptionPort() const { return m_exception_port; } - -//---------------------------------------------------------------------- -// MachTask::ExceptionPortIsValid -//---------------------------------------------------------------------- -bool MachTask::ExceptionPortIsValid() const { - return MACH_PORT_VALID(m_exception_port); -} - -//---------------------------------------------------------------------- -// MachTask::Clear -//---------------------------------------------------------------------- -void MachTask::Clear() { - // Do any cleanup needed for this task - m_task = TASK_NULL; - m_exception_thread = 0; - m_exception_port = MACH_PORT_NULL; -} - -//---------------------------------------------------------------------- -// MachTask::SaveExceptionPortInfo -//---------------------------------------------------------------------- -kern_return_t MachTask::SaveExceptionPortInfo() { - return m_exc_port_info.Save(TaskPort()); -} - -//---------------------------------------------------------------------- -// MachTask::RestoreExceptionPortInfo -//---------------------------------------------------------------------- -kern_return_t MachTask::RestoreExceptionPortInfo() { - return m_exc_port_info.Restore(TaskPort()); -} - -//---------------------------------------------------------------------- -// MachTask::ReadMemory -//---------------------------------------------------------------------- -nub_size_t MachTask::ReadMemory(nub_addr_t addr, nub_size_t size, void *buf) { - nub_size_t n = 0; - task_t task = TaskPort(); - if (task != TASK_NULL) { - n = m_vm_memory.Read(task, addr, buf, size); - - DNBLogThreadedIf(LOG_MEMORY, "MachTask::ReadMemory ( addr = 0x%8.8llx, " - "size = %llu, buf = %p) => %llu bytes read", - (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); - if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || - (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) { - DNBDataRef data((uint8_t *)buf, n, false); - data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, - DNBDataRef::TypeUInt8, 16); - } - } - return n; -} - -//---------------------------------------------------------------------- -// MachTask::WriteMemory -//---------------------------------------------------------------------- -nub_size_t MachTask::WriteMemory(nub_addr_t addr, nub_size_t size, - const void *buf) { - nub_size_t n = 0; - task_t task = TaskPort(); - if (task != TASK_NULL) { - n = m_vm_memory.Write(task, addr, buf, size); - DNBLogThreadedIf(LOG_MEMORY, "MachTask::WriteMemory ( addr = 0x%8.8llx, " - "size = %llu, buf = %p) => %llu bytes written", - (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); - if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || - (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) { - DNBDataRef data((const uint8_t *)buf, n, false); - data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, - DNBDataRef::TypeUInt8, 16); - } - } - return n; -} - -//---------------------------------------------------------------------- -// MachTask::MemoryRegionInfo -//---------------------------------------------------------------------- -int MachTask::GetMemoryRegionInfo(nub_addr_t addr, DNBRegionInfo *region_info) { - task_t task = TaskPort(); - if (task == TASK_NULL) - return -1; - - int ret = m_vm_memory.GetMemoryRegionInfo(task, addr, region_info); - DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx " - ") => %i (start = 0x%8.8llx, size = 0x%8.8llx, " - "permissions = %u)", - (uint64_t)addr, ret, (uint64_t)region_info->addr, - (uint64_t)region_info->size, region_info->permissions); - return ret; -} - -#define TIME_VALUE_TO_TIMEVAL(a, r) \ - do { \ - (r)->tv_sec = (a)->seconds; \ - (r)->tv_usec = (a)->microseconds; \ - } while (0) - -// We should consider moving this into each MacThread. -static void get_threads_profile_data(DNBProfileDataScanType scanType, - task_t task, nub_process_t pid, - std::vector<uint64_t> &threads_id, - std::vector<std::string> &threads_name, - std::vector<uint64_t> &threads_used_usec) { - kern_return_t kr; - thread_act_array_t threads; - mach_msg_type_number_t tcnt; - - kr = task_threads(task, &threads, &tcnt); - if (kr != KERN_SUCCESS) - return; - - for (mach_msg_type_number_t i = 0; i < tcnt; i++) { - thread_identifier_info_data_t identifier_info; - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - kr = ::thread_info(threads[i], THREAD_IDENTIFIER_INFO, - (thread_info_t)&identifier_info, &count); - if (kr != KERN_SUCCESS) - continue; - - thread_basic_info_data_t basic_info; - count = THREAD_BASIC_INFO_COUNT; - kr = ::thread_info(threads[i], THREAD_BASIC_INFO, - (thread_info_t)&basic_info, &count); - if (kr != KERN_SUCCESS) - continue; - - if ((basic_info.flags & TH_FLAGS_IDLE) == 0) { - nub_thread_t tid = - MachThread::GetGloballyUniqueThreadIDForMachPortID(threads[i]); - threads_id.push_back(tid); - - if ((scanType & eProfileThreadName) && - (identifier_info.thread_handle != 0)) { - struct proc_threadinfo proc_threadinfo; - int len = ::proc_pidinfo(pid, PROC_PIDTHREADINFO, - identifier_info.thread_handle, - &proc_threadinfo, PROC_PIDTHREADINFO_SIZE); - if (len && proc_threadinfo.pth_name[0]) { - threads_name.push_back(proc_threadinfo.pth_name); - } else { - threads_name.push_back(""); - } - } else { - threads_name.push_back(""); - } - struct timeval tv; - struct timeval thread_tv; - TIME_VALUE_TO_TIMEVAL(&basic_info.user_time, &thread_tv); - TIME_VALUE_TO_TIMEVAL(&basic_info.system_time, &tv); - timeradd(&thread_tv, &tv, &thread_tv); - uint64_t used_usec = thread_tv.tv_sec * 1000000ULL + thread_tv.tv_usec; - threads_used_usec.push_back(used_usec); - } - - mach_port_deallocate(mach_task_self(), threads[i]); - } - mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)threads, - tcnt * sizeof(*threads)); -} - -#define RAW_HEXBASE std::setfill('0') << std::hex << std::right -#define DECIMAL std::dec << std::setfill(' ') -std::string MachTask::GetProfileData(DNBProfileDataScanType scanType) { - std::string result; - - static int32_t numCPU = -1; - struct host_cpu_load_info host_info; - if (scanType & eProfileHostCPU) { - int32_t mib[] = {CTL_HW, HW_AVAILCPU}; - size_t len = sizeof(numCPU); - if (numCPU == -1) { - if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != - 0) - return result; - } - - mach_port_t localHost = mach_host_self(); - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, - (host_info_t)&host_info, &count); - if (kr != KERN_SUCCESS) - return result; - } - - task_t task = TaskPort(); - if (task == TASK_NULL) - return result; - - pid_t pid = m_process->ProcessID(); - - struct task_basic_info task_info; - DNBError err; - err = BasicInfo(task, &task_info); - - if (!err.Success()) - return result; - - uint64_t elapsed_usec = 0; - uint64_t task_used_usec = 0; - if (scanType & eProfileCPU) { - // Get current used time. - struct timeval current_used_time; - struct timeval tv; - TIME_VALUE_TO_TIMEVAL(&task_info.user_time, ¤t_used_time); - TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv); - timeradd(¤t_used_time, &tv, ¤t_used_time); - task_used_usec = - current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec; - - struct timeval current_elapsed_time; - int res = gettimeofday(¤t_elapsed_time, NULL); - if (res == 0) { - elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + - current_elapsed_time.tv_usec; - } - } - - std::vector<uint64_t> threads_id; - std::vector<std::string> threads_name; - std::vector<uint64_t> threads_used_usec; - - if (scanType & eProfileThreadsCPU) { - get_threads_profile_data(scanType, task, pid, threads_id, threads_name, - threads_used_usec); - } - - vm_statistics64_data_t vminfo; - uint64_t physical_memory = 0; - uint64_t anonymous = 0; - uint64_t phys_footprint = 0; - uint64_t memory_cap = 0; - if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, - m_process->GetCPUType(), pid, vminfo, - physical_memory, anonymous, - phys_footprint, memory_cap)) { - std::ostringstream profile_data_stream; - - if (scanType & eProfileHostCPU) { - profile_data_stream << "num_cpu:" << numCPU << ';'; - profile_data_stream << "host_user_ticks:" - << host_info.cpu_ticks[CPU_STATE_USER] << ';'; - profile_data_stream << "host_sys_ticks:" - << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';'; - profile_data_stream << "host_idle_ticks:" - << host_info.cpu_ticks[CPU_STATE_IDLE] << ';'; - } - - if (scanType & eProfileCPU) { - profile_data_stream << "elapsed_usec:" << elapsed_usec << ';'; - profile_data_stream << "task_used_usec:" << task_used_usec << ';'; - } - - if (scanType & eProfileThreadsCPU) { - const size_t num_threads = threads_id.size(); - for (size_t i = 0; i < num_threads; i++) { - profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] - << std::dec << ';'; - profile_data_stream << "thread_used_usec:" << threads_used_usec[i] - << ';'; - - if (scanType & eProfileThreadName) { - profile_data_stream << "thread_used_name:"; - const size_t len = threads_name[i].size(); - if (len) { - const char *thread_name = threads_name[i].c_str(); - // Make sure that thread name doesn't interfere with our delimiter. - profile_data_stream << RAW_HEXBASE << std::setw(2); - const uint8_t *ubuf8 = (const uint8_t *)(thread_name); - for (size_t j = 0; j < len; j++) { - profile_data_stream << (uint32_t)(ubuf8[j]); - } - // Reset back to DECIMAL. - profile_data_stream << DECIMAL; - } - profile_data_stream << ';'; - } - } - } - - if (scanType & eProfileHostMemory) - profile_data_stream << "total:" << physical_memory << ';'; - - if (scanType & eProfileMemory) { - static vm_size_t pagesize = vm_kernel_page_size; - - // This mimicks Activity Monitor. - uint64_t total_used_count = - (physical_memory / pagesize) - - (vminfo.free_count - vminfo.speculative_count) - - vminfo.external_page_count - vminfo.purgeable_count; - profile_data_stream << "used:" << total_used_count * pagesize << ';'; - - if (scanType & eProfileMemoryAnonymous) { - profile_data_stream << "anonymous:" << anonymous << ';'; - } - - profile_data_stream << "phys_footprint:" << phys_footprint << ';'; - } - - if (scanType & eProfileMemoryCap) { - profile_data_stream << "mem_cap:" << memory_cap << ';'; - } - -#ifdef LLDB_ENERGY - if (scanType & eProfileEnergy) { - struct rusage_info_v2 info; - int rc = proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t *)&info); - if (rc == 0) { - uint64_t now = mach_absolute_time(); - pm_task_energy_data_t pm_energy; - memset(&pm_energy, 0, sizeof(pm_energy)); - /* - * Disable most features of pm_sample_pid. It will gather - * network/GPU/WindowServer information; fill in the rest. - */ - pm_sample_task_and_pid(task, pid, &pm_energy, now, - PM_SAMPLE_ALL & ~PM_SAMPLE_NAME & - ~PM_SAMPLE_INTERVAL & ~PM_SAMPLE_CPU & - ~PM_SAMPLE_DISK); - pm_energy.sti.total_user = info.ri_user_time; - pm_energy.sti.total_system = info.ri_system_time; - pm_energy.sti.task_interrupt_wakeups = info.ri_interrupt_wkups; - pm_energy.sti.task_platform_idle_wakeups = info.ri_pkg_idle_wkups; - pm_energy.diskio_bytesread = info.ri_diskio_bytesread; - pm_energy.diskio_byteswritten = info.ri_diskio_byteswritten; - pm_energy.pageins = info.ri_pageins; - - uint64_t total_energy = - (uint64_t)(pm_energy_impact(&pm_energy) * NSEC_PER_SEC); - // uint64_t process_age = now - info.ri_proc_start_abstime; - // uint64_t avg_energy = 100.0 * (double)total_energy / - // (double)process_age; - - profile_data_stream << "energy:" << total_energy << ';'; - } - } -#endif - - profile_data_stream << "--end--;"; - - result = profile_data_stream.str(); - } - - return result; -} - -//---------------------------------------------------------------------- -// MachTask::TaskPortForProcessID -//---------------------------------------------------------------------- -task_t MachTask::TaskPortForProcessID(DNBError &err, bool force) { - if (((m_task == TASK_NULL) || force) && m_process != NULL) - m_task = MachTask::TaskPortForProcessID(m_process->ProcessID(), err); - return m_task; -} - -//---------------------------------------------------------------------- -// MachTask::TaskPortForProcessID -//---------------------------------------------------------------------- -task_t MachTask::TaskPortForProcessID(pid_t pid, DNBError &err, - uint32_t num_retries, - uint32_t usec_interval) { - if (pid != INVALID_NUB_PROCESS) { - DNBError err; - mach_port_t task_self = mach_task_self(); - task_t task = TASK_NULL; - for (uint32_t i = 0; i < num_retries; i++) { - err = ::task_for_pid(task_self, pid, &task); - - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) { - char str[1024]; - ::snprintf(str, sizeof(str), "::task_for_pid ( target_tport = 0x%4.4x, " - "pid = %d, &task ) => err = 0x%8.8x (%s)", - task_self, pid, err.Status(), - err.AsString() ? err.AsString() : "success"); - if (err.Fail()) - err.SetErrorString(str); - err.LogThreaded(str); - } - - if (err.Success()) - return task; - - // Sleep a bit and try again - ::usleep(usec_interval); - } - } - return TASK_NULL; -} - -//---------------------------------------------------------------------- -// MachTask::BasicInfo -//---------------------------------------------------------------------- -kern_return_t MachTask::BasicInfo(struct task_basic_info *info) { - return BasicInfo(TaskPort(), info); -} - -//---------------------------------------------------------------------- -// MachTask::BasicInfo -//---------------------------------------------------------------------- -kern_return_t MachTask::BasicInfo(task_t task, struct task_basic_info *info) { - if (info == NULL) - return KERN_INVALID_ARGUMENT; - - DNBError err; - mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; - err = ::task_info(task, TASK_BASIC_INFO, (task_info_t)info, &count); - const bool log_process = DNBLogCheckLogBit(LOG_TASK); - if (log_process || err.Fail()) - err.LogThreaded("::task_info ( target_task = 0x%4.4x, flavor = " - "TASK_BASIC_INFO, task_info_out => %p, task_info_outCnt => " - "%u )", - task, info, count); - if (DNBLogCheckLogBit(LOG_TASK) && DNBLogCheckLogBit(LOG_VERBOSE) && - err.Success()) { - float user = (float)info->user_time.seconds + - (float)info->user_time.microseconds / 1000000.0f; - float system = (float)info->user_time.seconds + - (float)info->user_time.microseconds / 1000000.0f; - DNBLogThreaded("task_basic_info = { suspend_count = %i, virtual_size = " - "0x%8.8llx, resident_size = 0x%8.8llx, user_time = %f, " - "system_time = %f }", - info->suspend_count, (uint64_t)info->virtual_size, - (uint64_t)info->resident_size, user, system); - } - return err.Status(); -} - -//---------------------------------------------------------------------- -// MachTask::IsValid -// -// Returns true if a task is a valid task port for a current process. -//---------------------------------------------------------------------- -bool MachTask::IsValid() const { return MachTask::IsValid(TaskPort()); } - -//---------------------------------------------------------------------- -// MachTask::IsValid -// -// Returns true if a task is a valid task port for a current process. -//---------------------------------------------------------------------- -bool MachTask::IsValid(task_t task) { - if (task != TASK_NULL) { - struct task_basic_info task_info; - return BasicInfo(task, &task_info) == KERN_SUCCESS; - } - return false; -} - -bool MachTask::StartExceptionThread(DNBError &err) { - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); - - task_t task = TaskPortForProcessID(err); - if (MachTask::IsValid(task)) { - // Got the mach port for the current process - mach_port_t task_self = mach_task_self(); - - // Allocate an exception port that we will use to track our child process - err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, - &m_exception_port); - if (err.Fail()) - return false; - - // Add the ability to send messages on the new exception port - err = ::mach_port_insert_right(task_self, m_exception_port, - m_exception_port, MACH_MSG_TYPE_MAKE_SEND); - if (err.Fail()) - return false; - - // Save the original state of the exception ports for our child process - SaveExceptionPortInfo(); - - // We weren't able to save the info for our exception ports, we must stop... - if (m_exc_port_info.mask == 0) { - err.SetErrorString("failed to get exception port info"); - return false; - } - - // Set the ability to get all exceptions on this port - err = ::task_set_exception_ports( - task, m_exc_port_info.mask, m_exception_port, - EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { - err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior " - "= 0x%8.8x, new_flavor = 0x%8.8x )", - task, m_exc_port_info.mask, m_exception_port, - (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), - THREAD_STATE_NONE); - } - - if (err.Fail()) - return false; - - // Create the exception thread - err = ::pthread_create(&m_exception_thread, NULL, MachTask::ExceptionThread, - this); - return err.Success(); - } else { - DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", - __FUNCTION__); - } - return false; -} - -kern_return_t MachTask::ShutDownExcecptionThread() { - DNBError err; - - err = RestoreExceptionPortInfo(); - - // NULL our our exception port and let our exception thread exit - mach_port_t exception_port = m_exception_port; - m_exception_port = 0; - - err.SetError(::pthread_cancel(m_exception_thread), DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::pthread_cancel ( thread = %p )", m_exception_thread); - - err.SetError(::pthread_join(m_exception_thread, NULL), DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::pthread_join ( thread = %p, value_ptr = NULL)", - m_exception_thread); - - // Deallocate our exception port that we used to track our child process - mach_port_t task_self = mach_task_self(); - err = ::mach_port_deallocate(task_self, exception_port); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::mach_port_deallocate ( task = 0x%4.4x, name = 0x%4.4x )", - task_self, exception_port); - - return err.Status(); -} - -void *MachTask::ExceptionThread(void *arg) { - if (arg == NULL) - return NULL; - - MachTask *mach_task = (MachTask *)arg; - MachProcess *mach_proc = mach_task->Process(); - DNBLogThreadedIf(LOG_EXCEPTIONS, - "MachTask::%s ( arg = %p ) starting thread...", __FUNCTION__, - arg); - -#if defined(__APPLE__) - pthread_setname_np("exception monitoring thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } -#endif -#endif - - // We keep a count of the number of consecutive exceptions received so - // we know to grab all exceptions without a timeout. We do this to get a - // bunch of related exceptions on our exception port so we can process - // then together. When we have multiple threads, we can get an exception - // per thread and they will come in consecutively. The main loop in this - // thread can stop periodically if needed to service things related to this - // process. - // flag set in the options, so we will wait forever for an exception on - // our exception port. After we get one exception, we then will use the - // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current - // exceptions for our process. After we have received the last pending - // exception, we will get a timeout which enables us to then notify - // our main thread that we have an exception bundle available. We then wait - // for the main thread to tell this exception thread to start trying to get - // exceptions messages again and we start again with a mach_msg read with - // infinite timeout. - uint32_t num_exceptions_received = 0; - DNBError err; - task_t task = mach_task->TaskPort(); - mach_msg_timeout_t periodic_timeout = 0; - -#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) - mach_msg_timeout_t watchdog_elapsed = 0; - mach_msg_timeout_t watchdog_timeout = 60 * 1000; - pid_t pid = mach_proc->ProcessID(); - CFReleaser<SBSWatchdogAssertionRef> watchdog; - - if (mach_proc->ProcessUsingSpringBoard()) { - // Request a renewal for every 60 seconds if we attached using SpringBoard - watchdog.reset(::SBSWatchdogAssertionCreateForPID(NULL, pid, 60)); - DNBLogThreadedIf( - LOG_TASK, "::SBSWatchdogAssertionCreateForPID (NULL, %4.4x, 60 ) => %p", - pid, watchdog.get()); - - if (watchdog.get()) { - ::SBSWatchdogAssertionRenew(watchdog.get()); - - CFTimeInterval watchdogRenewalInterval = - ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get()); - DNBLogThreadedIf( - LOG_TASK, - "::SBSWatchdogAssertionGetRenewalInterval ( %p ) => %g seconds", - watchdog.get(), watchdogRenewalInterval); - if (watchdogRenewalInterval > 0.0) { - watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000; - if (watchdog_timeout > 3000) - watchdog_timeout -= 1000; // Give us a second to renew our timeout - else if (watchdog_timeout > 1000) - watchdog_timeout -= - 250; // Give us a quarter of a second to renew our timeout - } - } - if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout) - periodic_timeout = watchdog_timeout; - } -#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - -#ifdef WITH_BKS - CFReleaser<BKSWatchdogAssertionRef> watchdog; - if (mach_proc->ProcessUsingBackBoard()) { - pid_t pid = mach_proc->ProcessID(); - CFAllocatorRef alloc = kCFAllocatorDefault; - watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid)); - } -#endif // #ifdef WITH_BKS - - while (mach_task->ExceptionPortIsValid()) { - ::pthread_testcancel(); - - MachException::Message exception_message; - - if (num_exceptions_received > 0) { - // No timeout, just receive as many exceptions as we can since we already - // have one and we want - // to get all currently available exceptions for this task - err = exception_message.Receive( - mach_task->ExceptionPort(), - MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0); - } else if (periodic_timeout > 0) { - // We need to stop periodically in this loop, so try and get a mach - // message with a valid timeout (ms) - err = exception_message.Receive(mach_task->ExceptionPort(), - MACH_RCV_MSG | MACH_RCV_INTERRUPT | - MACH_RCV_TIMEOUT, - periodic_timeout); - } else { - // We don't need to parse all current exceptions or stop periodically, - // just wait for an exception forever. - err = exception_message.Receive(mach_task->ExceptionPort(), - MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0); - } - - if (err.Status() == MACH_RCV_INTERRUPTED) { - // If we have no task port we should exit this thread - if (!mach_task->ExceptionPortIsValid()) { - DNBLogThreadedIf(LOG_EXCEPTIONS, "thread cancelled..."); - break; - } - - // Make sure our task is still valid - if (MachTask::IsValid(task)) { - // Task is still ok - DNBLogThreadedIf(LOG_EXCEPTIONS, - "interrupted, but task still valid, continuing..."); - continue; - } else { - DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); - mach_proc->SetState(eStateExited); - // Our task has died, exit the thread. - break; - } - } else if (err.Status() == MACH_RCV_TIMED_OUT) { - if (num_exceptions_received > 0) { - // We were receiving all current exceptions with a timeout of zero - // it is time to go back to our normal looping mode - num_exceptions_received = 0; - - // Notify our main thread we have a complete exception message - // bundle available and get the possibly updated task port back - // from the process in case we exec'ed and our task port changed - task = mach_proc->ExceptionMessageBundleComplete(); - - // in case we use a timeout value when getting exceptions... - // Make sure our task is still valid - if (MachTask::IsValid(task)) { - // Task is still ok - DNBLogThreadedIf(LOG_EXCEPTIONS, "got a timeout, continuing..."); - continue; - } else { - DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); - mach_proc->SetState(eStateExited); - // Our task has died, exit the thread. - break; - } - } - -#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) - if (watchdog.get()) { - watchdog_elapsed += periodic_timeout; - if (watchdog_elapsed >= watchdog_timeout) { - DNBLogThreadedIf(LOG_TASK, "SBSWatchdogAssertionRenew ( %p )", - watchdog.get()); - ::SBSWatchdogAssertionRenew(watchdog.get()); - watchdog_elapsed = 0; - } - } -#endif - } else if (err.Status() != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_EXCEPTIONS, "got some other error, do something " - "about it??? nah, continuing for " - "now..."); - // TODO: notify of error? - } else { - if (exception_message.CatchExceptionRaise(task)) { - if (exception_message.state.task_port != task) { - if (exception_message.state.IsValid()) { - // We exec'ed and our task port changed on us. - DNBLogThreadedIf(LOG_EXCEPTIONS, - "task port changed from 0x%4.4x to 0x%4.4x", - task, exception_message.state.task_port); - task = exception_message.state.task_port; - mach_task->TaskPortChanged(exception_message.state.task_port); - } - } - ++num_exceptions_received; - mach_proc->ExceptionMessageReceived(exception_message); - } - } - } - -#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) - if (watchdog.get()) { - // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel - // when we - // all are up and running on systems that support it. The SBS framework has - // a #define - // that will forward SBSWatchdogAssertionRelease to - // SBSWatchdogAssertionCancel for now - // so it should still build either way. - DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)", - watchdog.get()); - ::SBSWatchdogAssertionRelease(watchdog.get()); - } -#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s (%p): thread exiting...", - __FUNCTION__, arg); - return NULL; -} - -// So the TASK_DYLD_INFO used to just return the address of the all image infos -// as a single member called "all_image_info". Then someone decided it would be -// a good idea to rename this first member to "all_image_info_addr" and add a -// size member called "all_image_info_size". This of course can not be detected -// using code or #defines. So to hack around this problem, we define our own -// version of the TASK_DYLD_INFO structure so we can guarantee what is inside -// it. - -struct hack_task_dyld_info { - mach_vm_address_t all_image_info_addr; - mach_vm_size_t all_image_info_size; -}; - -nub_addr_t MachTask::GetDYLDAllImageInfosAddress(DNBError &err) { - struct hack_task_dyld_info dyld_info; - mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; - // Make sure that COUNT isn't bigger than our hacked up struct - // hack_task_dyld_info. - // If it is, then make COUNT smaller to match. - if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) - count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)); - - task_t task = TaskPortForProcessID(err); - if (err.Success()) { - err = ::task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); - if (err.Success()) { - // We now have the address of the all image infos structure - return dyld_info.all_image_info_addr; - } - } - return INVALID_NUB_ADDRESS; -} - -//---------------------------------------------------------------------- -// MachTask::AllocateMemory -//---------------------------------------------------------------------- -nub_addr_t MachTask::AllocateMemory(size_t size, uint32_t permissions) { - mach_vm_address_t addr; - task_t task = TaskPort(); - if (task == TASK_NULL) - return INVALID_NUB_ADDRESS; - - DNBError err; - err = ::mach_vm_allocate(task, &addr, size, TRUE); - if (err.Status() == KERN_SUCCESS) { - // Set the protections: - vm_prot_t mach_prot = VM_PROT_NONE; - if (permissions & eMemoryPermissionsReadable) - mach_prot |= VM_PROT_READ; - if (permissions & eMemoryPermissionsWritable) - mach_prot |= VM_PROT_WRITE; - if (permissions & eMemoryPermissionsExecutable) - mach_prot |= VM_PROT_EXECUTE; - - err = ::mach_vm_protect(task, addr, size, 0, mach_prot); - if (err.Status() == KERN_SUCCESS) { - m_allocations.insert(std::make_pair(addr, size)); - return addr; - } - ::mach_vm_deallocate(task, addr, size); - } - return INVALID_NUB_ADDRESS; -} - -//---------------------------------------------------------------------- -// MachTask::DeallocateMemory -//---------------------------------------------------------------------- -nub_bool_t MachTask::DeallocateMemory(nub_addr_t addr) { - task_t task = TaskPort(); - if (task == TASK_NULL) - return false; - - // We have to stash away sizes for the allocations... - allocation_collection::iterator pos, end = m_allocations.end(); - for (pos = m_allocations.begin(); pos != end; pos++) { - if ((*pos).first == addr) { - m_allocations.erase(pos); -#define ALWAYS_ZOMBIE_ALLOCATIONS 0 - if (ALWAYS_ZOMBIE_ALLOCATIONS || - getenv("DEBUGSERVER_ZOMBIE_ALLOCATIONS")) { - ::mach_vm_protect(task, (*pos).first, (*pos).second, 0, VM_PROT_NONE); - return true; - } else - return ::mach_vm_deallocate(task, (*pos).first, (*pos).second) == - KERN_SUCCESS; - } - } - return false; -} - -void MachTask::TaskPortChanged(task_t task) -{ - m_task = task; -} diff --git a/tools/debugserver/source/MacOSX/MachThread.cpp b/tools/debugserver/source/MacOSX/MachThread.cpp deleted file mode 100644 index 062e1c3d9edf..000000000000 --- a/tools/debugserver/source/MacOSX/MachThread.cpp +++ /dev/null @@ -1,783 +0,0 @@ -//===-- MachThread.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#include "MachThread.h" -#include "DNB.h" -#include "DNBLog.h" -#include "MachProcess.h" -#include "ThreadInfo.h" -#include <dlfcn.h> -#include <inttypes.h> -#include <mach/thread_policy.h> - -static uint32_t GetSequenceID() { - static uint32_t g_nextID = 0; - return ++g_nextID; -} - -MachThread::MachThread(MachProcess *process, bool is_64_bit, - uint64_t unique_thread_id, thread_t mach_port_num) - : m_process(process), m_unique_id(unique_thread_id), - m_mach_port_number(mach_port_num), m_seq_id(GetSequenceID()), - m_state(eStateUnloaded), m_state_mutex(PTHREAD_MUTEX_RECURSIVE), - m_suspend_count(0), m_stop_exception(), - m_arch_ap(DNBArchProtocol::Create(this)), m_reg_sets(NULL), - m_num_reg_sets(0), m_ident_info(), m_proc_threadinfo(), - m_dispatch_queue_name(), m_is_64_bit(is_64_bit), - m_pthread_qos_class_decode(nullptr) { - nub_size_t num_reg_sets = 0; - m_reg_sets = m_arch_ap->GetRegisterSetInfo(&num_reg_sets); - m_num_reg_sets = num_reg_sets; - - m_pthread_qos_class_decode = - (unsigned int (*)(unsigned long, int *, unsigned long *))dlsym( - RTLD_DEFAULT, "_pthread_qos_class_decode"); - - // Get the thread state so we know if a thread is in a state where we can't - // muck with it and also so we get the suspend count correct in case it was - // already suspended - GetBasicInfo(); - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, - "MachThread::MachThread ( process = %p, tid = 0x%8.8" PRIx64 - ", seq_id = %u )", - reinterpret_cast<void *>(&m_process), m_unique_id, m_seq_id); -} - -MachThread::~MachThread() { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, - "MachThread::~MachThread() for tid = 0x%8.8" PRIx64 " (%u)", - m_unique_id, m_seq_id); -} - -void MachThread::Suspend() { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", - __FUNCTION__); - if (MachPortNumberIsValid(m_mach_port_number)) { - DNBError err(::thread_suspend(m_mach_port_number), DNBError::MachKernel); - if (err.Success()) - m_suspend_count++; - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number); - } -} - -void MachThread::Resume(bool others_stopped) { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", - __FUNCTION__); - if (MachPortNumberIsValid(m_mach_port_number)) { - SetSuspendCountBeforeResume(others_stopped); - } -} - -bool MachThread::SetSuspendCountBeforeResume(bool others_stopped) { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", - __FUNCTION__); - DNBError err; - if (!MachPortNumberIsValid(m_mach_port_number)) - return false; - - integer_t times_to_resume; - - if (others_stopped) { - if (GetBasicInfo()) { - times_to_resume = m_basic_info.suspend_count; - m_suspend_count = -(times_to_resume - m_suspend_count); - } else - times_to_resume = 0; - } else { - times_to_resume = m_suspend_count; - m_suspend_count = 0; - } - - if (times_to_resume > 0) { - while (times_to_resume > 0) { - err = ::thread_resume(m_mach_port_number); - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); - if (err.Success()) - --times_to_resume; - else { - if (GetBasicInfo()) - times_to_resume = m_basic_info.suspend_count; - else - times_to_resume = 0; - } - } - } - return true; -} - -bool MachThread::RestoreSuspendCountAfterStop() { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", - __FUNCTION__); - DNBError err; - if (!MachPortNumberIsValid(m_mach_port_number)) - return false; - - if (m_suspend_count > 0) { - while (m_suspend_count > 0) { - err = ::thread_resume(m_mach_port_number); - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); - if (err.Success()) - --m_suspend_count; - else { - if (GetBasicInfo()) - m_suspend_count = m_basic_info.suspend_count; - else - m_suspend_count = 0; - return false; // ??? - } - } - } else if (m_suspend_count < 0) { - while (m_suspend_count < 0) { - err = ::thread_suspend(m_mach_port_number); - if (err.Success()) - ++m_suspend_count; - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) { - err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", - m_mach_port_number); - return false; - } - } - } - return true; -} - -const char *MachThread::GetBasicInfoAsString() const { - static char g_basic_info_string[1024]; - struct thread_basic_info basicInfo; - - if (GetBasicInfo(m_mach_port_number, &basicInfo)) { - - // char run_state_str[32]; - // size_t run_state_str_size = sizeof(run_state_str); - // switch (basicInfo.run_state) - // { - // case TH_STATE_RUNNING: strlcpy(run_state_str, "running", - // run_state_str_size); break; - // case TH_STATE_STOPPED: strlcpy(run_state_str, "stopped", - // run_state_str_size); break; - // case TH_STATE_WAITING: strlcpy(run_state_str, "waiting", - // run_state_str_size); break; - // case TH_STATE_UNINTERRUPTIBLE: strlcpy(run_state_str, - // "uninterruptible", run_state_str_size); break; - // case TH_STATE_HALTED: strlcpy(run_state_str, "halted", - // run_state_str_size); break; - // default: snprintf(run_state_str, - // run_state_str_size, "%d", basicInfo.run_state); break; // ??? - // } - float user = (float)basicInfo.user_time.seconds + - (float)basicInfo.user_time.microseconds / 1000000.0f; - float system = (float)basicInfo.user_time.seconds + - (float)basicInfo.user_time.microseconds / 1000000.0f; - snprintf(g_basic_info_string, sizeof(g_basic_info_string), - "Thread 0x%8.8" PRIx64 ": user=%f system=%f cpu=%d sleep_time=%d", - m_unique_id, user, system, basicInfo.cpu_usage, - basicInfo.sleep_time); - - return g_basic_info_string; - } - return NULL; -} - -// Finds the Mach port number for a given thread in the inferior process' port -// namespace. -thread_t MachThread::InferiorThreadID() const { - mach_msg_type_number_t i; - mach_port_name_array_t names; - mach_port_type_array_t types; - mach_msg_type_number_t ncount, tcount; - thread_t inferior_tid = INVALID_NUB_THREAD; - task_t my_task = ::mach_task_self(); - task_t task = m_process->Task().TaskPort(); - - kern_return_t kret = - ::mach_port_names(task, &names, &ncount, &types, &tcount); - if (kret == KERN_SUCCESS) { - - for (i = 0; i < ncount; i++) { - mach_port_t my_name; - mach_msg_type_name_t my_type; - - kret = ::mach_port_extract_right(task, names[i], MACH_MSG_TYPE_COPY_SEND, - &my_name, &my_type); - if (kret == KERN_SUCCESS) { - ::mach_port_deallocate(my_task, my_name); - if (my_name == m_mach_port_number) { - inferior_tid = names[i]; - break; - } - } - } - // Free up the names and types - ::vm_deallocate(my_task, (vm_address_t)names, - ncount * sizeof(mach_port_name_t)); - ::vm_deallocate(my_task, (vm_address_t)types, - tcount * sizeof(mach_port_type_t)); - } - return inferior_tid; -} - -bool MachThread::IsUserReady() { - if (m_basic_info.run_state == 0) - GetBasicInfo(); - - switch (m_basic_info.run_state) { - default: - case TH_STATE_UNINTERRUPTIBLE: - break; - - case TH_STATE_RUNNING: - case TH_STATE_STOPPED: - case TH_STATE_WAITING: - case TH_STATE_HALTED: - return true; - } - return false; -} - -struct thread_basic_info *MachThread::GetBasicInfo() { - if (MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info)) - return &m_basic_info; - return NULL; -} - -bool MachThread::GetBasicInfo(thread_t thread, - struct thread_basic_info *basicInfoPtr) { - if (MachPortNumberIsValid(thread)) { - unsigned int info_count = THREAD_BASIC_INFO_COUNT; - kern_return_t err = ::thread_info(thread, THREAD_BASIC_INFO, - (thread_info_t)basicInfoPtr, &info_count); - if (err == KERN_SUCCESS) - return true; - } - ::memset(basicInfoPtr, 0, sizeof(struct thread_basic_info)); - return false; -} - -bool MachThread::ThreadIDIsValid(uint64_t thread) { return thread != 0; } - -bool MachThread::MachPortNumberIsValid(thread_t thread) { - return thread != THREAD_NULL; -} - -bool MachThread::GetRegisterState(int flavor, bool force) { - return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; -} - -bool MachThread::SetRegisterState(int flavor) { - return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; -} - -uint64_t MachThread::GetPC(uint64_t failValue) { - // Get program counter - return m_arch_ap->GetPC(failValue); -} - -bool MachThread::SetPC(uint64_t value) { - // Set program counter - return m_arch_ap->SetPC(value); -} - -uint64_t MachThread::GetSP(uint64_t failValue) { - // Get stack pointer - return m_arch_ap->GetSP(failValue); -} - -nub_process_t MachThread::ProcessID() const { - if (m_process) - return m_process->ProcessID(); - return INVALID_NUB_PROCESS; -} - -void MachThread::Dump(uint32_t index) { - const char *thread_run_state = NULL; - - switch (m_basic_info.run_state) { - case TH_STATE_RUNNING: - thread_run_state = "running"; - break; // 1 thread is running normally - case TH_STATE_STOPPED: - thread_run_state = "stopped"; - break; // 2 thread is stopped - case TH_STATE_WAITING: - thread_run_state = "waiting"; - break; // 3 thread is waiting normally - case TH_STATE_UNINTERRUPTIBLE: - thread_run_state = "uninter"; - break; // 4 thread is in an uninterruptible wait - case TH_STATE_HALTED: - thread_run_state = "halted "; - break; // 5 thread is halted at a - default: - thread_run_state = "???"; - break; - } - - DNBLogThreaded( - "[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 - ", sp: 0x%16.16" PRIx64 - ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: " - "%2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", - index, m_seq_id, m_unique_id, GetPC(INVALID_NUB_ADDRESS), - GetSP(INVALID_NUB_ADDRESS), m_basic_info.user_time.seconds, - m_basic_info.user_time.microseconds, m_basic_info.system_time.seconds, - m_basic_info.system_time.microseconds, m_basic_info.cpu_usage, - m_basic_info.policy, m_basic_info.run_state, thread_run_state, - m_basic_info.flags, m_basic_info.suspend_count, m_suspend_count, - m_basic_info.sleep_time); - // DumpRegisterState(0); -} - -void MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, - bool others_stopped) { - if (thread_action->addr != INVALID_NUB_ADDRESS) - SetPC(thread_action->addr); - - SetState(thread_action->state); - switch (thread_action->state) { - case eStateStopped: - case eStateSuspended: - assert(others_stopped == false); - Suspend(); - break; - - case eStateRunning: - case eStateStepping: - Resume(others_stopped); - break; - default: - break; - } - m_arch_ap->ThreadWillResume(); - m_stop_exception.Clear(); -} - -DNBBreakpoint *MachThread::CurrentBreakpoint() { - return m_process->Breakpoints().FindByAddress(GetPC()); -} - -bool MachThread::ShouldStop(bool &step_more) { - // See if this thread is at a breakpoint? - DNBBreakpoint *bp = CurrentBreakpoint(); - - if (bp) { - // This thread is sitting at a breakpoint, ask the breakpoint - // if we should be stopping here. - return true; - } else { - if (m_arch_ap->StepNotComplete()) { - step_more = true; - return false; - } - // The thread state is used to let us know what the thread was - // trying to do. MachThread::ThreadWillResume() will set the - // thread state to various values depending if the thread was - // the current thread and if it was to be single stepped, or - // resumed. - if (GetState() == eStateRunning) { - // If our state is running, then we should continue as we are in - // the process of stepping over a breakpoint. - return false; - } else { - // Stop if we have any kind of valid exception for this - // thread. - if (GetStopException().IsValid()) - return true; - } - } - return false; -} -bool MachThread::IsStepping() { return GetState() == eStateStepping; } - -bool MachThread::ThreadDidStop() { - // This thread has existed prior to resuming under debug nub control, - // and has just been stopped. Do any cleanup that needs to be done - // after running. - - // The thread state and breakpoint will still have the same values - // as they had prior to resuming the thread, so it makes it easy to check - // if we were trying to step a thread, or we tried to resume while being - // at a breakpoint. - - // When this method gets called, the process state is still in the - // state it was in while running so we can act accordingly. - m_arch_ap->ThreadDidStop(); - - // We may have suspended this thread so the primary thread could step - // without worrying about race conditions, so lets restore our suspend - // count. - RestoreSuspendCountAfterStop(); - - // Update the basic information for a thread - MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); - - if (m_basic_info.suspend_count > 0) - SetState(eStateSuspended); - else - SetState(eStateStopped); - return true; -} - -bool MachThread::NotifyException(MachException::Data &exc) { - // Allow the arch specific protocol to process (MachException::Data &)exc - // first before possible reassignment of m_stop_exception with exc. - // See also MachThread::GetStopException(). - bool handled = m_arch_ap->NotifyException(exc); - - if (m_stop_exception.IsValid()) { - // We may have more than one exception for a thread, but we need to - // only remember the one that we will say is the reason we stopped. - // We may have been single stepping and also gotten a signal exception, - // so just remember the most pertinent one. - if (m_stop_exception.IsBreakpoint()) - m_stop_exception = exc; - } else { - m_stop_exception = exc; - } - - return handled; -} - -nub_state_t MachThread::GetState() { - // If any other threads access this we will need a mutex for it - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - return m_state; -} - -void MachThread::SetState(nub_state_t state) { - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - m_state = state; - DNBLogThreadedIf(LOG_THREAD, - "MachThread::SetState ( %s ) for tid = 0x%8.8" PRIx64 "", - DNBStateAsString(state), m_unique_id); -} - -nub_size_t MachThread::GetNumRegistersInSet(nub_size_t regSet) const { - if (regSet < m_num_reg_sets) - return m_reg_sets[regSet].num_registers; - return 0; -} - -const char *MachThread::GetRegisterSetName(nub_size_t regSet) const { - if (regSet < m_num_reg_sets) - return m_reg_sets[regSet].name; - return NULL; -} - -const DNBRegisterInfo *MachThread::GetRegisterInfo(nub_size_t regSet, - nub_size_t regIndex) const { - if (regSet < m_num_reg_sets) - if (regIndex < m_reg_sets[regSet].num_registers) - return &m_reg_sets[regSet].registers[regIndex]; - return NULL; -} -void MachThread::DumpRegisterState(nub_size_t regSet) { - if (regSet == REGISTER_SET_ALL) { - for (regSet = 1; regSet < m_num_reg_sets; regSet++) - DumpRegisterState(regSet); - } else { - if (m_arch_ap->RegisterSetStateIsValid((int)regSet)) { - const size_t numRegisters = GetNumRegistersInSet(regSet); - uint32_t regIndex = 0; - DNBRegisterValueClass reg; - for (regIndex = 0; regIndex < numRegisters; ++regIndex) { - if (m_arch_ap->GetRegisterValue((uint32_t)regSet, regIndex, ®)) { - reg.Dump(NULL, NULL); - } - } - } else { - DNBLog("%s: registers are not currently valid.", - GetRegisterSetName(regSet)); - } - } -} - -const DNBRegisterSetInfo * -MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets) const { - *num_reg_sets = m_num_reg_sets; - return &m_reg_sets[0]; -} - -bool MachThread::GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) { - return m_arch_ap->GetRegisterValue(set, reg, value); -} - -bool MachThread::SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) { - return m_arch_ap->SetRegisterValue(set, reg, value); -} - -nub_size_t MachThread::GetRegisterContext(void *buf, nub_size_t buf_len) { - return m_arch_ap->GetRegisterContext(buf, buf_len); -} - -nub_size_t MachThread::SetRegisterContext(const void *buf, nub_size_t buf_len) { - return m_arch_ap->SetRegisterContext(buf, buf_len); -} - -uint32_t MachThread::SaveRegisterState() { - return m_arch_ap->SaveRegisterState(); -} -bool MachThread::RestoreRegisterState(uint32_t save_id) { - return m_arch_ap->RestoreRegisterState(save_id); -} - -uint32_t MachThread::EnableHardwareBreakpoint(const DNBBreakpoint *bp) { - if (bp != NULL && bp->IsBreakpoint()) - return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); - return INVALID_NUB_HW_INDEX; -} - -uint32_t MachThread::EnableHardwareWatchpoint(const DNBBreakpoint *wp, - bool also_set_on_task) { - if (wp != NULL && wp->IsWatchpoint()) - return m_arch_ap->EnableHardwareWatchpoint( - wp->Address(), wp->ByteSize(), wp->WatchpointRead(), - wp->WatchpointWrite(), also_set_on_task); - return INVALID_NUB_HW_INDEX; -} - -bool MachThread::RollbackTransForHWP() { - return m_arch_ap->RollbackTransForHWP(); -} - -bool MachThread::FinishTransForHWP() { return m_arch_ap->FinishTransForHWP(); } - -bool MachThread::DisableHardwareBreakpoint(const DNBBreakpoint *bp) { - if (bp != NULL && bp->IsHardware()) - return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); - return false; -} - -bool MachThread::DisableHardwareWatchpoint(const DNBBreakpoint *wp, - bool also_set_on_task) { - if (wp != NULL && wp->IsHardware()) - return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex(), - also_set_on_task); - return false; -} - -uint32_t MachThread::NumSupportedHardwareWatchpoints() const { - return m_arch_ap->NumSupportedHardwareWatchpoints(); -} - -bool MachThread::GetIdentifierInfo() { - // Don't try to get the thread info once and cache it for the life of the - // thread. It changes over time, for instance - // if the thread name changes, then the thread_handle also changes... So you - // have to refetch it every time. - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - kern_return_t kret = ::thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t)&m_ident_info, &count); - return kret == KERN_SUCCESS; - - return false; -} - -const char *MachThread::GetName() { - if (GetIdentifierInfo()) { - int len = ::proc_pidinfo(m_process->ProcessID(), PROC_PIDTHREADINFO, - m_ident_info.thread_handle, &m_proc_threadinfo, - sizeof(m_proc_threadinfo)); - - if (len && m_proc_threadinfo.pth_name[0]) - return m_proc_threadinfo.pth_name; - } - return NULL; -} - -uint64_t -MachThread::GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id) { - kern_return_t kr; - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info(mach_port_id, THREAD_IDENTIFIER_INFO, (thread_info_t)&tident, - &tident_count); - if (kr != KERN_SUCCESS) { - return mach_port_id; - } - return tident.thread_id; -} - -nub_addr_t MachThread::GetPThreadT() { - nub_addr_t pthread_t_value = INVALID_NUB_ADDRESS; - if (MachPortNumberIsValid(m_mach_port_number)) { - kern_return_t kr; - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t)&tident, &tident_count); - if (kr == KERN_SUCCESS) { - // Dereference thread_handle to get the pthread_t value for this thread. - if (m_is_64_bit) { - uint64_t addr; - if (m_process->ReadMemory(tident.thread_handle, 8, &addr) == 8) { - if (addr != 0) { - pthread_t_value = addr; - } - } - } else { - uint32_t addr; - if (m_process->ReadMemory(tident.thread_handle, 4, &addr) == 4) { - if (addr != 0) { - pthread_t_value = addr; - } - } - } - } - } - return pthread_t_value; -} - -// Return this thread's TSD (Thread Specific Data) address. -// This is computed based on this thread's pthread_t value. -// -// We compute the TSD from the pthread_t by one of two methods. -// -// If plo_pthread_tsd_base_offset is non-zero, this is a simple offset that we -// add to -// the pthread_t to get the TSD base address. -// -// Else we read a pointer from memory at pthread_t + -// plo_pthread_tsd_base_address_offset and -// that gives us the TSD address. -// -// These plo_pthread_tsd_base values must be read out of libpthread by lldb & -// provided to debugserver. - -nub_addr_t -MachThread::GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size) { - nub_addr_t tsd_addr = INVALID_NUB_ADDRESS; - nub_addr_t pthread_t_value = GetPThreadT(); - if (plo_pthread_tsd_base_offset != 0 && - plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS) { - tsd_addr = pthread_t_value + plo_pthread_tsd_base_offset; - } else { - if (plo_pthread_tsd_entry_size == 4) { - uint32_t addr = 0; - if (m_process->ReadMemory(pthread_t_value + - plo_pthread_tsd_base_address_offset, - 4, &addr) == 4) { - if (addr != 0) { - tsd_addr = addr; - } - } - } - if (plo_pthread_tsd_entry_size == 4) { - uint64_t addr = 0; - if (m_process->ReadMemory(pthread_t_value + - plo_pthread_tsd_base_address_offset, - 8, &addr) == 8) { - if (addr != 0) { - tsd_addr = addr; - } - } - } - } - return tsd_addr; -} - -nub_addr_t MachThread::GetDispatchQueueT() { - nub_addr_t dispatch_queue_t_value = INVALID_NUB_ADDRESS; - if (MachPortNumberIsValid(m_mach_port_number)) { - kern_return_t kr; - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t)&tident, &tident_count); - if (kr == KERN_SUCCESS && tident.dispatch_qaddr != 0 && - tident.dispatch_qaddr != INVALID_NUB_ADDRESS) { - // Dereference dispatch_qaddr to get the dispatch_queue_t value for this - // thread's queue, if any. - if (m_is_64_bit) { - uint64_t addr; - if (m_process->ReadMemory(tident.dispatch_qaddr, 8, &addr) == 8) { - if (addr != 0) - dispatch_queue_t_value = addr; - } - } else { - uint32_t addr; - if (m_process->ReadMemory(tident.dispatch_qaddr, 4, &addr) == 4) { - if (addr != 0) - dispatch_queue_t_value = addr; - } - } - } - } - return dispatch_queue_t_value; -} - -ThreadInfo::QoS MachThread::GetRequestedQoS(nub_addr_t tsd, - uint64_t dti_qos_class_index) { - ThreadInfo::QoS qos_value; - if (MachPortNumberIsValid(m_mach_port_number) && - m_pthread_qos_class_decode != nullptr) { - uint64_t pthread_priority_value = 0; - if (m_is_64_bit) { - uint64_t pri; - if (m_process->ReadMemory(tsd + (dti_qos_class_index * 8), 8, &pri) == - 8) { - pthread_priority_value = pri; - } - } else { - uint32_t pri; - if (m_process->ReadMemory(tsd + (dti_qos_class_index * 4), 4, &pri) == - 4) { - pthread_priority_value = pri; - } - } - - uint32_t requested_qos = - m_pthread_qos_class_decode(pthread_priority_value, NULL, NULL); - - switch (requested_qos) { - // These constants from <pthread/qos.h> - case 0x21: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_USER_INTERACTIVE"; - qos_value.printable_name = "User Interactive"; - break; - case 0x19: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_USER_INITIATED"; - qos_value.printable_name = "User Initiated"; - break; - case 0x15: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_DEFAULT"; - qos_value.printable_name = "Default"; - break; - case 0x11: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_UTILITY"; - qos_value.printable_name = "Utility"; - break; - case 0x09: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_BACKGROUND"; - qos_value.printable_name = "Background"; - break; - case 0x00: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_UNSPECIFIED"; - qos_value.printable_name = "Unspecified"; - break; - } - } - return qos_value; -} diff --git a/tools/debugserver/source/MacOSX/MachThread.h b/tools/debugserver/source/MacOSX/MachThread.h deleted file mode 100644 index a98d8aa2b05c..000000000000 --- a/tools/debugserver/source/MacOSX/MachThread.h +++ /dev/null @@ -1,170 +0,0 @@ -//===-- MachThread.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachThread_h__ -#define __MachThread_h__ - -#include <string> -#include <vector> - -#include <libproc.h> -#include <mach/mach.h> -#include <pthread.h> -#include <sys/signal.h> - -#include "DNBArch.h" -#include "DNBRegisterInfo.h" -#include "MachException.h" -#include "PThreadCondition.h" -#include "PThreadMutex.h" - -#include "ThreadInfo.h" - -class DNBBreakpoint; -class MachProcess; -class MachThreadList; - -class MachThread { -public: - MachThread(MachProcess *process, bool is_64_bit, - uint64_t unique_thread_id = 0, thread_t mach_port_number = 0); - ~MachThread(); - - MachProcess *Process() { return m_process; } - const MachProcess *Process() const { return m_process; } - nub_process_t ProcessID() const; - void Dump(uint32_t index); - uint64_t ThreadID() const { return m_unique_id; } - thread_t MachPortNumber() const { return m_mach_port_number; } - thread_t InferiorThreadID() const; - - uint32_t SequenceID() const { return m_seq_id; } - static bool ThreadIDIsValid( - uint64_t thread); // The 64-bit system-wide unique thread identifier - static bool MachPortNumberIsValid(thread_t thread); // The mach port # for - // this thread in - // debugserver namespace - void Resume(bool others_stopped); - void Suspend(); - bool SetSuspendCountBeforeResume(bool others_stopped); - bool RestoreSuspendCountAfterStop(); - - bool GetRegisterState(int flavor, bool force); - bool SetRegisterState(int flavor); - uint64_t - GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter - bool SetPC(uint64_t value); // Set program counter - uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer - - DNBBreakpoint *CurrentBreakpoint(); - uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint); - uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint, - bool also_set_on_task); - bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint); - bool DisableHardwareWatchpoint(const DNBBreakpoint *watchpoint, - bool also_set_on_task); - uint32_t NumSupportedHardwareWatchpoints() const; - bool RollbackTransForHWP(); - bool FinishTransForHWP(); - - nub_state_t GetState(); - void SetState(nub_state_t state); - - void ThreadWillResume(const DNBThreadResumeAction *thread_action, - bool others_stopped = false); - bool ShouldStop(bool &step_more); - bool IsStepping(); - bool ThreadDidStop(); - bool NotifyException(MachException::Data &exc); - const MachException::Data &GetStopException() { return m_stop_exception; } - - nub_size_t GetNumRegistersInSet(nub_size_t regSet) const; - const char *GetRegisterSetName(nub_size_t regSet) const; - const DNBRegisterInfo *GetRegisterInfo(nub_size_t regSet, - nub_size_t regIndex) const; - void DumpRegisterState(nub_size_t regSet); - const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets) const; - bool GetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, - DNBRegisterValue *reg_value); - bool SetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, - const DNBRegisterValue *reg_value); - nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); - nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); - uint32_t SaveRegisterState(); - bool RestoreRegisterState(uint32_t save_id); - - void NotifyBreakpointChanged(const DNBBreakpoint *bp) {} - - bool IsUserReady(); - struct thread_basic_info *GetBasicInfo(); - const char *GetBasicInfoAsString() const; - const char *GetName(); - - DNBArchProtocol *GetArchProtocol() { return m_arch_ap.get(); } - - ThreadInfo::QoS GetRequestedQoS(nub_addr_t tsd, uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT(); - nub_addr_t GetDispatchQueueT(); - nub_addr_t - GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size); - - static uint64_t GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id); - -protected: - static bool GetBasicInfo(thread_t threadID, - struct thread_basic_info *basic_info); - - bool GetIdentifierInfo(); - - // const char * - // GetDispatchQueueName(); - // - MachProcess *m_process; // The process that owns this thread - uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t) - thread_t m_mach_port_number; // The mach port # for this thread in debugserver - // namesp. - uint32_t m_seq_id; // A Sequential ID that increments with each new thread - nub_state_t m_state; // The state of our process - PThreadMutex m_state_mutex; // Multithreaded protection for m_state - struct thread_basic_info m_basic_info; // Basic information for a thread used - // to see if a thread is valid - int32_t m_suspend_count; // The current suspend count > 0 means we have - // suspended m_suspendCount times, - // < 0 means we have resumed it m_suspendCount - // times. - MachException::Data m_stop_exception; // The best exception that describes why - // this thread is stopped - std::unique_ptr<DNBArchProtocol> - m_arch_ap; // Arch specific information for register state and more - const DNBRegisterSetInfo - *m_reg_sets; // Register set information for this thread - nub_size_t m_num_reg_sets; - thread_identifier_info_data_t m_ident_info; - struct proc_threadinfo m_proc_threadinfo; - std::string m_dispatch_queue_name; - bool m_is_64_bit; - - // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *, - // unsigned long *); - unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *, - unsigned long *); - -private: - friend class MachThreadList; -}; - -typedef std::shared_ptr<MachThread> MachThreadSP; - -#endif diff --git a/tools/debugserver/source/MacOSX/MachThreadList.cpp b/tools/debugserver/source/MacOSX/MachThreadList.cpp deleted file mode 100644 index 05e9627b591b..000000000000 --- a/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ /dev/null @@ -1,582 +0,0 @@ -//===-- MachThreadList.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#include "MachThreadList.h" - -#include <inttypes.h> -#include <sys/sysctl.h> - -#include "DNBLog.h" -#include "DNBThreadResumeActions.h" -#include "MachProcess.h" - -MachThreadList::MachThreadList() - : m_threads(), m_threads_mutex(PTHREAD_MUTEX_RECURSIVE), - m_is_64_bit(false) {} - -MachThreadList::~MachThreadList() {} - -nub_state_t MachThreadList::GetState(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetState(); - return eStateInvalid; -} - -const char *MachThreadList::GetName(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetName(); - return NULL; -} - -ThreadInfo::QoS MachThreadList::GetRequestedQoS(nub_thread_t tid, - nub_addr_t tsd, - uint64_t dti_qos_class_index) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); - return ThreadInfo::QoS(); -} - -nub_addr_t MachThreadList::GetPThreadT(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetPThreadT(); - return INVALID_NUB_ADDRESS; -} - -nub_addr_t MachThreadList::GetDispatchQueueT(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetDispatchQueueT(); - return INVALID_NUB_ADDRESS; -} - -nub_addr_t MachThreadList::GetTSDAddressForThread( - nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetTSDAddressForThread( - plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, - plo_pthread_tsd_entry_size); - return INVALID_NUB_ADDRESS; -} - -nub_thread_t MachThreadList::SetCurrentThread(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) { - m_current_thread = thread_sp; - return tid; - } - return INVALID_NUB_THREAD; -} - -bool MachThreadList::GetThreadStoppedReason( - nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetStopException().GetStopInfo(stop_info); - return false; -} - -bool MachThreadList::GetIdentifierInfo( - nub_thread_t tid, thread_identifier_info_data_t *ident_info) { - thread_t mach_port_number = GetMachPortNumberByThreadID(tid); - - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - return ::thread_info(mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t)ident_info, &count) == KERN_SUCCESS; -} - -void MachThreadList::DumpThreadStoppedReason(nub_thread_t tid) const { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - thread_sp->GetStopException().DumpStopReason(); -} - -const char *MachThreadList::GetThreadInfo(nub_thread_t tid) const { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetBasicInfoAsString(); - return NULL; -} - -MachThreadSP MachThreadList::GetThreadByID(nub_thread_t tid) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) { - if (m_threads[idx]->ThreadID() == tid) { - thread_sp = m_threads[idx]; - break; - } - } - return thread_sp; -} - -MachThreadSP -MachThreadList::GetThreadByMachPortNumber(thread_t mach_port_number) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) { - if (m_threads[idx]->MachPortNumber() == mach_port_number) { - thread_sp = m_threads[idx]; - break; - } - } - return thread_sp; -} - -nub_thread_t -MachThreadList::GetThreadIDByMachPortNumber(thread_t mach_port_number) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) { - if (m_threads[idx]->MachPortNumber() == mach_port_number) { - return m_threads[idx]->ThreadID(); - } - } - return INVALID_NUB_THREAD; -} - -thread_t MachThreadList::GetMachPortNumberByThreadID( - nub_thread_t globally_unique_id) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) { - if (m_threads[idx]->ThreadID() == globally_unique_id) { - return m_threads[idx]->MachPortNumber(); - } - } - return 0; -} - -bool MachThreadList::GetRegisterValue(nub_thread_t tid, uint32_t set, - uint32_t reg, - DNBRegisterValue *reg_value) const { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetRegisterValue(set, reg, reg_value); - - return false; -} - -bool MachThreadList::SetRegisterValue(nub_thread_t tid, uint32_t set, - uint32_t reg, - const DNBRegisterValue *reg_value) const { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->SetRegisterValue(set, reg, reg_value); - - return false; -} - -nub_size_t MachThreadList::GetRegisterContext(nub_thread_t tid, void *buf, - size_t buf_len) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->GetRegisterContext(buf, buf_len); - return 0; -} - -nub_size_t MachThreadList::SetRegisterContext(nub_thread_t tid, const void *buf, - size_t buf_len) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->SetRegisterContext(buf, buf_len); - return 0; -} - -uint32_t MachThreadList::SaveRegisterState(nub_thread_t tid) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->SaveRegisterState(); - return 0; -} - -bool MachThreadList::RestoreRegisterState(nub_thread_t tid, uint32_t save_id) { - MachThreadSP thread_sp(GetThreadByID(tid)); - if (thread_sp) - return thread_sp->RestoreRegisterState(save_id); - return 0; -} - -nub_size_t MachThreadList::NumThreads() const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - return m_threads.size(); -} - -nub_thread_t MachThreadList::ThreadIDAtIndex(nub_size_t idx) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - if (idx < m_threads.size()) - return m_threads[idx]->ThreadID(); - return INVALID_NUB_THREAD; -} - -nub_thread_t MachThreadList::CurrentThreadID() { - MachThreadSP thread_sp; - CurrentThread(thread_sp); - if (thread_sp.get()) - return thread_sp->ThreadID(); - return INVALID_NUB_THREAD; -} - -bool MachThreadList::NotifyException(MachException::Data &exc) { - MachThreadSP thread_sp(GetThreadByMachPortNumber(exc.thread_port)); - if (thread_sp) { - thread_sp->NotifyException(exc); - return true; - } - return false; -} - -void MachThreadList::Clear() { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - m_threads.clear(); -} - -uint32_t -MachThreadList::UpdateThreadList(MachProcess *process, bool update, - MachThreadList::collection *new_threads) { - // locker will keep a mutex locked until it goes out of scope - DNBLogThreadedIf(LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, " - "update = %u) process stop count = %u", - process->ProcessID(), update, process->StopCount()); - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - - if (process->StopCount() == 0) { - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID()}; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, - &bufsize, NULL, 0) == 0 && - bufsize > 0) { - if (processInfo.kp_proc.p_flag & P_LP64) - m_is_64_bit = true; - } -#if defined(__i386__) || defined(__x86_64__) - if (m_is_64_bit) - DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); - else - DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); -#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - if (m_is_64_bit) - DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); - else - DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); -#endif - } - - if (m_threads.empty() || update) { - thread_array_t thread_list = NULL; - mach_msg_type_number_t thread_list_count = 0; - task_t task = process->Task().TaskPort(); - DNBError err(::task_threads(task, &thread_list, &thread_list_count), - DNBError::MachKernel); - - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, " - "thread_list_count => %u )", - task, thread_list, thread_list_count); - - if (err.Status() == KERN_SUCCESS && thread_list_count > 0) { - MachThreadList::collection currThreads; - size_t idx; - // Iterator through the current thread list and see which threads - // we already have in our list (keep them), which ones we don't - // (add them), and which ones are not around anymore (remove them). - for (idx = 0; idx < thread_list_count; ++idx) { - const thread_t mach_port_num = thread_list[idx]; - - uint64_t unique_thread_id = - MachThread::GetGloballyUniqueThreadIDForMachPortID(mach_port_num); - MachThreadSP thread_sp(GetThreadByID(unique_thread_id)); - if (thread_sp) { - // Keep the existing thread class - currThreads.push_back(thread_sp); - } else { - // We don't have this thread, lets add it. - thread_sp.reset(new MachThread(process, m_is_64_bit, unique_thread_id, - mach_port_num)); - - // Add the new thread regardless of its is user ready state... - // Make sure the thread is ready to be displayed and shown to users - // before we add this thread to our list... - if (thread_sp->IsUserReady()) { - if (new_threads) - new_threads->push_back(thread_sp); - - currThreads.push_back(thread_sp); - } - } - } - - m_threads.swap(currThreads); - m_current_thread.reset(); - - // Free the vm memory given to us by ::task_threads() - vm_size_t thread_list_size = - (vm_size_t)(thread_list_count * sizeof(thread_t)); - ::vm_deallocate(::mach_task_self(), (vm_address_t)thread_list, - thread_list_size); - } - } - return static_cast<uint32_t>(m_threads.size()); -} - -void MachThreadList::CurrentThread(MachThreadSP &thread_sp) { - // locker will keep a mutex locked until it goes out of scope - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - if (m_current_thread.get() == NULL) { - // Figure out which thread is going to be our current thread. - // This is currently done by finding the first thread in the list - // that has a valid exception. - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) { - if (m_threads[idx]->GetStopException().IsValid()) { - m_current_thread = m_threads[idx]; - break; - } - } - } - thread_sp = m_current_thread; -} - -void MachThreadList::Dump() const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) { - m_threads[idx]->Dump(idx); - } -} - -void MachThreadList::ProcessWillResume( - MachProcess *process, const DNBThreadResumeActions &thread_actions) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - - // Update our thread list, because sometimes libdispatch or the kernel - // will spawn threads while a task is suspended. - MachThreadList::collection new_threads; - - // First figure out if we were planning on running only one thread, and if so - // force that thread to resume. - bool run_one_thread; - nub_thread_t solo_thread = INVALID_NUB_THREAD; - if (thread_actions.GetSize() > 0 && - thread_actions.NumActionsWithState(eStateStepping) + - thread_actions.NumActionsWithState(eStateRunning) == - 1) { - run_one_thread = true; - const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); - size_t num_actions = thread_actions.GetSize(); - for (size_t i = 0; i < num_actions; i++, action_ptr++) { - if (action_ptr->state == eStateStepping || - action_ptr->state == eStateRunning) { - solo_thread = action_ptr->tid; - break; - } - } - } else - run_one_thread = false; - - UpdateThreadList(process, true, &new_threads); - - DNBThreadResumeAction resume_new_threads = {-1U, eStateRunning, 0, - INVALID_NUB_ADDRESS}; - // If we are planning to run only one thread, any new threads should be - // suspended. - if (run_one_thread) - resume_new_threads.state = eStateSuspended; - - const size_t num_new_threads = new_threads.size(); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) { - MachThread *thread = m_threads[idx].get(); - bool handled = false; - for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) { - if (thread == new_threads[new_idx].get()) { - thread->ThreadWillResume(&resume_new_threads); - handled = true; - break; - } - } - - if (!handled) { - const DNBThreadResumeAction *thread_action = - thread_actions.GetActionForThread(thread->ThreadID(), true); - // There must always be a thread action for every thread. - assert(thread_action); - bool others_stopped = false; - if (solo_thread == thread->ThreadID()) - others_stopped = true; - thread->ThreadWillResume(thread_action, others_stopped); - } - } - - if (new_threads.size()) { - for (uint32_t idx = 0; idx < num_new_threads; ++idx) { - DNBLogThreadedIf( - LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) " - "stop-id=%u, resuming newly discovered thread: " - "0x%8.8" PRIx64 ", thread-is-user-ready=%i)", - process->ProcessID(), process->StopCount(), - new_threads[idx]->ThreadID(), new_threads[idx]->IsUserReady()); - } - } -} - -uint32_t MachThreadList::ProcessDidStop(MachProcess *process) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - // Update our thread list - const uint32_t num_threads = UpdateThreadList(process, true); - for (uint32_t idx = 0; idx < num_threads; ++idx) { - m_threads[idx]->ThreadDidStop(); - } - return num_threads; -} - -//---------------------------------------------------------------------- -// Check each thread in our thread list to see if we should notify our -// client of the current halt in execution. -// -// Breakpoints can have callback functions associated with them than -// can return true to stop, or false to continue executing the inferior. -// -// RETURNS -// true if we should stop and notify our clients -// false if we should resume our child process and skip notification -//---------------------------------------------------------------------- -bool MachThreadList::ShouldStop(bool &step_more) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - uint32_t should_stop = false; - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) { - should_stop = m_threads[idx]->ShouldStop(step_more); - } - return should_stop; -} - -void MachThreadList::NotifyBreakpointChanged(const DNBBreakpoint *bp) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) { - m_threads[idx]->NotifyBreakpointChanged(bp); - } -} - -uint32_t -MachThreadList::EnableHardwareBreakpoint(const DNBBreakpoint *bp) const { - if (bp != NULL) { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->EnableHardwareBreakpoint(bp); - } - return INVALID_NUB_HW_INDEX; -} - -bool MachThreadList::DisableHardwareBreakpoint(const DNBBreakpoint *bp) const { - if (bp != NULL) { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->DisableHardwareBreakpoint(bp); - } - return false; -} - -// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> -// MachProcess::EnableWatchpoint() -// -> MachThreadList::EnableHardwareWatchpoint(). -uint32_t -MachThreadList::EnableHardwareWatchpoint(const DNBBreakpoint *wp) const { - uint32_t hw_index = INVALID_NUB_HW_INDEX; - if (wp != NULL) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - // On Mac OS X we have to prime the control registers for new threads. We - // do this - // using the control register data for the first thread, for lack of a - // better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) { - if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint( - wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) { - // We know that idx failed for some reason. Let's rollback the - // transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return INVALID_NUB_HW_INDEX; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - } - return hw_index; -} - -bool MachThreadList::DisableHardwareWatchpoint(const DNBBreakpoint *wp) const { - if (wp != NULL) { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - - // On Mac OS X we have to prime the control registers for new threads. We - // do this - // using the control register data for the first thread, for lack of a - // better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) { - if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) { - // We know that idx failed for some reason. Let's rollback the - // transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return false; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - - return true; - } - return false; -} - -uint32_t MachThreadList::NumSupportedHardwareWatchpoints() const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - // Use an arbitrary thread to retrieve the number of supported hardware - // watchpoints. - if (num_threads) - return m_threads[0]->NumSupportedHardwareWatchpoints(); - return 0; -} - -uint32_t MachThreadList::GetThreadIndexForThreadStoppedWithSignal( - const int signo) const { - PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); - uint32_t should_stop = false; - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) { - if (m_threads[idx]->GetStopException().SoftSignal() == signo) - return idx; - } - return UINT32_MAX; -} diff --git a/tools/debugserver/source/MacOSX/MachThreadList.h b/tools/debugserver/source/MacOSX/MachThreadList.h deleted file mode 100644 index bcef695edf87..000000000000 --- a/tools/debugserver/source/MacOSX/MachThreadList.h +++ /dev/null @@ -1,97 +0,0 @@ -//===-- MachThreadList.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/19/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachThreadList_h__ -#define __MachThreadList_h__ - -#include "MachThread.h" -#include "ThreadInfo.h" - -class DNBThreadResumeActions; - -class MachThreadList { -public: - MachThreadList(); - ~MachThreadList(); - - void Clear(); - void Dump() const; - bool GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - DNBRegisterValue *reg_value) const; - bool SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, - const DNBRegisterValue *reg_value) const; - nub_size_t GetRegisterContext(nub_thread_t tid, void *buf, size_t buf_len); - nub_size_t SetRegisterContext(nub_thread_t tid, const void *buf, - size_t buf_len); - uint32_t SaveRegisterState(nub_thread_t tid); - bool RestoreRegisterState(nub_thread_t tid, uint32_t save_id); - const char *GetThreadInfo(nub_thread_t tid) const; - void ProcessWillResume(MachProcess *process, - const DNBThreadResumeActions &thread_actions); - uint32_t ProcessDidStop(MachProcess *process); - bool NotifyException(MachException::Data &exc); - bool ShouldStop(bool &step_more); - const char *GetName(nub_thread_t tid); - nub_state_t GetState(nub_thread_t tid); - nub_thread_t SetCurrentThread(nub_thread_t tid); - - ThreadInfo::QoS GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, - uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT(nub_thread_t tid); - nub_addr_t GetDispatchQueueT(nub_thread_t tid); - nub_addr_t - GetTSDAddressForThread(nub_thread_t tid, - uint64_t plo_pthread_tsd_base_address_offset, - uint64_t plo_pthread_tsd_base_offset, - uint64_t plo_pthread_tsd_entry_size); - - bool GetThreadStoppedReason(nub_thread_t tid, - struct DNBThreadStopInfo *stop_info) const; - void DumpThreadStoppedReason(nub_thread_t tid) const; - bool GetIdentifierInfo(nub_thread_t tid, - thread_identifier_info_data_t *ident_info); - nub_size_t NumThreads() const; - nub_thread_t ThreadIDAtIndex(nub_size_t idx) const; - nub_thread_t CurrentThreadID(); - void CurrentThread(MachThreadSP &threadSP); - void NotifyBreakpointChanged(const DNBBreakpoint *bp); - uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *bp) const; - bool DisableHardwareBreakpoint(const DNBBreakpoint *bp) const; - uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *wp) const; - bool DisableHardwareWatchpoint(const DNBBreakpoint *wp) const; - uint32_t NumSupportedHardwareWatchpoints() const; - - uint32_t GetThreadIndexForThreadStoppedWithSignal(const int signo) const; - - MachThreadSP GetThreadByID(nub_thread_t tid) const; - - MachThreadSP GetThreadByMachPortNumber(thread_t mach_port_number) const; - nub_thread_t GetThreadIDByMachPortNumber(thread_t mach_port_number) const; - thread_t GetMachPortNumberByThreadID(nub_thread_t globally_unique_id) const; - -protected: - typedef std::vector<MachThreadSP> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - uint32_t UpdateThreadList(MachProcess *process, bool update, - collection *num_threads = NULL); - // const_iterator FindThreadByID (thread_t tid) const; - - collection m_threads; - mutable PThreadMutex m_threads_mutex; - MachThreadSP m_current_thread; - bool m_is_64_bit; -}; - -#endif // #ifndef __MachThreadList_h__ diff --git a/tools/debugserver/source/MacOSX/MachVMMemory.cpp b/tools/debugserver/source/MacOSX/MachVMMemory.cpp deleted file mode 100644 index 754fb82dba3e..000000000000 --- a/tools/debugserver/source/MacOSX/MachVMMemory.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//===-- MachVMMemory.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#include "MachVMMemory.h" -#include "DNBLog.h" -#include "MachVMRegion.h" -#include <dlfcn.h> -#include <mach/mach_vm.h> -#include <mach/shared_region.h> -#include <sys/sysctl.h> - -#if defined(WITH_FBS) || defined(WITH_BKS) -extern "C" { -#import <sys/kern_memorystatus.h> -} -#endif - -static const vm_size_t kInvalidPageSize = ~0; - -MachVMMemory::MachVMMemory() : m_page_size(kInvalidPageSize), m_err(0) {} - -MachVMMemory::~MachVMMemory() {} - -nub_size_t MachVMMemory::PageSize(task_t task) { - if (m_page_size == kInvalidPageSize) { -#if defined(TASK_VM_INFO) && TASK_VM_INFO >= 22 - if (task != TASK_NULL) { - kern_return_t kr; - mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT; - task_vm_info_data_t vm_info; - kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count); - if (kr == KERN_SUCCESS) { - DNBLogThreadedIf( - LOG_TASK, - "MachVMMemory::PageSize task_info returned page size of 0x%x", - (int)vm_info.page_size); - m_page_size = vm_info.page_size; - return m_page_size; - } else { - DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info call " - "failed to get page size, TASK_VM_INFO %d, " - "TASK_VM_INFO_COUNT %d, kern return %d", - TASK_VM_INFO, TASK_VM_INFO_COUNT, kr); - } - } -#endif - m_err = ::host_page_size(::mach_host_self(), &m_page_size); - if (m_err.Fail()) - m_page_size = 0; - } - return m_page_size; -} - -nub_size_t MachVMMemory::MaxBytesLeftInPage(task_t task, nub_addr_t addr, - nub_size_t count) { - const nub_size_t page_size = PageSize(task); - if (page_size > 0) { - nub_size_t page_offset = (addr % page_size); - nub_size_t bytes_left_in_page = page_size - page_offset; - if (count > bytes_left_in_page) - count = bytes_left_in_page; - } - return count; -} - -nub_bool_t MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, - DNBRegionInfo *region_info) { - MachVMRegion vmRegion(task); - - if (vmRegion.GetRegionForAddress(address)) { - region_info->addr = vmRegion.StartAddress(); - region_info->size = vmRegion.GetByteSize(); - region_info->permissions = vmRegion.GetDNBPermissions(); - } else { - region_info->addr = address; - region_info->size = 0; - if (vmRegion.GetError().Success()) { - // vmRegion.GetRegionForAddress() return false, indicating that "address" - // wasn't in a valid region, but the "vmRegion" info was successfully - // read from the task which means the info describes the next valid - // region from which we can infer the size of this invalid region - mach_vm_address_t start_addr = vmRegion.StartAddress(); - if (address < start_addr) - region_info->size = start_addr - address; - } - // If we can't get any info about the size from the next region it means - // we asked about an address that was past all mappings, so the size - // of this region will take up all remaining address space. - if (region_info->size == 0) - region_info->size = INVALID_NUB_ADDRESS - region_info->addr; - - // Not readable, writeable or executable - region_info->permissions = 0; - } - return true; -} - -static uint64_t GetPhysicalMemory() { - // This doesn't change often at all. No need to poll each time. - static uint64_t physical_memory = 0; - static bool calculated = false; - if (calculated) - return physical_memory; - - size_t len = sizeof(physical_memory); - sysctlbyname("hw.memsize", &physical_memory, &len, NULL, 0); - - calculated = true; - return physical_memory; -} - -nub_bool_t MachVMMemory::GetMemoryProfile( - DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, - cpu_type_t cputype, nub_process_t pid, vm_statistics64_data_t &vminfo, - uint64_t &physical_memory, uint64_t &anonymous, - uint64_t &phys_footprint, uint64_t &memory_cap) -{ - if (scanType & eProfileHostMemory) - physical_memory = GetPhysicalMemory(); - - if (scanType & eProfileMemory) { - static mach_port_t localHost = mach_host_self(); - mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; - host_statistics64(localHost, HOST_VM_INFO64, (host_info64_t)&vminfo, - &count); - - kern_return_t kr; - mach_msg_type_number_t info_count; - task_vm_info_data_t vm_info; - - info_count = TASK_VM_INFO_COUNT; - kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count); - if (kr == KERN_SUCCESS) { - if (scanType & eProfileMemoryAnonymous) { - anonymous = vm_info.internal + vm_info.compressed - vm_info.purgeable_volatile_pmap; - } - - phys_footprint = vm_info.phys_footprint; - } - } - -#if defined(WITH_FBS) || defined(WITH_BKS) - if (scanType & eProfileMemoryCap) { - memorystatus_memlimit_properties_t memlimit_properties; - memset(&memlimit_properties, 0, sizeof(memlimit_properties)); - if (memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, pid, 0, &memlimit_properties, sizeof(memlimit_properties)) == 0) { - memory_cap = memlimit_properties.memlimit_active; - } - } -#endif - - return true; -} - -nub_size_t MachVMMemory::Read(task_t task, nub_addr_t address, void *data, - nub_size_t data_count) { - if (data == NULL || data_count == 0) - return 0; - - nub_size_t total_bytes_read = 0; - nub_addr_t curr_addr = address; - uint8_t *curr_data = (uint8_t *)data; - while (total_bytes_read < data_count) { - mach_vm_size_t curr_size = - MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read); - mach_msg_type_number_t curr_bytes_read = 0; - vm_offset_t vm_memory = 0; - m_err = ::mach_vm_read(task, curr_addr, curr_size, &vm_memory, - &curr_bytes_read); - - if (DNBLogCheckLogBit(LOG_MEMORY)) - m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, " - "size = %llu, data => %8.8p, dataCnt => %i )", - task, (uint64_t)curr_addr, (uint64_t)curr_size, - vm_memory, curr_bytes_read); - - if (m_err.Success()) { - if (curr_bytes_read != curr_size) { - if (DNBLogCheckLogBit(LOG_MEMORY)) - m_err.LogThreaded( - "::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, " - "data => %8.8p, dataCnt=>%i ) only read %u of %llu bytes", - task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, - curr_bytes_read, curr_bytes_read, (uint64_t)curr_size); - } - ::memcpy(curr_data, (void *)vm_memory, curr_bytes_read); - ::vm_deallocate(mach_task_self(), vm_memory, curr_bytes_read); - total_bytes_read += curr_bytes_read; - curr_addr += curr_bytes_read; - curr_data += curr_bytes_read; - } else { - break; - } - } - return total_bytes_read; -} - -nub_size_t MachVMMemory::Write(task_t task, nub_addr_t address, - const void *data, nub_size_t data_count) { - MachVMRegion vmRegion(task); - - nub_size_t total_bytes_written = 0; - nub_addr_t curr_addr = address; - const uint8_t *curr_data = (const uint8_t *)data; - - while (total_bytes_written < data_count) { - if (vmRegion.GetRegionForAddress(curr_addr)) { - mach_vm_size_t curr_data_count = data_count - total_bytes_written; - mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); - if (region_bytes_left == 0) { - break; - } - if (curr_data_count > region_bytes_left) - curr_data_count = region_bytes_left; - - if (vmRegion.SetProtections(curr_addr, curr_data_count, - VM_PROT_READ | VM_PROT_WRITE)) { - nub_size_t bytes_written = - WriteRegion(task, curr_addr, curr_data, curr_data_count); - if (bytes_written <= 0) { - // Status should have already be posted by WriteRegion... - break; - } else { - total_bytes_written += bytes_written; - curr_addr += bytes_written; - curr_data += bytes_written; - } - } else { - DNBLogThreadedIf( - LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on " - "region for address: [0x%8.8llx-0x%8.8llx)", - (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count)); - break; - } - } else { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, - "Failed to get region for address: 0x%8.8llx", - (uint64_t)address); - break; - } - } - - return total_bytes_written; -} - -nub_size_t MachVMMemory::WriteRegion(task_t task, const nub_addr_t address, - const void *data, - const nub_size_t data_count) { - if (data == NULL || data_count == 0) - return 0; - - nub_size_t total_bytes_written = 0; - nub_addr_t curr_addr = address; - const uint8_t *curr_data = (const uint8_t *)data; - while (total_bytes_written < data_count) { - mach_msg_type_number_t curr_data_count = - static_cast<mach_msg_type_number_t>(MaxBytesLeftInPage( - task, curr_addr, data_count - total_bytes_written)); - m_err = - ::mach_vm_write(task, curr_addr, (pointer_t)curr_data, curr_data_count); - if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, " - "data = %8.8p, dataCnt = %u )", - task, (uint64_t)curr_addr, curr_data, curr_data_count); - -#if !defined(__i386__) && !defined(__x86_64__) - vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; - - m_err = ::vm_machine_attribute(task, curr_addr, curr_data_count, - MATTR_CACHE, &mattr_value); - if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) - m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = " - "0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value " - "=> MATTR_VAL_CACHE_FLUSH )", - task, (uint64_t)curr_addr, curr_data_count); -#endif - - if (m_err.Success()) { - total_bytes_written += curr_data_count; - curr_addr += curr_data_count; - curr_data += curr_data_count; - } else { - break; - } - } - return total_bytes_written; -} diff --git a/tools/debugserver/source/MacOSX/MachVMMemory.h b/tools/debugserver/source/MacOSX/MachVMMemory.h deleted file mode 100644 index 513b69ee709f..000000000000 --- a/tools/debugserver/source/MacOSX/MachVMMemory.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- MachVMMemory.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachVMMemory_h__ -#define __MachVMMemory_h__ - -#include "DNBDefs.h" -#include "DNBError.h" -#include <mach/mach.h> - -class MachVMMemory { -public: - MachVMMemory(); - ~MachVMMemory(); - nub_size_t Read(task_t task, nub_addr_t address, void *data, - nub_size_t data_count); - nub_size_t Write(task_t task, nub_addr_t address, const void *data, - nub_size_t data_count); - nub_size_t PageSize(task_t task); - nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, - DNBRegionInfo *region_info); - nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, - struct task_basic_info ti, cpu_type_t cputype, - nub_process_t pid, vm_statistics64_data_t &vminfo, - uint64_t &physical_memory, uint64_t &anonymous, - uint64_t &phys_footprint, uint64_t &memory_cap); - -protected: - nub_size_t MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count); - - nub_size_t WriteRegion(task_t task, const nub_addr_t address, - const void *data, const nub_size_t data_count); - - vm_size_t m_page_size; - DNBError m_err; -}; - -#endif // #ifndef __MachVMMemory_h__ diff --git a/tools/debugserver/source/MacOSX/MachVMRegion.cpp b/tools/debugserver/source/MacOSX/MachVMRegion.cpp deleted file mode 100644 index 172fc7867b57..000000000000 --- a/tools/debugserver/source/MacOSX/MachVMRegion.cpp +++ /dev/null @@ -1,185 +0,0 @@ -//===-- MachVMRegion.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#include "MachVMRegion.h" -#include "DNBLog.h" -#include <assert.h> -#include <mach/mach_vm.h> - -MachVMRegion::MachVMRegion(task_t task) - : m_task(task), m_addr(INVALID_NUB_ADDRESS), m_err(), - m_start(INVALID_NUB_ADDRESS), m_size(0), m_depth(-1), - m_curr_protection(0), m_protection_addr(INVALID_NUB_ADDRESS), - m_protection_size(0) { - memset(&m_data, 0, sizeof(m_data)); -} - -MachVMRegion::~MachVMRegion() { - // Restore any original protections and clear our vars - Clear(); -} - -void MachVMRegion::Clear() { - RestoreProtections(); - m_addr = INVALID_NUB_ADDRESS; - m_err.Clear(); - m_start = INVALID_NUB_ADDRESS; - m_size = 0; - m_depth = -1; - memset(&m_data, 0, sizeof(m_data)); - m_curr_protection = 0; - m_protection_addr = INVALID_NUB_ADDRESS; - m_protection_size = 0; -} - -bool MachVMRegion::SetProtections(mach_vm_address_t addr, mach_vm_size_t size, - vm_prot_t prot) { - if (ContainsAddress(addr)) { - mach_vm_size_t prot_size = size; - mach_vm_address_t end_addr = EndAddress(); - if (prot_size > (end_addr - addr)) - prot_size = end_addr - addr; - - if (prot_size > 0) { - if (prot == (m_curr_protection & VM_PROT_ALL)) { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, - "MachVMRegion::%s: protections (%u) already " - "sufficient for task 0x%4.4x at address 0x%8.8llx) ", - __FUNCTION__, prot, m_task, (uint64_t)addr); - // Protections are already set as requested... - return true; - } else { - m_err = ::mach_vm_protect(m_task, addr, prot_size, 0, prot); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS)) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = " - "0x%8.8llx, size = %llu, set_max = %i, prot = %u )", - m_task, (uint64_t)addr, (uint64_t)prot_size, 0, - prot); - if (m_err.Fail()) { - // Try again with the ability to create a copy on write region - m_err = ::mach_vm_protect(m_task, addr, prot_size, 0, - prot | VM_PROT_COPY); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = " - "0x%8.8llx, size = %llu, set_max = %i, prot = %u " - ")", - m_task, (uint64_t)addr, (uint64_t)prot_size, 0, - prot | VM_PROT_COPY); - } - if (m_err.Success()) { - m_curr_protection = prot; - m_protection_addr = addr; - m_protection_size = prot_size; - return true; - } - } - } else { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, - "%s: Zero size for task 0x%4.4x at address 0x%8.8llx) ", - __FUNCTION__, m_task, (uint64_t)addr); - } - } - return false; -} - -bool MachVMRegion::RestoreProtections() { - if (m_curr_protection != m_data.protection && m_protection_size > 0) { - m_err = ::mach_vm_protect(m_task, m_protection_addr, m_protection_size, 0, - m_data.protection); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, " - "size = %llu, set_max = %i, prot = %u )", - m_task, (uint64_t)m_protection_addr, - (uint64_t)m_protection_size, 0, m_data.protection); - if (m_err.Success()) { - m_protection_size = 0; - m_protection_addr = INVALID_NUB_ADDRESS; - m_curr_protection = m_data.protection; - return true; - } - } else { - m_err.Clear(); - return true; - } - - return false; -} - -bool MachVMRegion::GetRegionForAddress(nub_addr_t addr) { - // Restore any original protections and clear our vars - Clear(); - m_err.Clear(); - m_addr = addr; - m_start = addr; - m_depth = 1024; - mach_msg_type_number_t info_size = kRegionInfoSize; - assert(sizeof(info_size) == 4); - m_err = - ::mach_vm_region_recurse(m_task, &m_start, &m_size, &m_depth, - (vm_region_recurse_info_t)&m_data, &info_size); - - const bool failed = m_err.Fail(); - const bool log_protections = DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS); - - if (log_protections || failed) - m_err.LogThreaded("::mach_vm_region_recurse ( task = 0x%4.4x, address => " - "0x%8.8llx, size => %llu, nesting_depth => %d, info => " - "%p, infoCnt => %d) addr = 0x%8.8llx ", - m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, - &m_data, info_size, (uint64_t)addr); - - if (failed) - return false; - if (log_protections) { - DNBLogThreaded("info = { prot = %u, " - "max_prot = %u, " - "inheritance = 0x%8.8x, " - "offset = 0x%8.8llx, " - "user_tag = 0x%8.8x, " - "ref_count = %u, " - "shadow_depth = %u, " - "ext_pager = %u, " - "share_mode = %u, " - "is_submap = %d, " - "behavior = %d, " - "object_id = 0x%8.8x, " - "user_wired_count = 0x%4.4x }", - m_data.protection, m_data.max_protection, m_data.inheritance, - (uint64_t)m_data.offset, m_data.user_tag, m_data.ref_count, - m_data.shadow_depth, m_data.external_pager, - m_data.share_mode, m_data.is_submap, m_data.behavior, - m_data.object_id, m_data.user_wired_count); - } - m_curr_protection = m_data.protection; - - // We make a request for an address and got no error back, but this - // doesn't mean that "addr" is in the range. The data in this object will - // be valid though, so you could see where the next region begins. So we - // return false, yet leave "m_err" with a successfull return code. - return !((addr < m_start) || (addr >= (m_start + m_size))); -} - -uint32_t MachVMRegion::GetDNBPermissions() const { - if (m_addr == INVALID_NUB_ADDRESS || m_start == INVALID_NUB_ADDRESS || - m_size == 0) - return 0; - uint32_t dnb_permissions = 0; - - if ((m_data.protection & VM_PROT_READ) == VM_PROT_READ) - dnb_permissions |= eMemoryPermissionsReadable; - if ((m_data.protection & VM_PROT_WRITE) == VM_PROT_WRITE) - dnb_permissions |= eMemoryPermissionsWritable; - if ((m_data.protection & VM_PROT_EXECUTE) == VM_PROT_EXECUTE) - dnb_permissions |= eMemoryPermissionsExecutable; - return dnb_permissions; -} diff --git a/tools/debugserver/source/MacOSX/MachVMRegion.h b/tools/debugserver/source/MacOSX/MachVMRegion.h deleted file mode 100644 index 758112d236d7..000000000000 --- a/tools/debugserver/source/MacOSX/MachVMRegion.h +++ /dev/null @@ -1,73 +0,0 @@ -//===-- MachVMRegion.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/26/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachVMRegion_h__ -#define __MachVMRegion_h__ - -#include "DNBDefs.h" -#include "DNBError.h" -#include <mach/mach.h> - -class MachVMRegion { -public: - MachVMRegion(task_t task); - ~MachVMRegion(); - - void Clear(); - mach_vm_address_t StartAddress() const { return m_start; } - mach_vm_address_t EndAddress() const { return m_start + m_size; } - mach_vm_size_t GetByteSize() const { return m_size; } - mach_vm_address_t BytesRemaining(mach_vm_address_t addr) const { - if (ContainsAddress(addr)) - return m_size - (addr - m_start); - else - return 0; - } - bool ContainsAddress(mach_vm_address_t addr) const { - return addr >= StartAddress() && addr < EndAddress(); - } - - bool SetProtections(mach_vm_address_t addr, mach_vm_size_t size, - vm_prot_t prot); - bool RestoreProtections(); - bool GetRegionForAddress(nub_addr_t addr); - - uint32_t GetDNBPermissions() const; - - const DNBError &GetError() { return m_err; } - -protected: -#if defined(VM_REGION_SUBMAP_SHORT_INFO_COUNT_64) - typedef vm_region_submap_short_info_data_64_t RegionInfo; - enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 }; -#else - typedef vm_region_submap_info_data_64_t RegionInfo; - enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 }; -#endif - - task_t m_task; - mach_vm_address_t m_addr; - DNBError m_err; - mach_vm_address_t m_start; - mach_vm_size_t m_size; - natural_t m_depth; - RegionInfo m_data; - vm_prot_t m_curr_protection; // The current, possibly modified protections. - // Original value is saved in m_data.protections. - mach_vm_address_t - m_protection_addr; // The start address at which protections were changed - mach_vm_size_t - m_protection_size; // The size of memory that had its protections changed -}; - -#endif // #ifndef __MachVMRegion_h__ diff --git a/tools/debugserver/source/MacOSX/OsLogger.cpp b/tools/debugserver/source/MacOSX/OsLogger.cpp deleted file mode 100644 index 40aeec73f0aa..000000000000 --- a/tools/debugserver/source/MacOSX/OsLogger.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//===-- OsLogger.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "OsLogger.h" -#include <Availability.h> - -#if (LLDB_USE_OS_LOG) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) - -#include <os/log.h> - -#include "DNBDefs.h" -#include "DNBLog.h" - -#define LLDB_OS_LOG_MAX_BUFFER_LENGTH 256 - -namespace { -//---------------------------------------------------------------------- -// Darwin os_log logging callback that can be registered with -// DNBLogSetLogCallback -//---------------------------------------------------------------------- -void DarwinLogCallback(void *baton, uint32_t flags, const char *format, - va_list args) { - if (format == nullptr) - return; - - static os_log_t g_logger; - if (!g_logger) { - g_logger = os_log_create("com.apple.dt.lldb", "debugserver"); - if (!g_logger) - return; - } - - os_log_type_t log_type; - if (flags & DNBLOG_FLAG_FATAL) - log_type = OS_LOG_TYPE_FAULT; - else if (flags & DNBLOG_FLAG_ERROR) - log_type = OS_LOG_TYPE_ERROR; - else if (flags & DNBLOG_FLAG_WARNING) - log_type = OS_LOG_TYPE_DEFAULT; - else if (flags & DNBLOG_FLAG_VERBOSE) - log_type = OS_LOG_TYPE_DEBUG; - else - log_type = OS_LOG_TYPE_DEFAULT; - - // This code is unfortunate. os_log* only takes static strings, but - // our current log API isn't set up to make use of that style. - char buffer[LLDB_OS_LOG_MAX_BUFFER_LENGTH]; - vsnprintf(buffer, sizeof(buffer), format, args); - os_log_with_type(g_logger, log_type, "%{public}s", buffer); -} -} - -DNBCallbackLog OsLogger::GetLogFunction() { return DarwinLogCallback; } - -#else - -DNBCallbackLog OsLogger::GetLogFunction() { return nullptr; } - -#endif - diff --git a/tools/debugserver/source/MacOSX/OsLogger.h b/tools/debugserver/source/MacOSX/OsLogger.h deleted file mode 100644 index 9afdcb974d9a..000000000000 --- a/tools/debugserver/source/MacOSX/OsLogger.h +++ /dev/null @@ -1,20 +0,0 @@ -//===-- OsLogger.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef OsLogger_h -#define OsLogger_h - -#include "DNBDefs.h" - -class OsLogger { -public: - static DNBCallbackLog GetLogFunction(); -}; - -#endif /* OsLogger_h */ diff --git a/tools/debugserver/source/MacOSX/ThreadInfo.h b/tools/debugserver/source/MacOSX/ThreadInfo.h deleted file mode 100644 index e9773caf9ea3..000000000000 --- a/tools/debugserver/source/MacOSX/ThreadInfo.h +++ /dev/null @@ -1,26 +0,0 @@ -//===-- ThreadInfo.h -----------------------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __ThreadInfo_h__ -#define __ThreadInfo_h__ - -namespace ThreadInfo { - -class QoS { -public: - QoS() : constant_name(), printable_name(), enum_value(UINT32_MAX) {} - bool IsValid() { return enum_value != UINT32_MAX; } - std::string constant_name; - std::string printable_name; - uint32_t enum_value; -}; -}; - -#endif // __ThreadInfo_h__ diff --git a/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp deleted file mode 100644 index 2841ddb11081..000000000000 --- a/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ /dev/null @@ -1,2194 +0,0 @@ -//===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// 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 <inttypes.h> -#include <sys/sysctl.h> - -// 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 - -// 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; -} - -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; -} - -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]); - } -} - -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 int num_watchpoints = NumSupportedHardwareWatchpoints(); - for (int 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 <rdar://problem/6372672> 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 <rdar://problem/6372672> 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) { - // 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 mismatch - 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 mismatch - 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) { - 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}, - {e_regSetVFP, exc_fsr, "fsr", NULL, Uint, Hex, 4, EXC_OFFSET(fsr), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM}, - {e_regSetVFP, exc_far, "far", NULL, Uint, Hex, 4, EXC_OFFSET(far), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM}}; - -// 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 = (uint8_t *)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 - (uint8_t *)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/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h deleted file mode 100644 index e8622c4ec7eb..000000000000 --- a/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ /dev/null @@ -1,275 +0,0 @@ -//===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DebugNubArchMachARM_h__ -#define __DebugNubArchMachARM_h__ - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include "DNBArch.h" - -#include <map> - -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); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState(); - virtual bool RestoreRegisterState(uint32_t save_id); - - virtual kern_return_t GetRegisterState(int set, bool force); - virtual kern_return_t SetRegisterState(int set); - virtual bool RegisterSetStateIsValid(int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data &exc); - - static DNBArchProtocol *Create(MachThread *thread); - static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); - static uint32_t GetCPUType(); - - virtual uint32_t NumSupportedHardwareBreakpoints(); - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size); - virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index); - - virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task); - virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task); - 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(); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - -#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); - - typedef enum RegisterSetTag { - 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 - } RegisterSet; - - 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<disabled_watchpoint> 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<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (__arm__) -#endif // #ifndef __DebugNubArchMachARM_h__ diff --git a/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp b/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp deleted file mode 100644 index 51bc5aaee5bb..000000000000 --- a/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp +++ /dev/null @@ -1,2104 +0,0 @@ -//===-- DNBArchMachARM64.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include "MacOSX/arm64/DNBArchImplARM64.h" - -#if defined(ARM_THREAD_STATE64_COUNT) - -#include "DNB.h" -#include "DNBBreakpoint.h" -#include "DNBLog.h" -#include "DNBRegisterInfo.h" -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachThread.h" - -#include <inttypes.h> -#include <sys/sysctl.h> - -// Break only in privileged or user mode -// (PAC bits in the DBGWVRn_EL1 watchpoint control register) -#define S_USER ((uint32_t)(2u << 1)) - -#define BCR_ENABLE ((uint32_t)(1u)) -#define WCR_ENABLE ((uint32_t)(1u)) - -// Watchpoint load/store -// (LSC bits in the DBGWVRn_EL1 watchpoint control register) -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) - -// Enable breakpoint, watchpoint, and vector catch debug exceptions. -// (MDE bit in the MDSCR_EL1 register. Equivalent to the MDBGen bit in -// DBGDSCRext in Aarch32) -#define MDE_ENABLE ((uint32_t)(1u << 15)) - -// Single instruction step -// (SS bit in the MDSCR_EL1 register) -#define SS_ENABLE ((uint32_t)(1u)) - -static const uint8_t g_arm64_breakpoint_opcode[] = { - 0x00, 0x00, 0x20, 0xD4}; // "brk #0", 0xd4200000 in BE byte order -static const uint8_t g_arm_breakpoint_opcode[] = { - 0xFE, 0xDE, 0xFF, 0xE7}; // this armv7 insn also works in arm64 - -// If we need to set one logical watchpoint by using -// two hardware watchpoint registers, the watchpoint -// will be split into a "high" and "low" watchpoint. -// Record both of them in the LoHi array. - -// 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}; - -void DNBArchMachARM64::Initialize() { - DNBArchPluginInfo arch_plugin_info = { - CPU_TYPE_ARM64, DNBArchMachARM64::Create, - DNBArchMachARM64::GetRegisterSetInfo, - DNBArchMachARM64::SoftwareBreakpointOpcode}; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); -} - -DNBArchProtocol *DNBArchMachARM64::Create(MachThread *thread) { - DNBArchMachARM64 *obj = new DNBArchMachARM64(thread); - - return obj; -} - -const uint8_t * -DNBArchMachARM64::SoftwareBreakpointOpcode(nub_size_t byte_size) { - return g_arm_breakpoint_opcode; -} - -uint32_t DNBArchMachARM64::GetCPUType() { return CPU_TYPE_ARM64; } - -uint64_t DNBArchMachARM64::GetPC(uint64_t failValue) { - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__pc; - return failValue; -} - -kern_return_t DNBArchMachARM64::SetPC(uint64_t value) { - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) { - m_state.context.gpr.__pc = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; -} - -uint64_t DNBArchMachARM64::GetSP(uint64_t failValue) { - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__sp; - return failValue; -} - -kern_return_t DNBArchMachARM64::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 = e_regSetGPRCount; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, - (thread_state_t)&m_state.context.gpr, &count); - if (DNBLogEnabledForAny(LOG_THREAD)) { - uint64_t *x = &m_state.context.gpr.__x[0]; - DNBLogThreaded( - "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs" - "\n x0=%16.16llx" - "\n x1=%16.16llx" - "\n x2=%16.16llx" - "\n x3=%16.16llx" - "\n x4=%16.16llx" - "\n x5=%16.16llx" - "\n x6=%16.16llx" - "\n x7=%16.16llx" - "\n x8=%16.16llx" - "\n x9=%16.16llx" - "\n x10=%16.16llx" - "\n x11=%16.16llx" - "\n x12=%16.16llx" - "\n x13=%16.16llx" - "\n x14=%16.16llx" - "\n x15=%16.16llx" - "\n x16=%16.16llx" - "\n x17=%16.16llx" - "\n x18=%16.16llx" - "\n x19=%16.16llx" - "\n x20=%16.16llx" - "\n x21=%16.16llx" - "\n x22=%16.16llx" - "\n x23=%16.16llx" - "\n x24=%16.16llx" - "\n x25=%16.16llx" - "\n x26=%16.16llx" - "\n x27=%16.16llx" - "\n x28=%16.16llx" - "\n fp=%16.16llx" - "\n lr=%16.16llx" - "\n sp=%16.16llx" - "\n pc=%16.16llx" - "\n cpsr=%8.8x", - m_thread->MachPortNumber(), e_regSetGPR, e_regSetGPRCount, kret, count, - x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[0], x[11], - x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21], - x[22], x[23], x[24], x[25], x[26], x[27], x[28], - m_state.context.gpr.__fp, m_state.context.gpr.__lr, - m_state.context.gpr.__sp, m_state.context.gpr.__pc, - m_state.context.gpr.__cpsr); - } - m_state.SetError(set, Read, kret); - return kret; -} - -kern_return_t DNBArchMachARM64::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; - - // Read the registers from our thread - mach_msg_type_number_t count = e_regSetVFPCount; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE64, - (thread_state_t)&m_state.context.vfp, &count); - if (DNBLogEnabledForAny(LOG_THREAD)) { -#if defined(__arm64__) || defined(__aarch64__) - 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 q16 = 0x%16.16llx%16.16llx" - "\n q17 = 0x%16.16llx%16.16llx" - "\n q18 = 0x%16.16llx%16.16llx" - "\n q19 = 0x%16.16llx%16.16llx" - "\n q20 = 0x%16.16llx%16.16llx" - "\n q21 = 0x%16.16llx%16.16llx" - "\n q22 = 0x%16.16llx%16.16llx" - "\n q23 = 0x%16.16llx%16.16llx" - "\n q24 = 0x%16.16llx%16.16llx" - "\n q25 = 0x%16.16llx%16.16llx" - "\n q26 = 0x%16.16llx%16.16llx" - "\n q27 = 0x%16.16llx%16.16llx" - "\n q28 = 0x%16.16llx%16.16llx" - "\n q29 = 0x%16.16llx%16.16llx" - "\n q30 = 0x%16.16llx%16.16llx" - "\n q31 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), e_regSetVFP, e_regSetVFPCount, 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], - ((uint64_t *)&m_state.context.vfp.__v[16])[0], - ((uint64_t *)&m_state.context.vfp.__v[16])[1], - ((uint64_t *)&m_state.context.vfp.__v[17])[0], - ((uint64_t *)&m_state.context.vfp.__v[17])[1], - ((uint64_t *)&m_state.context.vfp.__v[18])[0], - ((uint64_t *)&m_state.context.vfp.__v[18])[1], - ((uint64_t *)&m_state.context.vfp.__v[19])[0], - ((uint64_t *)&m_state.context.vfp.__v[19])[1], - ((uint64_t *)&m_state.context.vfp.__v[20])[0], - ((uint64_t *)&m_state.context.vfp.__v[20])[1], - ((uint64_t *)&m_state.context.vfp.__v[21])[0], - ((uint64_t *)&m_state.context.vfp.__v[21])[1], - ((uint64_t *)&m_state.context.vfp.__v[22])[0], - ((uint64_t *)&m_state.context.vfp.__v[22])[1], - ((uint64_t *)&m_state.context.vfp.__v[23])[0], - ((uint64_t *)&m_state.context.vfp.__v[23])[1], - ((uint64_t *)&m_state.context.vfp.__v[24])[0], - ((uint64_t *)&m_state.context.vfp.__v[24])[1], - ((uint64_t *)&m_state.context.vfp.__v[25])[0], - ((uint64_t *)&m_state.context.vfp.__v[25])[1], - ((uint64_t *)&m_state.context.vfp.__v[26])[0], - ((uint64_t *)&m_state.context.vfp.__v[26])[1], - ((uint64_t *)&m_state.context.vfp.__v[27])[0], - ((uint64_t *)&m_state.context.vfp.__v[27])[1], - ((uint64_t *)&m_state.context.vfp.__v[28])[0], - ((uint64_t *)&m_state.context.vfp.__v[28])[1], - ((uint64_t *)&m_state.context.vfp.__v[29])[0], - ((uint64_t *)&m_state.context.vfp.__v[29])[1], - ((uint64_t *)&m_state.context.vfp.__v[30])[0], - ((uint64_t *)&m_state.context.vfp.__v[30])[1], - ((uint64_t *)&m_state.context.vfp.__v[31])[0], - ((uint64_t *)&m_state.context.vfp.__v[31])[1], - m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); -#endif - } - m_state.SetError(set, Read, kret); - return kret; -} - -kern_return_t DNBArchMachARM64::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 = e_regSetEXCCount; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, - (thread_state_t)&m_state.context.exc, &count); - m_state.SetError(set, Read, kret); - return kret; -} - -static void DumpDBGState(const arm_debug_state_t &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]); -} - -kern_return_t DNBArchMachARM64::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 - mach_msg_type_number_t count = e_regSetDBGCount; - kern_return_t kret = - ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, - (thread_state_t)&m_state.dbg, &count); - m_state.SetError(set, Read, kret); - - return kret; -} - -kern_return_t DNBArchMachARM64::SetGPRState() { - int set = e_regSetGPR; - kern_return_t kret = ::thread_set_state( - m_thread->MachPortNumber(), ARM_THREAD_STATE64, - (thread_state_t)&m_state.context.gpr, e_regSetGPRCount); - 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 DNBArchMachARM64::SetVFPState() { - int set = e_regSetVFP; - kern_return_t kret = ::thread_set_state( - m_thread->MachPortNumber(), ARM_NEON_STATE64, - (thread_state_t)&m_state.context.vfp, e_regSetVFPCount); - 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 DNBArchMachARM64::SetEXCState() { - int set = e_regSetEXC; - kern_return_t kret = ::thread_set_state( - m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, - (thread_state_t)&m_state.context.exc, e_regSetEXCCount); - 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 DNBArchMachARM64::SetDBGState(bool also_set_on_task) { - int set = e_regSetDBG; - kern_return_t kret = - ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, - (thread_state_t)&m_state.dbg, e_regSetDBGCount); - if (also_set_on_task) { - kern_return_t task_kret = task_set_state( - m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE64, - (thread_state_t)&m_state.dbg, e_regSetDBGCount); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::SetDBGState failed " - "to set debug control register state: " - "0x%8.8x.", - task_kret); - } - 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 DNBArchMachARM64::ThreadWillResume() { - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) { - EnableHardwareSingleStep(true); - } - - // 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 DNBArchMachARM64::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); - - // One logical watchpoint was split into two watchpoint locations because - // it was too big. If the watchpoint exception is indicating the 2nd half - // of the two-parter, find the address of the 1st half and report that -- - // that's what lldb is going to expect to see. - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " - "watchpoint %d was hit on address " - "0x%llx", - hw_index, (uint64_t)addr); - const int num_watchpoints = NumSupportedHardwareWatchpoints(); - for (int 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 DNBArchMachARM64::ThreadDidStop() { - bool success = true; - - m_state.InvalidateAllRegisterStates(); - - 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()) { - // 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; -} - -// Set the single step bit in the processor status register. -kern_return_t DNBArchMachARM64::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(); - } - - 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 |= SS_ENABLE; - } 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 &= ~(SS_ENABLE); - } - - 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 uint64_t bits(uint64_t value, uint32_t msbit, uint32_t lsbit) { - assert(msbit >= lsbit); - uint64_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 -} - -uint32_t DNBArchMachARM64::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 { -// For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in -// EL0 so it can't -// access that reg. The kernel should have filled in the sysctls based on it -// though. -#if defined(__arm__) - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); - uint32_t numWRPs = bits(register_DBGDIDR, 31, 28); - // Zero is reserved for the WRP count, so don't increment it if it is zero - if (numWRPs > 0) - numWRPs++; - g_num_supported_hw_watchpoints = numWRPs; - DNBLogThreadedIf(LOG_THREAD, - "Number of supported hw watchpoints via asm(): %d", - g_num_supported_hw_watchpoints); -#endif - } - } - return g_num_supported_hw_watchpoints; -} - -uint32_t DNBArchMachARM64::EnableHardwareWatchpoint(nub_addr_t addr, - nub_size_t size, bool read, - bool write, - bool also_set_on_task) { - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchMachARM64::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; - - // arm64 watchpoints really have 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. - - // arm64 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. - - nub_addr_t aligned_wp_address = addr & ~0x7; - uint32_t addr_dword_offset = addr & 0x7; - - // 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 > 8) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" - "EnableHardwareWatchpoint(addr = " - "0x%8.8llx, size = %zu) needs two " - "hardware watchpoints slots to monitor", - (uint64_t)addr, size); - int low_watchpoint_size = 8 - addr_dword_offset; - int high_watchpoint_size = addr_dword_offset + size - 8; - - 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 + 8, 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(false); - - 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, "DNBArchMachARM64::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, "DNBArchMachARM64::" - "EnableHardwareWatchpoint() " - "SetDBGState() => 0x%8.8x.", - kret); - - if (kret == KERN_SUCCESS) - return i; - } else { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" - "EnableHardwareWatchpoint(): All " - "hardware resources (%u) are in use.", - num_hw_watchpoints); - } - } - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchMachARM64::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 DNBArchMachARM64::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, "DNBArchMachARM64::" - "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 DNBArchMachARM64::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 DNBArchMachARM64::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.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" - "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); -} - -// This is for checking the Byte Address Select bits in the DBRWCRn_EL1 control -// register. -// Returns -1 if the trailing bit patterns are not one of: -// { 0b???????1, 0b??????10, 0b?????100, 0b????1000, 0b???10000, 0b??100000, -// 0b?1000000, 0b10000000 }. -static inline int32_t LowestBitSet(uint32_t val) { - for (unsigned i = 0; i < 8; ++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 DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr) { - // Read the debug state - kern_return_t kret = GetDBGState(true); - // DumpDBGState(m_state.dbg); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchMachARM64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", - kret); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx", - (uint64_t)addr); - - // This is the watchpoint value to match against, i.e., word address. - nub_addr_t wp_val = addr & ~((nub_addr_t)3); - 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, "DNBArchMachARM64::" - "GetHardwareWatchpointHit() slot: %u " - "(addr = 0x%llx).", - i, (uint64_t)wp_addr); - if (wp_val == wp_addr) { - uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); - - // Sanity check the byte_mask, first. - if (LowestBitSet(byte_mask) < 0) - continue; - - // Check that the watchpoint is enabled. - if (!IsWatchpointEnabled(debug_state, i)) - 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 DNBArchMachARM64::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 DNBArchMachARM64::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 DNBArchMachARM64::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], 63, 0); -} - -//---------------------------------------------------------------------- -// Register information definitions for 64 bit ARMv8. -//---------------------------------------------------------------------- -enum gpr_regnums { - gpr_x0 = 0, - gpr_x1, - gpr_x2, - gpr_x3, - gpr_x4, - gpr_x5, - gpr_x6, - gpr_x7, - gpr_x8, - gpr_x9, - gpr_x10, - gpr_x11, - gpr_x12, - gpr_x13, - gpr_x14, - gpr_x15, - gpr_x16, - gpr_x17, - gpr_x18, - gpr_x19, - gpr_x20, - gpr_x21, - gpr_x22, - gpr_x23, - gpr_x24, - gpr_x25, - gpr_x26, - gpr_x27, - gpr_x28, - gpr_fp, - gpr_x29 = gpr_fp, - gpr_lr, - gpr_x30 = gpr_lr, - gpr_sp, - gpr_x31 = gpr_sp, - gpr_pc, - gpr_cpsr, - gpr_w0, - gpr_w1, - gpr_w2, - gpr_w3, - gpr_w4, - gpr_w5, - gpr_w6, - gpr_w7, - gpr_w8, - gpr_w9, - gpr_w10, - gpr_w11, - gpr_w12, - gpr_w13, - gpr_w14, - gpr_w15, - gpr_w16, - gpr_w17, - gpr_w18, - gpr_w19, - gpr_w20, - gpr_w21, - gpr_w22, - gpr_w23, - gpr_w24, - gpr_w25, - gpr_w26, - gpr_w27, - gpr_w28 - -}; - -enum { - vfp_v0 = 0, - vfp_v1, - vfp_v2, - vfp_v3, - vfp_v4, - vfp_v5, - vfp_v6, - vfp_v7, - vfp_v8, - vfp_v9, - vfp_v10, - vfp_v11, - vfp_v12, - vfp_v13, - vfp_v14, - vfp_v15, - vfp_v16, - vfp_v17, - vfp_v18, - vfp_v19, - vfp_v20, - vfp_v21, - vfp_v22, - vfp_v23, - vfp_v24, - vfp_v25, - vfp_v26, - vfp_v27, - vfp_v28, - vfp_v29, - vfp_v30, - vfp_v31, - vfp_fpsr, - vfp_fpcr, - - // lower 32 bits of the corresponding vfp_v<n> reg. - vfp_s0, - 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, - - // lower 64 bits of the corresponding vfp_v<n> reg. - 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 -}; - -enum { exc_far = 0, exc_esr, exc_exception }; - -// These numbers from the "DWARF for the ARM 64-bit Architecture (AArch64)" -// document. - -enum { - dwarf_x0 = 0, - dwarf_x1, - dwarf_x2, - dwarf_x3, - dwarf_x4, - dwarf_x5, - dwarf_x6, - dwarf_x7, - dwarf_x8, - dwarf_x9, - dwarf_x10, - dwarf_x11, - dwarf_x12, - dwarf_x13, - dwarf_x14, - dwarf_x15, - dwarf_x16, - dwarf_x17, - dwarf_x18, - dwarf_x19, - dwarf_x20, - dwarf_x21, - dwarf_x22, - dwarf_x23, - dwarf_x24, - dwarf_x25, - dwarf_x26, - dwarf_x27, - dwarf_x28, - dwarf_x29, - dwarf_x30, - dwarf_x31, - dwarf_pc = 32, - dwarf_elr_mode = 33, - dwarf_fp = dwarf_x29, - dwarf_lr = dwarf_x30, - dwarf_sp = dwarf_x31, - // 34-63 reserved - - // V0-V31 (128 bit vector registers) - dwarf_v0 = 64, - dwarf_v1, - dwarf_v2, - dwarf_v3, - dwarf_v4, - dwarf_v5, - dwarf_v6, - dwarf_v7, - dwarf_v8, - dwarf_v9, - dwarf_v10, - dwarf_v11, - dwarf_v12, - dwarf_v13, - dwarf_v14, - dwarf_v15, - dwarf_v16, - dwarf_v17, - dwarf_v18, - dwarf_v19, - dwarf_v20, - dwarf_v21, - dwarf_v22, - dwarf_v23, - dwarf_v24, - dwarf_v25, - dwarf_v26, - dwarf_v27, - dwarf_v28, - dwarf_v29, - dwarf_v30, - dwarf_v31 - - // 96-127 reserved -}; - -enum { - debugserver_gpr_x0 = 0, - debugserver_gpr_x1, - debugserver_gpr_x2, - debugserver_gpr_x3, - debugserver_gpr_x4, - debugserver_gpr_x5, - debugserver_gpr_x6, - debugserver_gpr_x7, - debugserver_gpr_x8, - debugserver_gpr_x9, - debugserver_gpr_x10, - debugserver_gpr_x11, - debugserver_gpr_x12, - debugserver_gpr_x13, - debugserver_gpr_x14, - debugserver_gpr_x15, - debugserver_gpr_x16, - debugserver_gpr_x17, - debugserver_gpr_x18, - debugserver_gpr_x19, - debugserver_gpr_x20, - debugserver_gpr_x21, - debugserver_gpr_x22, - debugserver_gpr_x23, - debugserver_gpr_x24, - debugserver_gpr_x25, - debugserver_gpr_x26, - debugserver_gpr_x27, - debugserver_gpr_x28, - debugserver_gpr_fp, // x29 - debugserver_gpr_lr, // x30 - debugserver_gpr_sp, // sp aka xsp - debugserver_gpr_pc, - debugserver_gpr_cpsr, - debugserver_vfp_v0, - debugserver_vfp_v1, - debugserver_vfp_v2, - debugserver_vfp_v3, - debugserver_vfp_v4, - debugserver_vfp_v5, - debugserver_vfp_v6, - debugserver_vfp_v7, - debugserver_vfp_v8, - debugserver_vfp_v9, - debugserver_vfp_v10, - debugserver_vfp_v11, - debugserver_vfp_v12, - debugserver_vfp_v13, - debugserver_vfp_v14, - debugserver_vfp_v15, - debugserver_vfp_v16, - debugserver_vfp_v17, - debugserver_vfp_v18, - debugserver_vfp_v19, - debugserver_vfp_v20, - debugserver_vfp_v21, - debugserver_vfp_v22, - debugserver_vfp_v23, - debugserver_vfp_v24, - debugserver_vfp_v25, - debugserver_vfp_v26, - debugserver_vfp_v27, - debugserver_vfp_v28, - debugserver_vfp_v29, - debugserver_vfp_v30, - debugserver_vfp_v31, - debugserver_vfp_fpsr, - debugserver_vfp_fpcr -}; - -const char *g_contained_x0[]{"x0", NULL}; -const char *g_contained_x1[]{"x1", NULL}; -const char *g_contained_x2[]{"x2", NULL}; -const char *g_contained_x3[]{"x3", NULL}; -const char *g_contained_x4[]{"x4", NULL}; -const char *g_contained_x5[]{"x5", NULL}; -const char *g_contained_x6[]{"x6", NULL}; -const char *g_contained_x7[]{"x7", NULL}; -const char *g_contained_x8[]{"x8", NULL}; -const char *g_contained_x9[]{"x9", NULL}; -const char *g_contained_x10[]{"x10", NULL}; -const char *g_contained_x11[]{"x11", NULL}; -const char *g_contained_x12[]{"x12", NULL}; -const char *g_contained_x13[]{"x13", NULL}; -const char *g_contained_x14[]{"x14", NULL}; -const char *g_contained_x15[]{"x15", NULL}; -const char *g_contained_x16[]{"x16", NULL}; -const char *g_contained_x17[]{"x17", NULL}; -const char *g_contained_x18[]{"x18", NULL}; -const char *g_contained_x19[]{"x19", NULL}; -const char *g_contained_x20[]{"x20", NULL}; -const char *g_contained_x21[]{"x21", NULL}; -const char *g_contained_x22[]{"x22", NULL}; -const char *g_contained_x23[]{"x23", NULL}; -const char *g_contained_x24[]{"x24", NULL}; -const char *g_contained_x25[]{"x25", NULL}; -const char *g_contained_x26[]{"x26", NULL}; -const char *g_contained_x27[]{"x27", NULL}; -const char *g_contained_x28[]{"x28", NULL}; - -const char *g_invalidate_x0[]{"x0", "w0", NULL}; -const char *g_invalidate_x1[]{"x1", "w1", NULL}; -const char *g_invalidate_x2[]{"x2", "w2", NULL}; -const char *g_invalidate_x3[]{"x3", "w3", NULL}; -const char *g_invalidate_x4[]{"x4", "w4", NULL}; -const char *g_invalidate_x5[]{"x5", "w5", NULL}; -const char *g_invalidate_x6[]{"x6", "w6", NULL}; -const char *g_invalidate_x7[]{"x7", "w7", NULL}; -const char *g_invalidate_x8[]{"x8", "w8", NULL}; -const char *g_invalidate_x9[]{"x9", "w9", NULL}; -const char *g_invalidate_x10[]{"x10", "w10", NULL}; -const char *g_invalidate_x11[]{"x11", "w11", NULL}; -const char *g_invalidate_x12[]{"x12", "w12", NULL}; -const char *g_invalidate_x13[]{"x13", "w13", NULL}; -const char *g_invalidate_x14[]{"x14", "w14", NULL}; -const char *g_invalidate_x15[]{"x15", "w15", NULL}; -const char *g_invalidate_x16[]{"x16", "w16", NULL}; -const char *g_invalidate_x17[]{"x17", "w17", NULL}; -const char *g_invalidate_x18[]{"x18", "w18", NULL}; -const char *g_invalidate_x19[]{"x19", "w19", NULL}; -const char *g_invalidate_x20[]{"x20", "w20", NULL}; -const char *g_invalidate_x21[]{"x21", "w21", NULL}; -const char *g_invalidate_x22[]{"x22", "w22", NULL}; -const char *g_invalidate_x23[]{"x23", "w23", NULL}; -const char *g_invalidate_x24[]{"x24", "w24", NULL}; -const char *g_invalidate_x25[]{"x25", "w25", NULL}; -const char *g_invalidate_x26[]{"x26", "w26", NULL}; -const char *g_invalidate_x27[]{"x27", "w27", NULL}; -const char *g_invalidate_x28[]{"x28", "w28", NULL}; - -#define GPR_OFFSET_IDX(idx) (offsetof(DNBArchMachARM64::GPR, __x[idx])) - -#define GPR_OFFSET_NAME(reg) (offsetof(DNBArchMachARM64::GPR, __##reg)) - -// 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, 8, GPR_OFFSET_IDX(idx), \ - dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, \ - g_invalidate_x##idx \ - } -#define DEFINE_GPR_NAME(reg, alt, gen) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_NAME(reg), \ - dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, NULL \ - } -#define DEFINE_PSEUDO_GPR_IDX(idx, reg) \ - { \ - e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, 4, 0, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - g_contained_x##idx, g_invalidate_x##idx \ - } - -//_STRUCT_ARM_THREAD_STATE64 -//{ -// uint64_t x[29]; /* General purpose registers x0-x28 */ -// uint64_t fp; /* Frame pointer x29 */ -// uint64_t lr; /* Link register x30 */ -// uint64_t sp; /* Stack pointer x31 */ -// uint64_t pc; /* Program counter */ -// uint32_t cpsr; /* Current program status register */ -//}; - -// General purpose registers -const DNBRegisterInfo DNBArchMachARM64::g_gpr_registers[] = { - DEFINE_GPR_IDX(0, x0, "arg1", GENERIC_REGNUM_ARG1), - DEFINE_GPR_IDX(1, x1, "arg2", GENERIC_REGNUM_ARG2), - DEFINE_GPR_IDX(2, x2, "arg3", GENERIC_REGNUM_ARG3), - DEFINE_GPR_IDX(3, x3, "arg4", GENERIC_REGNUM_ARG4), - DEFINE_GPR_IDX(4, x4, "arg5", GENERIC_REGNUM_ARG5), - DEFINE_GPR_IDX(5, x5, "arg6", GENERIC_REGNUM_ARG6), - DEFINE_GPR_IDX(6, x6, "arg7", GENERIC_REGNUM_ARG7), - DEFINE_GPR_IDX(7, x7, "arg8", GENERIC_REGNUM_ARG8), - DEFINE_GPR_IDX(8, x8, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(9, x9, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(10, x10, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(11, x11, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(12, x12, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(13, x13, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(14, x14, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(15, x15, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(16, x16, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(17, x17, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(18, x18, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(19, x19, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(20, x20, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(21, x21, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(22, x22, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(23, x23, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(24, x24, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(25, x25, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(26, x26, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(27, x27, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_IDX(28, x28, NULL, INVALID_NUB_REGNUM), - DEFINE_GPR_NAME(fp, "x29", GENERIC_REGNUM_FP), - DEFINE_GPR_NAME(lr, "x30", GENERIC_REGNUM_RA), - DEFINE_GPR_NAME(sp, "xsp", GENERIC_REGNUM_SP), - DEFINE_GPR_NAME(pc, NULL, GENERIC_REGNUM_PC), - - // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp, - // lr. - // this should be specified for arm64 too even though debugserver is only - // used for - // userland debugging. - {e_regSetGPR, gpr_cpsr, "cpsr", "flags", Uint, Hex, 4, - GPR_OFFSET_NAME(cpsr), dwarf_elr_mode, dwarf_elr_mode, INVALID_NUB_REGNUM, - debugserver_gpr_cpsr, NULL, NULL}, - - DEFINE_PSEUDO_GPR_IDX(0, w0), - DEFINE_PSEUDO_GPR_IDX(1, w1), - DEFINE_PSEUDO_GPR_IDX(2, w2), - DEFINE_PSEUDO_GPR_IDX(3, w3), - DEFINE_PSEUDO_GPR_IDX(4, w4), - DEFINE_PSEUDO_GPR_IDX(5, w5), - DEFINE_PSEUDO_GPR_IDX(6, w6), - DEFINE_PSEUDO_GPR_IDX(7, w7), - DEFINE_PSEUDO_GPR_IDX(8, w8), - DEFINE_PSEUDO_GPR_IDX(9, w9), - DEFINE_PSEUDO_GPR_IDX(10, w10), - DEFINE_PSEUDO_GPR_IDX(11, w11), - DEFINE_PSEUDO_GPR_IDX(12, w12), - DEFINE_PSEUDO_GPR_IDX(13, w13), - DEFINE_PSEUDO_GPR_IDX(14, w14), - DEFINE_PSEUDO_GPR_IDX(15, w15), - DEFINE_PSEUDO_GPR_IDX(16, w16), - DEFINE_PSEUDO_GPR_IDX(17, w17), - DEFINE_PSEUDO_GPR_IDX(18, w18), - DEFINE_PSEUDO_GPR_IDX(19, w19), - DEFINE_PSEUDO_GPR_IDX(20, w20), - DEFINE_PSEUDO_GPR_IDX(21, w21), - DEFINE_PSEUDO_GPR_IDX(22, w22), - DEFINE_PSEUDO_GPR_IDX(23, w23), - DEFINE_PSEUDO_GPR_IDX(24, w24), - DEFINE_PSEUDO_GPR_IDX(25, w25), - DEFINE_PSEUDO_GPR_IDX(26, w26), - DEFINE_PSEUDO_GPR_IDX(27, w27), - DEFINE_PSEUDO_GPR_IDX(28, w28)}; - -const char *g_contained_v0[]{"v0", NULL}; -const char *g_contained_v1[]{"v1", NULL}; -const char *g_contained_v2[]{"v2", NULL}; -const char *g_contained_v3[]{"v3", NULL}; -const char *g_contained_v4[]{"v4", NULL}; -const char *g_contained_v5[]{"v5", NULL}; -const char *g_contained_v6[]{"v6", NULL}; -const char *g_contained_v7[]{"v7", NULL}; -const char *g_contained_v8[]{"v8", NULL}; -const char *g_contained_v9[]{"v9", NULL}; -const char *g_contained_v10[]{"v10", NULL}; -const char *g_contained_v11[]{"v11", NULL}; -const char *g_contained_v12[]{"v12", NULL}; -const char *g_contained_v13[]{"v13", NULL}; -const char *g_contained_v14[]{"v14", NULL}; -const char *g_contained_v15[]{"v15", NULL}; -const char *g_contained_v16[]{"v16", NULL}; -const char *g_contained_v17[]{"v17", NULL}; -const char *g_contained_v18[]{"v18", NULL}; -const char *g_contained_v19[]{"v19", NULL}; -const char *g_contained_v20[]{"v20", NULL}; -const char *g_contained_v21[]{"v21", NULL}; -const char *g_contained_v22[]{"v22", NULL}; -const char *g_contained_v23[]{"v23", NULL}; -const char *g_contained_v24[]{"v24", NULL}; -const char *g_contained_v25[]{"v25", NULL}; -const char *g_contained_v26[]{"v26", NULL}; -const char *g_contained_v27[]{"v27", NULL}; -const char *g_contained_v28[]{"v28", NULL}; -const char *g_contained_v29[]{"v29", NULL}; -const char *g_contained_v30[]{"v30", NULL}; -const char *g_contained_v31[]{"v31", NULL}; - -const char *g_invalidate_v0[]{"v0", "d0", "s0", NULL}; -const char *g_invalidate_v1[]{"v1", "d1", "s1", NULL}; -const char *g_invalidate_v2[]{"v2", "d2", "s2", NULL}; -const char *g_invalidate_v3[]{"v3", "d3", "s3", NULL}; -const char *g_invalidate_v4[]{"v4", "d4", "s4", NULL}; -const char *g_invalidate_v5[]{"v5", "d5", "s5", NULL}; -const char *g_invalidate_v6[]{"v6", "d6", "s6", NULL}; -const char *g_invalidate_v7[]{"v7", "d7", "s7", NULL}; -const char *g_invalidate_v8[]{"v8", "d8", "s8", NULL}; -const char *g_invalidate_v9[]{"v9", "d9", "s9", NULL}; -const char *g_invalidate_v10[]{"v10", "d10", "s10", NULL}; -const char *g_invalidate_v11[]{"v11", "d11", "s11", NULL}; -const char *g_invalidate_v12[]{"v12", "d12", "s12", NULL}; -const char *g_invalidate_v13[]{"v13", "d13", "s13", NULL}; -const char *g_invalidate_v14[]{"v14", "d14", "s14", NULL}; -const char *g_invalidate_v15[]{"v15", "d15", "s15", NULL}; -const char *g_invalidate_v16[]{"v16", "d16", "s16", NULL}; -const char *g_invalidate_v17[]{"v17", "d17", "s17", NULL}; -const char *g_invalidate_v18[]{"v18", "d18", "s18", NULL}; -const char *g_invalidate_v19[]{"v19", "d19", "s19", NULL}; -const char *g_invalidate_v20[]{"v20", "d20", "s20", NULL}; -const char *g_invalidate_v21[]{"v21", "d21", "s21", NULL}; -const char *g_invalidate_v22[]{"v22", "d22", "s22", NULL}; -const char *g_invalidate_v23[]{"v23", "d23", "s23", NULL}; -const char *g_invalidate_v24[]{"v24", "d24", "s24", NULL}; -const char *g_invalidate_v25[]{"v25", "d25", "s25", NULL}; -const char *g_invalidate_v26[]{"v26", "d26", "s26", NULL}; -const char *g_invalidate_v27[]{"v27", "d27", "s27", NULL}; -const char *g_invalidate_v28[]{"v28", "d28", "s28", NULL}; -const char *g_invalidate_v29[]{"v29", "d29", "s29", NULL}; -const char *g_invalidate_v30[]{"v30", "d30", "s30", NULL}; -const char *g_invalidate_v31[]{"v31", "d31", "s31", NULL}; - -#if defined(__arm64__) || defined(__aarch64__) -#define VFP_V_OFFSET_IDX(idx) \ - (offsetof(DNBArchMachARM64::FPU, __v) + (idx * 16) + \ - offsetof(DNBArchMachARM64::Context, vfp)) -#else -#define VFP_V_OFFSET_IDX(idx) \ - (offsetof(DNBArchMachARM64::FPU, opaque) + (idx * 16) + \ - offsetof(DNBArchMachARM64::Context, vfp)) -#endif -#define VFP_OFFSET_NAME(reg) \ - (offsetof(DNBArchMachARM64::FPU, reg) + \ - offsetof(DNBArchMachARM64::Context, vfp)) -#define EXC_OFFSET(reg) \ - (offsetof(DNBArchMachARM64::EXC, reg) + \ - offsetof(DNBArchMachARM64::Context, exc)) - -//#define FLOAT_FORMAT Float -#define DEFINE_VFP_V_IDX(idx) \ - { \ - e_regSetVFP, vfp_v##idx, "v" #idx, "q" #idx, Vector, VectorOfUInt8, 16, \ - VFP_V_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_v##idx, \ - INVALID_NUB_REGNUM, debugserver_vfp_v##idx, NULL, g_invalidate_v##idx \ - } -#define DEFINE_PSEUDO_VFP_S_IDX(idx) \ - { \ - e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, Float, 4, 0, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx \ - } -#define DEFINE_PSEUDO_VFP_D_IDX(idx) \ - { \ - e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, 0, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx \ - } - -// Floating point registers -const DNBRegisterInfo DNBArchMachARM64::g_vfp_registers[] = { - DEFINE_VFP_V_IDX(0), - DEFINE_VFP_V_IDX(1), - DEFINE_VFP_V_IDX(2), - DEFINE_VFP_V_IDX(3), - DEFINE_VFP_V_IDX(4), - DEFINE_VFP_V_IDX(5), - DEFINE_VFP_V_IDX(6), - DEFINE_VFP_V_IDX(7), - DEFINE_VFP_V_IDX(8), - DEFINE_VFP_V_IDX(9), - DEFINE_VFP_V_IDX(10), - DEFINE_VFP_V_IDX(11), - DEFINE_VFP_V_IDX(12), - DEFINE_VFP_V_IDX(13), - DEFINE_VFP_V_IDX(14), - DEFINE_VFP_V_IDX(15), - DEFINE_VFP_V_IDX(16), - DEFINE_VFP_V_IDX(17), - DEFINE_VFP_V_IDX(18), - DEFINE_VFP_V_IDX(19), - DEFINE_VFP_V_IDX(20), - DEFINE_VFP_V_IDX(21), - DEFINE_VFP_V_IDX(22), - DEFINE_VFP_V_IDX(23), - DEFINE_VFP_V_IDX(24), - DEFINE_VFP_V_IDX(25), - DEFINE_VFP_V_IDX(26), - DEFINE_VFP_V_IDX(27), - DEFINE_VFP_V_IDX(28), - DEFINE_VFP_V_IDX(29), - DEFINE_VFP_V_IDX(30), - DEFINE_VFP_V_IDX(31), - {e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, - VFP_V_OFFSET_IDX(32) + 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, - VFP_V_OFFSET_IDX(32) + 4, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, - - DEFINE_PSEUDO_VFP_S_IDX(0), - DEFINE_PSEUDO_VFP_S_IDX(1), - DEFINE_PSEUDO_VFP_S_IDX(2), - DEFINE_PSEUDO_VFP_S_IDX(3), - DEFINE_PSEUDO_VFP_S_IDX(4), - DEFINE_PSEUDO_VFP_S_IDX(5), - DEFINE_PSEUDO_VFP_S_IDX(6), - DEFINE_PSEUDO_VFP_S_IDX(7), - DEFINE_PSEUDO_VFP_S_IDX(8), - DEFINE_PSEUDO_VFP_S_IDX(9), - DEFINE_PSEUDO_VFP_S_IDX(10), - DEFINE_PSEUDO_VFP_S_IDX(11), - DEFINE_PSEUDO_VFP_S_IDX(12), - DEFINE_PSEUDO_VFP_S_IDX(13), - DEFINE_PSEUDO_VFP_S_IDX(14), - DEFINE_PSEUDO_VFP_S_IDX(15), - DEFINE_PSEUDO_VFP_S_IDX(16), - DEFINE_PSEUDO_VFP_S_IDX(17), - DEFINE_PSEUDO_VFP_S_IDX(18), - DEFINE_PSEUDO_VFP_S_IDX(19), - DEFINE_PSEUDO_VFP_S_IDX(20), - DEFINE_PSEUDO_VFP_S_IDX(21), - DEFINE_PSEUDO_VFP_S_IDX(22), - DEFINE_PSEUDO_VFP_S_IDX(23), - DEFINE_PSEUDO_VFP_S_IDX(24), - DEFINE_PSEUDO_VFP_S_IDX(25), - DEFINE_PSEUDO_VFP_S_IDX(26), - DEFINE_PSEUDO_VFP_S_IDX(27), - DEFINE_PSEUDO_VFP_S_IDX(28), - DEFINE_PSEUDO_VFP_S_IDX(29), - DEFINE_PSEUDO_VFP_S_IDX(30), - DEFINE_PSEUDO_VFP_S_IDX(31), - - DEFINE_PSEUDO_VFP_D_IDX(0), - DEFINE_PSEUDO_VFP_D_IDX(1), - DEFINE_PSEUDO_VFP_D_IDX(2), - DEFINE_PSEUDO_VFP_D_IDX(3), - DEFINE_PSEUDO_VFP_D_IDX(4), - DEFINE_PSEUDO_VFP_D_IDX(5), - DEFINE_PSEUDO_VFP_D_IDX(6), - DEFINE_PSEUDO_VFP_D_IDX(7), - DEFINE_PSEUDO_VFP_D_IDX(8), - DEFINE_PSEUDO_VFP_D_IDX(9), - DEFINE_PSEUDO_VFP_D_IDX(10), - DEFINE_PSEUDO_VFP_D_IDX(11), - DEFINE_PSEUDO_VFP_D_IDX(12), - DEFINE_PSEUDO_VFP_D_IDX(13), - DEFINE_PSEUDO_VFP_D_IDX(14), - DEFINE_PSEUDO_VFP_D_IDX(15), - DEFINE_PSEUDO_VFP_D_IDX(16), - DEFINE_PSEUDO_VFP_D_IDX(17), - DEFINE_PSEUDO_VFP_D_IDX(18), - DEFINE_PSEUDO_VFP_D_IDX(19), - DEFINE_PSEUDO_VFP_D_IDX(20), - DEFINE_PSEUDO_VFP_D_IDX(21), - DEFINE_PSEUDO_VFP_D_IDX(22), - DEFINE_PSEUDO_VFP_D_IDX(23), - DEFINE_PSEUDO_VFP_D_IDX(24), - DEFINE_PSEUDO_VFP_D_IDX(25), - DEFINE_PSEUDO_VFP_D_IDX(26), - DEFINE_PSEUDO_VFP_D_IDX(27), - DEFINE_PSEUDO_VFP_D_IDX(28), - DEFINE_PSEUDO_VFP_D_IDX(29), - DEFINE_PSEUDO_VFP_D_IDX(30), - DEFINE_PSEUDO_VFP_D_IDX(31) - -}; - -//_STRUCT_ARM_EXCEPTION_STATE64 -//{ -// uint64_t far; /* Virtual Fault Address */ -// uint32_t esr; /* Exception syndrome */ -// uint32_t exception; /* number of arm exception taken */ -//}; - -// Exception registers -const DNBRegisterInfo DNBArchMachARM64::g_exc_registers[] = { - {e_regSetEXC, exc_far, "far", NULL, Uint, Hex, 8, EXC_OFFSET(__far), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetEXC, exc_esr, "esr", NULL, Uint, Hex, 4, EXC_OFFSET(__esr), - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, NULL, NULL}, - {e_regSetEXC, exc_exception, "exception", NULL, Uint, Hex, 4, - EXC_OFFSET(__exception), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}}; - -// Number of registers in each register set -const size_t DNBArchMachARM64::k_num_gpr_registers = - sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::k_num_vfp_registers = - sizeof(g_vfp_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::k_num_exc_registers = - sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::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 DNBArchMachARM64::g_reg_sets[] = { - {"ARM64 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 DNBArchMachARM64::k_num_register_sets = - sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); - -const DNBRegisterSetInfo * -DNBArchMachARM64::GetRegisterSetInfo(nub_size_t *num_reg_sets) { - *num_reg_sets = k_num_register_sets; - return g_reg_sets; -} - -bool DNBArchMachARM64::FixGenericRegisterNumber(uint32_t &set, uint32_t ®) { - 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_fp; - 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; - - case GENERIC_REGNUM_ARG1: - case GENERIC_REGNUM_ARG2: - case GENERIC_REGNUM_ARG3: - case GENERIC_REGNUM_ARG4: - case GENERIC_REGNUM_ARG5: - case GENERIC_REGNUM_ARG6: - set = e_regSetGPR; - reg = gpr_x0 + reg - GENERIC_REGNUM_ARG1; - break; - - default: - return false; - } - } - return true; -} -bool DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) { - if (!FixGenericRegisterNumber(set, reg)) - 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 <= gpr_pc) { - value->value.uint64 = m_state.context.gpr.__x[reg]; - return true; - } else if (reg == gpr_cpsr) { - value->value.uint32 = m_state.context.gpr.__cpsr; - return true; - } - break; - - case e_regSetVFP: - - if (reg >= vfp_v0 && reg <= vfp_v31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_v0], - 16); -#else - memcpy(&value->value.v_uint8, - ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), - 16); -#endif - return true; - } else if (reg == vfp_fpsr) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.uint32, &m_state.context.vfp.__fpsr, 4); -#else - memcpy(&value->value.uint32, - ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0, 4); -#endif - return true; - } else if (reg == vfp_fpcr) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.uint32, &m_state.context.vfp.__fpcr, 4); -#else - memcpy(&value->value.uint32, - ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 4, 4); -#endif - return true; - } else if (reg >= vfp_s0 && reg <= vfp_s31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_s0], - 4); -#else - memcpy(&value->value.v_uint8, - ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), - 4); -#endif - return true; - } else if (reg >= vfp_d0 && reg <= vfp_d31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_d0], - 8); -#else - memcpy(&value->value.v_uint8, - ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), - 8); -#endif - return true; - } - break; - - case e_regSetEXC: - if (reg == exc_far) { - value->value.uint64 = m_state.context.exc.__far; - return true; - } else if (reg == exc_esr) { - value->value.uint32 = m_state.context.exc.__esr; - return true; - } else if (reg == exc_exception) { - value->value.uint32 = m_state.context.exc.__exception; - return true; - } - break; - } - } - return false; -} - -bool DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value) { - if (!FixGenericRegisterNumber(set, reg)) - 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 <= gpr_pc) { - m_state.context.gpr.__x[reg] = value->value.uint64; - success = true; - } else if (reg == gpr_cpsr) { - m_state.context.gpr.__cpsr = value->value.uint32; - success = true; - } - break; - - case e_regSetVFP: - if (reg >= vfp_v0 && reg <= vfp_v31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&m_state.context.vfp.__v[reg - vfp_v0], &value->value.v_uint8, - 16); -#else - memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), - &value->value.v_uint8, 16); -#endif - success = true; - } else if (reg == vfp_fpsr) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&m_state.context.vfp.__fpsr, &value->value.uint32, 4); -#else - memcpy(((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0, - &value->value.uint32, 4); -#endif - success = true; - } else if (reg == vfp_fpcr) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&m_state.context.vfp.__fpcr, &value->value.uint32, 4); -#else - memcpy(((uint8_t *)m_state.context.vfp.opaque) + (32 * 16) + 4, - &value->value.uint32, 4); -#endif - success = true; - } else if (reg >= vfp_s0 && reg <= vfp_s31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&m_state.context.vfp.__v[reg - vfp_s0], &value->value.v_uint8, - 4); -#else - memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), - &value->value.v_uint8, 4); -#endif - success = true; - } else if (reg >= vfp_d0 && reg <= vfp_d31) { -#if defined(__arm64__) || defined(__aarch64__) - memcpy(&m_state.context.vfp.__v[reg - vfp_d0], &value->value.v_uint8, - 8); -#else - memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), - &value->value.v_uint8, 8); -#endif - success = true; - } - break; - - case e_regSetEXC: - if (reg == exc_far) { - m_state.context.exc.__far = value->value.uint64; - success = true; - } else if (reg == exc_esr) { - m_state.context.exc.__esr = value->value.uint32; - success = true; - } else if (reg == exc_exception) { - m_state.context.exc.__exception = value->value.uint32; - success = true; - } - break; - } - } - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; -} - -kern_return_t DNBArchMachARM64::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 DNBArchMachARM64::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 DNBArchMachARM64::RegisterSetStateIsValid(int set) const { - return m_state.RegsAreValid(set); -} - -nub_size_t DNBArchMachARM64::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, - "DNBArchMachARM64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, - buf_len, size); - // Return the size of the register context even if NULL was passed in - return size; -} - -nub_size_t DNBArchMachARM64::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 = (uint8_t *)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 - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert(bytes_written == size); - SetGPRState(); - SetVFPState(); - SetEXCState(); - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchMachARM64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, - buf_len, size); - return size; -} - -uint32_t DNBArchMachARM64::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, "DNBArchMachARM64::SaveRegisterState () " - "error: GPR regs failed to read: %u ", - kret); - } else if ((kret = GetVFPState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::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 DNBArchMachARM64::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, "DNBArchMachARM64::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, "DNBArchMachARM64::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_THREAD_STATE64_COUNT) -#endif // #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) diff --git a/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h b/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h deleted file mode 100644 index cde0abf42d53..000000000000 --- a/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h +++ /dev/null @@ -1,249 +0,0 @@ -//===-- DNBArchMachARM64.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBArchImplARM64_h__ -#define __DNBArchImplARM64_h__ - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include <mach/thread_status.h> -#include <map> - -#if defined(ARM_THREAD_STATE64_COUNT) - -#include "DNBArch.h" - -class MachThread; - -class DNBArchMachARM64 : public DNBArchProtocol { -public: - enum { kMaxNumThumbITBreakpoints = 4 }; - - DNBArchMachARM64(MachThread *thread) - : m_thread(thread), m_state(), m_disabled_watchpoints(), - 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)); - } - - virtual ~DNBArchMachARM64() {} - - static void Initialize(); - static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState(); - virtual bool RestoreRegisterState(uint32_t save_id); - - virtual kern_return_t GetRegisterState(int set, bool force); - virtual kern_return_t SetRegisterState(int set); - virtual bool RegisterSetStateIsValid(int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data &exc); - - static DNBArchProtocol *Create(MachThread *thread); - static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); - static uint32_t GetCPUType(); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task); - virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task); - virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, - bool also_set_on_task); - -protected: - kern_return_t EnableHardwareSingleStep(bool enable); - static bool FixGenericRegisterNumber(uint32_t &set, uint32_t ®); - - typedef enum RegisterSetTag { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, // ARM_THREAD_STATE64, - e_regSetVFP, // ARM_NEON_STATE64, - e_regSetEXC, // ARM_EXCEPTION_STATE64, - e_regSetDBG, // ARM_DEBUG_STATE64, - kNumRegisterSets - } RegisterSet; - - enum { - e_regSetGPRCount = ARM_THREAD_STATE64_COUNT, - e_regSetVFPCount = ARM_NEON_STATE64_COUNT, - e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT, - e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT, - }; - - enum { Read = 0, Write = 1, kNumErrors = 2 }; - - typedef arm_thread_state64_t GPR; - typedef arm_neon_state64_t FPU; - typedef arm_exception_state64_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; - arm_debug_state64_t 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); } - - void InvalidateAllRegisterStates() { SetError(e_regSetALL, 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); - - // Helper functions for watchpoint implementaions. - - typedef arm_debug_state64_t DBG; - - void ClearWatchpointOccurred(); - bool HasWatchpointOccurred(); - 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); - virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); - virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - - class disabled_watchpoint { - public: - disabled_watchpoint() { - addr = 0; - control = 0; - } - nub_addr_t addr; - uint32_t control; - }; - -protected: - MachThread *m_thread; - State m_state; - arm_debug_state64_t m_dbg_save; - - // arm64 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<disabled_watchpoint> m_disabled_watchpoints; - - // 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<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (ARM_THREAD_STATE64_COUNT) -#endif // #if defined (__arm__) -#endif // #ifndef __DNBArchImplARM64_h__ diff --git a/tools/debugserver/source/MacOSX/dbgnub-mig.defs b/tools/debugserver/source/MacOSX/dbgnub-mig.defs deleted file mode 100644 index cd5be1700704..000000000000 --- a/tools/debugserver/source/MacOSX/dbgnub-mig.defs +++ /dev/null @@ -1,5 +0,0 @@ -/* - * nub.defs - */ - -#import <mach/mach_exc.defs> diff --git a/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp deleted file mode 100644 index ba37a328ecf3..000000000000 --- a/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ /dev/null @@ -1,2387 +0,0 @@ -//===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__i386__) || defined(__x86_64__) - -#include <sys/cdefs.h> - -#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<uint32_t>(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<uint32_t>(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::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::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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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", NULL, 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<uint32_t>(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/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h deleted file mode 100644 index ce56a540e092..000000000000 --- a/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ /dev/null @@ -1,239 +0,0 @@ -//===-- DNBArchImplI386.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBArchImplI386_h__ -#define __DNBArchImplI386_h__ - -#if defined(__i386__) || defined(__x86_64__) - -#include "DNBArch.h" -#include "MachRegisterStatesI386.h" - -#include <map> - -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(); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState(); - virtual bool RestoreRegisterState(uint32_t save_id); - - virtual kern_return_t GetRegisterState(int set, bool force); - virtual kern_return_t SetRegisterState(int set); - virtual bool RegisterSetStateIsValid(int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data &exc); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task); - virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - -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; - - typedef enum RegisterSetTag { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPU, - e_regSetEXC, - e_regSetDBG, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag { - 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) - } RegisterSetWordSize; - - 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(); - - // 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); - - virtual bool StartTransForHWP(); - virtual bool RollbackTransForHWP(); - virtual bool FinishTransForHWP(); - 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<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (__i386__) || defined (__x86_64__) -#endif // #ifndef __DNBArchImplI386_h__ diff --git a/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h b/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h deleted file mode 100644 index e51ecfd24bef..000000000000 --- a/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h +++ /dev/null @@ -1,242 +0,0 @@ -//===-- MachRegisterStatesI386.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Sean Callanan on 3/16/11. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachRegisterStatesI386_h__ -#define __MachRegisterStatesI386_h__ - -#include <inttypes.h> - -#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 diff --git a/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp b/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp deleted file mode 100644 index 1653287430ad..000000000000 --- a/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp +++ /dev/null @@ -1,492 +0,0 @@ -//===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) - -#if __DARWIN_UNIX03 -#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) __##reg -#else -#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) reg -#endif - -#include "MacOSX/ppc/DNBArchImpl.h" -#include "DNBBreakpoint.h" -#include "DNBLog.h" -#include "DNBRegisterInfo.h" -#include "MacOSX/MachThread.h" - -static const uint8_t g_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; - -const uint8_t *DNBArchMachPPC::SoftwareBreakpointOpcode(nub_size_t size) { - if (size == 4) - return g_breakpoint_opcode; - return NULL; -} - -uint32_t DNBArchMachPPC::GetCPUType() { return CPU_TYPE_POWERPC; } - -uint64_t DNBArchMachPPC::GetPC(uint64_t failValue) { - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0); - return failValue; -} - -kern_return_t DNBArchMachPPC::SetPC(uint64_t value) { - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) { - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0) = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; -} - -uint64_t DNBArchMachPPC::GetSP(uint64_t failValue) { - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(r1); - return failValue; -} - -kern_return_t DNBArchMachPPC::GetGPRState(bool force) { - if (force || m_state.GetError(e_regSetGPR, Read)) { - mach_msg_type_number_t count = e_regSetWordSizeGPR; - m_state.SetError(e_regSetGPR, Read, - ::thread_get_state(m_thread->MachPortNumber(), e_regSetGPR, - (thread_state_t)&m_state.gpr, &count)); - } - return m_state.GetError(e_regSetGPR, Read); -} - -kern_return_t DNBArchMachPPC::GetFPRState(bool force) { - if (force || m_state.GetError(e_regSetFPR, Read)) { - mach_msg_type_number_t count = e_regSetWordSizeFPR; - m_state.SetError(e_regSetFPR, Read, - ::thread_get_state(m_thread->MachPortNumber(), e_regSetFPR, - (thread_state_t)&m_state.fpr, &count)); - } - return m_state.GetError(e_regSetFPR, Read); -} - -kern_return_t DNBArchMachPPC::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(), e_regSetEXC, - (thread_state_t)&m_state.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); -} - -kern_return_t DNBArchMachPPC::GetVECState(bool force) { - if (force || m_state.GetError(e_regSetVEC, Read)) { - mach_msg_type_number_t count = e_regSetWordSizeVEC; - m_state.SetError(e_regSetVEC, Read, - ::thread_get_state(m_thread->MachPortNumber(), e_regSetVEC, - (thread_state_t)&m_state.vec, &count)); - } - return m_state.GetError(e_regSetVEC, Read); -} - -kern_return_t DNBArchMachPPC::SetGPRState() { - m_state.SetError(e_regSetGPR, Write, - ::thread_set_state(m_thread->MachPortNumber(), e_regSetGPR, - (thread_state_t)&m_state.gpr, - e_regSetWordSizeGPR)); - return m_state.GetError(e_regSetGPR, Write); -} - -kern_return_t DNBArchMachPPC::SetFPRState() { - m_state.SetError(e_regSetFPR, Write, - ::thread_set_state(m_thread->MachPortNumber(), e_regSetFPR, - (thread_state_t)&m_state.fpr, - e_regSetWordSizeFPR)); - return m_state.GetError(e_regSetFPR, Write); -} - -kern_return_t DNBArchMachPPC::SetEXCState() { - m_state.SetError(e_regSetEXC, Write, - ::thread_set_state(m_thread->MachPortNumber(), e_regSetEXC, - (thread_state_t)&m_state.exc, - e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); -} - -kern_return_t DNBArchMachPPC::SetVECState() { - m_state.SetError(e_regSetVEC, Write, - ::thread_set_state(m_thread->MachPortNumber(), e_regSetVEC, - (thread_state_t)&m_state.vec, - e_regSetWordSizeVEC)); - return m_state.GetError(e_regSetVEC, Write); -} - -bool DNBArchMachPPC::ThreadWillResume() { - bool success = true; - - // 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 - success = EnableHardwareSingleStep(true) == KERN_SUCCESS; - } - return success; -} - -bool DNBArchMachPPC::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; -} - -// Set the single step bit in the processor status register. -kern_return_t DNBArchMachPPC::EnableHardwareSingleStep(bool enable) { - DNBLogThreadedIf(LOG_STEP, - "DNBArchMachPPC::EnableHardwareSingleStep( enable = %d )", - enable); - if (GetGPRState(false) == KERN_SUCCESS) { - const uint32_t trace_bit = 0x400; - if (enable) - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) |= trace_bit; - else - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); -} - -//---------------------------------------------------------------------- -// Register information definitions for 32 bit PowerPC. -//---------------------------------------------------------------------- - -enum gpr_regnums { - e_regNumGPR_srr0, - e_regNumGPR_srr1, - e_regNumGPR_r0, - e_regNumGPR_r1, - e_regNumGPR_r2, - e_regNumGPR_r3, - e_regNumGPR_r4, - e_regNumGPR_r5, - e_regNumGPR_r6, - e_regNumGPR_r7, - e_regNumGPR_r8, - e_regNumGPR_r9, - e_regNumGPR_r10, - e_regNumGPR_r11, - e_regNumGPR_r12, - e_regNumGPR_r13, - e_regNumGPR_r14, - e_regNumGPR_r15, - e_regNumGPR_r16, - e_regNumGPR_r17, - e_regNumGPR_r18, - e_regNumGPR_r19, - e_regNumGPR_r20, - e_regNumGPR_r21, - e_regNumGPR_r22, - e_regNumGPR_r23, - e_regNumGPR_r24, - e_regNumGPR_r25, - e_regNumGPR_r26, - e_regNumGPR_r27, - e_regNumGPR_r28, - e_regNumGPR_r29, - e_regNumGPR_r30, - e_regNumGPR_r31, - e_regNumGPR_cr, - e_regNumGPR_xer, - e_regNumGPR_lr, - e_regNumGPR_ctr, - e_regNumGPR_mq, - e_regNumGPR_vrsave -}; - -// General purpose registers -static DNBRegisterInfo g_gpr_registers[] = { - {"srr0", Uint, 4, Hex}, {"srr1", Uint, 4, Hex}, {"r0", Uint, 4, Hex}, - {"r1", Uint, 4, Hex}, {"r2", Uint, 4, Hex}, {"r3", Uint, 4, Hex}, - {"r4", Uint, 4, Hex}, {"r5", Uint, 4, Hex}, {"r6", Uint, 4, Hex}, - {"r7", Uint, 4, Hex}, {"r8", Uint, 4, Hex}, {"r9", Uint, 4, Hex}, - {"r10", Uint, 4, Hex}, {"r11", Uint, 4, Hex}, {"r12", Uint, 4, Hex}, - {"r13", Uint, 4, Hex}, {"r14", Uint, 4, Hex}, {"r15", Uint, 4, Hex}, - {"r16", Uint, 4, Hex}, {"r17", Uint, 4, Hex}, {"r18", Uint, 4, Hex}, - {"r19", Uint, 4, Hex}, {"r20", Uint, 4, Hex}, {"r21", Uint, 4, Hex}, - {"r22", Uint, 4, Hex}, {"r23", Uint, 4, Hex}, {"r24", Uint, 4, Hex}, - {"r25", Uint, 4, Hex}, {"r26", Uint, 4, Hex}, {"r27", Uint, 4, Hex}, - {"r28", Uint, 4, Hex}, {"r29", Uint, 4, Hex}, {"r30", Uint, 4, Hex}, - {"r31", Uint, 4, Hex}, {"cr", Uint, 4, Hex}, {"xer", Uint, 4, Hex}, - {"lr", Uint, 4, Hex}, {"ctr", Uint, 4, Hex}, {"mq", Uint, 4, Hex}, - {"vrsave", Uint, 4, Hex}, -}; - -// Floating point registers -static DNBRegisterInfo g_fpr_registers[] = { - {"fp0", IEEE754, 8, Float}, {"fp1", IEEE754, 8, Float}, - {"fp2", IEEE754, 8, Float}, {"fp3", IEEE754, 8, Float}, - {"fp4", IEEE754, 8, Float}, {"fp5", IEEE754, 8, Float}, - {"fp6", IEEE754, 8, Float}, {"fp7", IEEE754, 8, Float}, - {"fp8", IEEE754, 8, Float}, {"fp9", IEEE754, 8, Float}, - {"fp10", IEEE754, 8, Float}, {"fp11", IEEE754, 8, Float}, - {"fp12", IEEE754, 8, Float}, {"fp13", IEEE754, 8, Float}, - {"fp14", IEEE754, 8, Float}, {"fp15", IEEE754, 8, Float}, - {"fp16", IEEE754, 8, Float}, {"fp17", IEEE754, 8, Float}, - {"fp18", IEEE754, 8, Float}, {"fp19", IEEE754, 8, Float}, - {"fp20", IEEE754, 8, Float}, {"fp21", IEEE754, 8, Float}, - {"fp22", IEEE754, 8, Float}, {"fp23", IEEE754, 8, Float}, - {"fp24", IEEE754, 8, Float}, {"fp25", IEEE754, 8, Float}, - {"fp26", IEEE754, 8, Float}, {"fp27", IEEE754, 8, Float}, - {"fp28", IEEE754, 8, Float}, {"fp29", IEEE754, 8, Float}, - {"fp30", IEEE754, 8, Float}, {"fp31", IEEE754, 8, Float}, - {"fpscr", Uint, 4, Hex}}; - -// Exception registers - -static DNBRegisterInfo g_exc_registers[] = {{"dar", Uint, 4, Hex}, - {"dsisr", Uint, 4, Hex}, - {"exception", Uint, 4, Hex}}; - -// Altivec registers -static DNBRegisterInfo g_vec_registers[] = { - {"vr0", Vector, 16, VectorOfFloat32}, - {"vr1", Vector, 16, VectorOfFloat32}, - {"vr2", Vector, 16, VectorOfFloat32}, - {"vr3", Vector, 16, VectorOfFloat32}, - {"vr4", Vector, 16, VectorOfFloat32}, - {"vr5", Vector, 16, VectorOfFloat32}, - {"vr6", Vector, 16, VectorOfFloat32}, - {"vr7", Vector, 16, VectorOfFloat32}, - {"vr8", Vector, 16, VectorOfFloat32}, - {"vr9", Vector, 16, VectorOfFloat32}, - {"vr10", Vector, 16, VectorOfFloat32}, - {"vr11", Vector, 16, VectorOfFloat32}, - {"vr12", Vector, 16, VectorOfFloat32}, - {"vr13", Vector, 16, VectorOfFloat32}, - {"vr14", Vector, 16, VectorOfFloat32}, - {"vr15", Vector, 16, VectorOfFloat32}, - {"vr16", Vector, 16, VectorOfFloat32}, - {"vr17", Vector, 16, VectorOfFloat32}, - {"vr18", Vector, 16, VectorOfFloat32}, - {"vr19", Vector, 16, VectorOfFloat32}, - {"vr20", Vector, 16, VectorOfFloat32}, - {"vr21", Vector, 16, VectorOfFloat32}, - {"vr22", Vector, 16, VectorOfFloat32}, - {"vr23", Vector, 16, VectorOfFloat32}, - {"vr24", Vector, 16, VectorOfFloat32}, - {"vr25", Vector, 16, VectorOfFloat32}, - {"vr26", Vector, 16, VectorOfFloat32}, - {"vr27", Vector, 16, VectorOfFloat32}, - {"vr28", Vector, 16, VectorOfFloat32}, - {"vr29", Vector, 16, VectorOfFloat32}, - {"vr30", Vector, 16, VectorOfFloat32}, - {"vr31", Vector, 16, VectorOfFloat32}, - {"vscr", Uint, 16, Hex}, - {"vrvalid", Uint, 4, Hex}}; - -// Number of registers in each register set -const size_t k_num_gpr_registers = - sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); -const size_t k_num_fpr_registers = - sizeof(g_fpr_registers) / sizeof(DNBRegisterInfo); -const size_t k_num_exc_registers = - sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); -const size_t k_num_vec_registers = - sizeof(g_vec_registers) / sizeof(DNBRegisterInfo); -// Total number of registers for this architecture -const size_t k_num_ppc_registers = k_num_gpr_registers + k_num_fpr_registers + - k_num_exc_registers + k_num_vec_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. -//---------------------------------------------------------------------- -static const DNBRegisterSetInfo g_reg_sets[] = { - {"PowerPC Registers", NULL, k_num_ppc_registers}, - {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, - {"Floating Point Registers", g_fpr_registers, k_num_fpr_registers}, - {"Exception State Registers", g_exc_registers, k_num_exc_registers}, - {"Altivec Registers", g_vec_registers, k_num_vec_registers}}; -// Total number of register sets for this architecture -const size_t k_num_register_sets = - sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); - -const DNBRegisterSetInfo * -DNBArchMachPPC::GetRegisterSetInfo(nub_size_t *num_reg_sets) const { - *num_reg_sets = k_num_register_sets; - return g_reg_sets; -} - -bool DNBArchMachPPC::GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) const { - if (set == REGISTER_SET_GENERIC) { - switch (reg) { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = e_regNumGPR_srr0; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = e_regNumGPR_r1; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - // Return false for now instead of returning r30 as gcc 3.x would - // use a variety of registers for the FP and it takes inspecting - // the stack to make sure there is a frame pointer before we can - // determine the FP. - return false; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = e_regNumGPR_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = e_regNumGPR_srr1; - break; - - default: - return false; - } - } - - if (!m_state.RegsAreValid(set)) - 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.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0))[reg]; - return true; - } - break; - - case e_regSetFPR: - if (reg < 32) { - value->value.float64 = - m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpregs)[reg]; - return true; - } else if (reg == 32) { - value->value.uint32 = - m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpscr); - return true; - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) { - value->value.uint32 = - (&m_state.exc.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(dar))[reg]; - return true; - } - break; - - case e_regSetVEC: - if (reg < k_num_vec_registers) { - if (reg < 33) // FP0 - FP31 and VSCR - { - // Copy all 4 uint32 values for this vector register - value->value.v_uint32[0] = - m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] - [0]; - value->value.v_uint32[1] = - m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] - [1]; - value->value.v_uint32[2] = - m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] - [2]; - value->value.v_uint32[3] = - m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] - [3]; - return true; - } else if (reg == 34) // VRVALID - { - value->value.uint32 = - m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vrvalid); - return true; - } - } - break; - } - } - return false; -} - -kern_return_t DNBArchMachPPC::GetRegisterState(int set, bool force) { - switch (set) { - case e_regSetALL: - return GetGPRState(force) | GetFPRState(force) | GetEXCState(force) | - GetVECState(force); - case e_regSetGPR: - return GetGPRState(force); - case e_regSetFPR: - return GetFPRState(force); - case e_regSetEXC: - return GetEXCState(force); - case e_regSetVEC: - return GetVECState(force); - default: - break; - } - return KERN_INVALID_ARGUMENT; -} - -kern_return_t DNBArchMachPPC::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() | SetFPRState() | SetEXCState() | SetVECState(); - case e_regSetGPR: - return SetGPRState(); - case e_regSetFPR: - return SetFPRState(); - case e_regSetEXC: - return SetEXCState(); - case e_regSetVEC: - return SetVECState(); - default: - break; - } - return KERN_INVALID_ARGUMENT; -} - -bool DNBArchMachPPC::RegisterSetStateIsValid(int set) const { - return m_state.RegsAreValid(set); -} - -#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) diff --git a/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h b/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h deleted file mode 100644 index 8aed9fc0f80a..000000000000 --- a/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h +++ /dev/null @@ -1,160 +0,0 @@ -//===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DebugNubArchMachPPC_h__ -#define __DebugNubArchMachPPC_h__ - -#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) - -#include "DNBArch.h" - -class MachThread; - -class DNBArchMachPPC : public DNBArchProtocol { -public: - DNBArchMachPPC(MachThread *thread) : m_thread(thread), m_state() {} - - virtual ~DNBArchMachPPC() {} - - virtual const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets) const; - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value) const; - virtual kern_return_t GetRegisterState(int set, bool force); - virtual kern_return_t SetRegisterState(int set); - virtual bool RegisterSetStateIsValid(int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual bool ThreadWillResume(); - virtual bool ThreadDidStop(); - - static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); - static uint32_t GetCPUType(); - -protected: - kern_return_t EnableHardwareSingleStep(bool enable); - - typedef enum RegisterSetTag { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPR, - e_regSetEXC, - e_regSetVEC, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag { - e_regSetWordSizeGPR = PPC_THREAD_STATE_COUNT, - e_regSetWordSizeFPR = PPC_FLOAT_STATE_COUNT, - e_regSetWordSizeEXC = PPC_EXCEPTION_STATE_COUNT, - e_regSetWordSizeVEC = PPC_VECTOR_STATE_COUNT - } RegisterSetWordSize; - - enum { Read = 0, Write = 1, kNumErrors = 2 }; - - struct State { - ppc_thread_state_t gpr; - ppc_float_state_t fpr; - ppc_exception_state_t exc; - ppc_vector_state_t vec; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t fpr_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t vec_errs[2]; // Read/Write errors - - State() { - uint32_t i; - for (i = 0; i < kNumErrors; i++) { - gpr_errs[i] = -1; - fpr_errs[i] = -1; - exc_errs[i] = -1; - vec_errs[i] = -1; - } - } - void InvalidateAllRegisterStates() { SetError(e_regSetALL, 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] | fpr_errs[err_idx] | exc_errs[err_idx] | - vec_errs[err_idx]; - case e_regSetGPR: - return gpr_errs[err_idx]; - case e_regSetFPR: - return fpr_errs[err_idx]; - case e_regSetEXC: - return exc_errs[err_idx]; - case e_regSetVEC: - return vec_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] = fpr_errs[err_idx] = exc_errs[err_idx] = - vec_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetFPR: - fpr_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetVEC: - vec_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 GetFPRState(bool force); - kern_return_t GetEXCState(bool force); - kern_return_t GetVECState(bool force); - - kern_return_t SetGPRState(); - kern_return_t SetFPRState(); - kern_return_t SetEXCState(); - kern_return_t SetVECState(); - -protected: - MachThread *m_thread; - State m_state; -}; - -#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) -#endif // #ifndef __DebugNubArchMachPPC_h__ diff --git a/tools/debugserver/source/MacOSX/stack_logging.h b/tools/debugserver/source/MacOSX/stack_logging.h deleted file mode 100644 index 5209e38a08ea..000000000000 --- a/tools/debugserver/source/MacOSX/stack_logging.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 1999-2007 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef malloc_history_test_stack_logging_h -#define malloc_history_test_stack_logging_h - -#import <malloc/malloc.h> - -#define stack_logging_type_free 0 -#define stack_logging_type_generic \ - 1 /* anything that is not allocation/deallocation */ -#define stack_logging_type_alloc 2 /* malloc, realloc, etc... */ -#define stack_logging_type_dealloc 4 /* free, realloc, etc... */ - -// Following flags are absorbed by stack_logging_log_stack() -#define stack_logging_flag_zone 8 /* NSZoneMalloc, etc... */ -#define stack_logging_flag_calloc 16 /* multiply arguments to get the size */ -#define stack_logging_flag_object \ - 32 /* NSAllocateObject(Class, extraBytes, zone) */ -#define stack_logging_flag_cleared 64 /* for NewEmptyHandle */ -#define stack_logging_flag_handle 128 /* for Handle (de-)allocation routines \ - */ -#define stack_logging_flag_set_handle_size \ - 256 /* (Handle, newSize) treated specially */ - -/* Macro used to disguise addresses so that leak finding can work */ -#define STACK_LOGGING_DISGUISE(address) \ - ((address) ^ 0x00005555) /* nicely idempotent */ - -extern "C" int - stack_logging_enable_logging; /* when clear, no logging takes place */ -extern "C" int stack_logging_dontcompact; /* default is to compact; when set - does not compact alloc/free logs; - useful for tracing history */ - -extern "C" void stack_logging_log_stack(unsigned type, unsigned arg1, - unsigned arg2, unsigned arg3, - unsigned result, - unsigned num_hot_to_skip); -/* This is the old log-to-memory logger, which is now deprecated. It remains - * for compatibility with performance tools that haven't been updated to - * disk_stack_logging_log_stack() yet. */ - -extern "C" void -__disk_stack_logging_log_stack(uint32_t type_flags, uintptr_t zone_ptr, - uintptr_t size, uintptr_t ptr_arg, - uintptr_t return_val, uint32_t num_hot_to_skip); -/* Fits as the malloc_logger; logs malloc/free/realloc events and can log custom - * events if called directly */ - -/* 64-bit-aware stack log access. */ -typedef struct { - uint32_t type_flags; - uint64_t stack_identifier; - uint64_t argument; - mach_vm_address_t address; -} mach_stack_logging_record_t; - -extern "C" kern_return_t -__mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, - mach_vm_address_t *stack_frames_buffer, - uint32_t max_stack_frames, uint32_t *count); -/* Gets the last allocation record (malloc, realloc, or free) about address */ - -extern "C" kern_return_t __mach_stack_logging_enumerate_records( - task_t task, mach_vm_address_t address, - void enumerator(mach_stack_logging_record_t, void *), void *context); -/* Applies enumerator to all records involving address sending context as - * enumerator's second parameter; if !address, applies enumerator to all records - */ - -extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack( - task_t task, uint64_t stack_identifier, - mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, - uint32_t *count); -/* Given a uniqued_stack fills stack_frames_buffer */ - -#pragma mark - -#pragma mark Legacy - -/* The following is the old 32-bit-only, in-process-memory stack logging. This - * is deprecated and clients should move to the above 64-bit-aware disk stack - * logging SPI. */ - -typedef struct { - unsigned type; - unsigned uniqued_stack; - unsigned argument; - unsigned address; /* disguised, to avoid confusing leaks */ -} stack_logging_record_t; - -typedef struct { - unsigned overall_num_bytes; - unsigned num_records; - unsigned lock; /* 0 means OK to lock; used for inter-process locking */ - unsigned *uniquing_table; /* allocated using vm_allocate() */ - /* hashtable organized as (PC, uniqued parent) - Only the second half of the table is active - To enable us to grow dynamically */ - unsigned uniquing_table_num_pages; /* number of pages of the table */ - unsigned extra_retain_count; /* not used by stack_logging_log_stack */ - unsigned filler[2]; /* align to cache lines for better performance */ - stack_logging_record_t records[0]; /* records follow here */ -} stack_logging_record_list_t; - -extern "C" stack_logging_record_list_t *stack_logging_the_record_list; -/* This is the global variable containing all logs */ - -extern "C" kern_return_t -stack_logging_get_frames(task_t task, memory_reader_t reader, - vm_address_t address, - vm_address_t *stack_frames_buffer, - unsigned max_stack_frames, unsigned *num_frames); -/* Gets the last record in stack_logging_the_record_list about address */ - -#define STACK_LOGGING_ENUMERATION_PROVIDED \ - 1 // temporary to avoid dependencies between projects - -extern "C" kern_return_t stack_logging_enumerate_records( - task_t task, memory_reader_t reader, vm_address_t address, - void enumerator(stack_logging_record_t, void *), void *context); -/* Gets all the records about address; - If !address, gets all records */ - -extern "C" kern_return_t stack_logging_frames_for_uniqued_stack( - task_t task, memory_reader_t reader, unsigned uniqued_stack, - vm_address_t *stack_frames_buffer, unsigned max_stack_frames, - unsigned *num_frames); -/* Given a uniqued_stack fills stack_frames_buffer */ - -extern "C" void thread_stack_pcs(vm_address_t *buffer, unsigned max, - unsigned *num); -/* Convenience to fill buffer with the PCs of the frames, starting with the hot - frames; - num: returned number of frames - */ - -#endif diff --git a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp deleted file mode 100644 index 2f8ed32fa5d0..000000000000 --- a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ /dev/null @@ -1,2890 +0,0 @@ -//===-- DNBArchImplX86_64.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#if defined(__i386__) || defined(__x86_64__) - -#include <sys/cdefs.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -#include "DNBLog.h" -#include "MacOSX/x86_64/DNBArchImplX86_64.h" -#include "MachProcess.h" -#include "MachThread.h" -#include <mach/mach.h> -#include <stdlib.h> - -#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 - -bool DetectHardwareFeature(const char *feature) { - int answer = 0; - size_t answer_size = sizeof(answer); - int error = ::sysctlbyname(feature, &answer, &answer_size, NULL, 0); - return error == 0 && answer != 0; -} - -enum AVXPresence { eAVXUnknown = -1, eAVXNotPresent = 0, eAVXPresent = 1 }; - -bool LogAVXAndReturn(AVXPresence has_avx, int err, const char * os_ver) { - DNBLogThreadedIf(LOG_THREAD, - "CPUHasAVX(): g_has_avx = %i (err = %i, os_ver = %s)", - has_avx, err, os_ver); - return (has_avx == eAVXPresent); -} - -extern "C" bool CPUHasAVX() { - static AVXPresence g_has_avx = eAVXUnknown; - if (g_has_avx != eAVXUnknown) - return LogAVXAndReturn(g_has_avx, 0, ""); - - g_has_avx = eAVXNotPresent; - - // OS X 10.7.3 and earlier have a bug in thread_get_state that truncated the - // size of the return. To work around this we have to disable AVX debugging - // on hosts prior to 10.7.3 (<rdar://problem/10122874>). - int mib[2]; - char buffer[1024]; - size_t length = sizeof(buffer); - mib[0] = CTL_KERN; - mib[1] = KERN_OSVERSION; - - // KERN_OSVERSION returns the build number which is a number signifying the - // major version, a capitol letter signifying the minor version, and numbers - // signifying the build (ex: on 10.12.3, the returned value is 16D32). - int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0); - if (err != 0) - return LogAVXAndReturn(g_has_avx, err, ""); - - size_t first_letter = 0; - for (; first_letter < length; ++first_letter) { - // This is looking for the first uppercase letter - if (isupper(buffer[first_letter])) - break; - } - char letter = buffer[first_letter]; - buffer[first_letter] = '\0'; - auto major_ver = strtoull(buffer, NULL, 0); - buffer[first_letter] = letter; - - // In this check we're looking to see that our major and minor version numer - // was >= 11E, which is the 10.7.4 release. - if (major_ver < 11 || (major_ver == 11 && letter < 'E')) - return LogAVXAndReturn(g_has_avx, err, buffer); - if (DetectHardwareFeature("hw.optional.avx1_0")) - g_has_avx = eAVXPresent; - - return LogAVXAndReturn(g_has_avx, err, buffer); -} - -extern "C" bool CPUHasAVX512f() { - static AVXPresence g_has_avx512f = eAVXUnknown; - if (g_has_avx512f != eAVXUnknown) - return g_has_avx512f == eAVXPresent; - - g_has_avx512f = DetectHardwareFeature("hw.optional.avx512f") ? eAVXPresent - : eAVXNotPresent; - - return (g_has_avx512f == eAVXPresent); -} - -uint64_t DNBArchImplX86_64::GetPC(uint64_t failValue) { - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__rip; - return failValue; -} - -kern_return_t DNBArchImplX86_64::SetPC(uint64_t value) { - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) { - m_state.context.gpr.__rip = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; -} - -uint64_t DNBArchImplX86_64::GetSP(uint64_t failValue) { - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__rsp; - 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 - -kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { - if (force || m_state.GetError(e_regSetGPR, Read)) { -#if DEBUG_GPR_VALUES - m_state.context.gpr.__rax = ('a' << 8) + 'x'; - m_state.context.gpr.__rbx = ('b' << 8) + 'x'; - m_state.context.gpr.__rcx = ('c' << 8) + 'x'; - m_state.context.gpr.__rdx = ('d' << 8) + 'x'; - m_state.context.gpr.__rdi = ('d' << 8) + 'i'; - m_state.context.gpr.__rsi = ('s' << 8) + 'i'; - m_state.context.gpr.__rbp = ('b' << 8) + 'p'; - m_state.context.gpr.__rsp = ('s' << 8) + 'p'; - m_state.context.gpr.__r8 = ('r' << 8) + '8'; - m_state.context.gpr.__r9 = ('r' << 8) + '9'; - m_state.context.gpr.__r10 = ('r' << 8) + 'a'; - m_state.context.gpr.__r11 = ('r' << 8) + 'b'; - m_state.context.gpr.__r12 = ('r' << 8) + 'c'; - m_state.context.gpr.__r13 = ('r' << 8) + 'd'; - m_state.context.gpr.__r14 = ('r' << 8) + 'e'; - m_state.context.gpr.__r15 = ('r' << 8) + 'f'; - m_state.context.gpr.__rip = ('i' << 8) + 'p'; - m_state.context.gpr.__rflags = ('f' << 8) + 'l'; - m_state.context.gpr.__cs = ('c' << 8) + 's'; - m_state.context.gpr.__fs = ('f' << 8) + 's'; - m_state.context.gpr.__gs = ('g' << 8) + 's'; - 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(), __x86_64_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, &count)); - DNBLogThreadedIf( - LOG_THREAD, - "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" - "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" - "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" - "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" - "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" - "\n\trip = %16.16llx" - "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", - m_thread->MachPortNumber(), x86_THREAD_STATE64, - x86_THREAD_STATE64_COUNT, m_state.GetError(e_regSetGPR, Read), - m_state.context.gpr.__rax, m_state.context.gpr.__rbx, - m_state.context.gpr.__rcx, m_state.context.gpr.__rdx, - m_state.context.gpr.__rdi, m_state.context.gpr.__rsi, - m_state.context.gpr.__rbp, m_state.context.gpr.__rsp, - m_state.context.gpr.__r8, m_state.context.gpr.__r9, - m_state.context.gpr.__r10, m_state.context.gpr.__r11, - m_state.context.gpr.__r12, m_state.context.gpr.__r13, - m_state.context.gpr.__r14, m_state.context.gpr.__r15, - m_state.context.gpr.__rip, m_state.context.gpr.__rflags, - m_state.context.gpr.__cs, m_state.context.gpr.__fs, - m_state.context.gpr.__gs); - -// DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) -// => 0x%8.8x" -// "\n\trax = %16.16llx" -// "\n\trbx = %16.16llx" -// "\n\trcx = %16.16llx" -// "\n\trdx = %16.16llx" -// "\n\trdi = %16.16llx" -// "\n\trsi = %16.16llx" -// "\n\trbp = %16.16llx" -// "\n\trsp = %16.16llx" -// "\n\t r8 = %16.16llx" -// "\n\t r9 = %16.16llx" -// "\n\tr10 = %16.16llx" -// "\n\tr11 = %16.16llx" -// "\n\tr12 = %16.16llx" -// "\n\tr13 = %16.16llx" -// "\n\tr14 = %16.16llx" -// "\n\tr15 = %16.16llx" -// "\n\trip = %16.16llx" -// "\n\tflg = %16.16llx" -// "\n\t cs = %16.16llx" -// "\n\t fs = %16.16llx" -// "\n\t gs = %16.16llx", -// m_thread->MachPortNumber(), -// x86_THREAD_STATE64, -// x86_THREAD_STATE64_COUNT, -// m_state.GetError(e_regSetGPR, Read), -// m_state.context.gpr.__rax, -// m_state.context.gpr.__rbx, -// m_state.context.gpr.__rcx, -// m_state.context.gpr.__rdx, -// m_state.context.gpr.__rdi, -// m_state.context.gpr.__rsi, -// m_state.context.gpr.__rbp, -// m_state.context.gpr.__rsp, -// m_state.context.gpr.__r8, -// m_state.context.gpr.__r9, -// m_state.context.gpr.__r10, -// m_state.context.gpr.__r11, -// m_state.context.gpr.__r12, -// m_state.context.gpr.__r13, -// m_state.context.gpr.__r14, -// m_state.context.gpr.__r15, -// m_state.context.gpr.__rip, -// m_state.context.gpr.__rflags, -// m_state.context.gpr.__cs, -// m_state.context.gpr.__fs, -// m_state.context.gpr.__gs); -#endif - } - return m_state.GetError(e_regSetGPR, Read); -} - -// Uncomment the value below to verify the values in the debugger. -//#define DEBUG_FPU_REGS 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED - -kern_return_t DNBArchImplX86_64::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'; - m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8'; - m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9'; - m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A'; - m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B'; - m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C'; - m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D'; - m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E'; - m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F'; - } - 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 < 16; ++i) { - m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i; - m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i; - m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i; - m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i; - m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i; - m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i; - m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i; - m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i; - m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i; - m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i; - m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i; - m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i; - m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i; - m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i; - m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i; - m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i; - } - for (int i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) - m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; - } - 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.context.fpu.avx512f.__fpu_zmmh8.__ymm_reg[i] = '8'; - m_state.context.fpu.avx512f.__fpu_zmmh9.__ymm_reg[i] = '9'; - m_state.context.fpu.avx512f.__fpu_zmmh10.__ymm_reg[i] = 'A'; - m_state.context.fpu.avx512f.__fpu_zmmh11.__ymm_reg[i] = 'B'; - m_state.context.fpu.avx512f.__fpu_zmmh12.__ymm_reg[i] = 'C'; - m_state.context.fpu.avx512f.__fpu_zmmh13.__ymm_reg[i] = 'D'; - m_state.context.fpu.avx512f.__fpu_zmmh14.__ymm_reg[i] = 'E'; - m_state.context.fpu.avx512f.__fpu_zmmh15.__ymm_reg[i] = 'F'; - } - for (int i = 0; i < 64; ++i) { - m_state.context.fpu.avx512f.__fpu_zmm16.__zmm_reg[i] = 'G'; - m_state.context.fpu.avx512f.__fpu_zmm17.__zmm_reg[i] = 'H'; - m_state.context.fpu.avx512f.__fpu_zmm18.__zmm_reg[i] = 'I'; - m_state.context.fpu.avx512f.__fpu_zmm19.__zmm_reg[i] = 'J'; - m_state.context.fpu.avx512f.__fpu_zmm20.__zmm_reg[i] = 'K'; - m_state.context.fpu.avx512f.__fpu_zmm21.__zmm_reg[i] = 'L'; - m_state.context.fpu.avx512f.__fpu_zmm22.__zmm_reg[i] = 'M'; - m_state.context.fpu.avx512f.__fpu_zmm23.__zmm_reg[i] = 'N'; - m_state.context.fpu.avx512f.__fpu_zmm24.__zmm_reg[i] = 'O'; - m_state.context.fpu.avx512f.__fpu_zmm25.__zmm_reg[i] = 'P'; - m_state.context.fpu.avx512f.__fpu_zmm26.__zmm_reg[i] = 'Q'; - m_state.context.fpu.avx512f.__fpu_zmm27.__zmm_reg[i] = 'R'; - m_state.context.fpu.avx512f.__fpu_zmm28.__zmm_reg[i] = 'S'; - m_state.context.fpu.avx512f.__fpu_zmm29.__zmm_reg[i] = 'T'; - m_state.context.fpu.avx512f.__fpu_zmm30.__zmm_reg[i] = 'U'; - m_state.context.fpu.avx512f.__fpu_zmm31.__zmm_reg[i] = 'V'; - } - } - m_state.SetError(e_regSetFPU, Read, 0); - } else { - mach_msg_type_number_t count = e_regSetWordSizeFPU; - int flavor = __x86_64_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 = __x86_64_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); - else - DNBLogThreadedIf(LOG_THREAD, - "::thread_get_state attempted fetch of avx512 fpu regctx failed, will try fetching avx"); - } - if (CPUHasAVX() || FORCE_AVX_REGS) { - count = e_regSetWordSizeAVX; - flavor = __x86_64_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 DNBArchImplX86_64::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(), __x86_64_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); -} - -kern_return_t DNBArchImplX86_64::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(), - __x86_64_THREAD_STATE, - (thread_state_t)&m_state.context.gpr, - e_regSetWordSizeGPR)); - DNBLogThreadedIf( - LOG_THREAD, - "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" - "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" - "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" - "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" - "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" - "\n\trip = %16.16llx" - "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", - m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR, - m_state.GetError(e_regSetGPR, Write), m_state.context.gpr.__rax, - m_state.context.gpr.__rbx, m_state.context.gpr.__rcx, - m_state.context.gpr.__rdx, m_state.context.gpr.__rdi, - m_state.context.gpr.__rsi, m_state.context.gpr.__rbp, - m_state.context.gpr.__rsp, m_state.context.gpr.__r8, - m_state.context.gpr.__r9, m_state.context.gpr.__r10, - m_state.context.gpr.__r11, m_state.context.gpr.__r12, - m_state.context.gpr.__r13, m_state.context.gpr.__r14, - m_state.context.gpr.__r15, m_state.context.gpr.__rip, - m_state.context.gpr.__rflags, m_state.context.gpr.__cs, - m_state.context.gpr.__fs, m_state.context.gpr.__gs); - return m_state.GetError(e_regSetGPR, Write); -} - -kern_return_t DNBArchImplX86_64::SetFPUState() { - if (DEBUG_FPU_REGS) { - m_state.SetError(e_regSetFPU, Write, 0); - return m_state.GetError(e_regSetFPU, Write); - } else { - int flavor = __x86_64_FLOAT_STATE; - mach_msg_type_number_t count = e_regSetWordSizeFPU; - if (CPUHasAVX512f() || FORCE_AVX_REGS) { - count = e_regSetWordSizeAVX512f; - flavor = __x86_64_AVX512F_STATE; - m_state.SetError( - e_regSetFPU, Write, - ::thread_set_state(m_thread->MachPortNumber(), flavor, - (thread_state_t)&m_state.context.fpu, count)); - if (m_state.GetError(e_regSetFPU, Write) == KERN_SUCCESS) - return m_state.GetError(e_regSetFPU, Write); - else - DNBLogThreadedIf(LOG_THREAD, - "::thread_get_state attempted save of avx512 fpu regctx failed, will try saving avx regctx"); - } - - if (CPUHasAVX() || FORCE_AVX_REGS) { - flavor = __x86_64_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 DNBArchImplX86_64::SetEXCState() { - m_state.SetError(e_regSetEXC, Write, - ::thread_set_state(m_thread->MachPortNumber(), - __x86_64_EXCEPTION_STATE, - (thread_state_t)&m_state.context.exc, - e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); -} - -kern_return_t DNBArchImplX86_64::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(), __x86_64_DEBUG_STATE, - (thread_state_t)&m_state.context.dbg, &count)); - } - return m_state.GetError(e_regSetDBG, Read); -} - -kern_return_t DNBArchImplX86_64::SetDBGState(bool also_set_on_task) { - m_state.SetError(e_regSetDBG, Write, - ::thread_set_state(m_thread->MachPortNumber(), - __x86_64_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(), __x86_64_DEBUG_STATE, - (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); - if (kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed " - "to set debug control register state: " - "0x%8.8x.", - kret); - } - return m_state.GetError(e_regSetDBG, Write); -} - -void DNBArchImplX86_64::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, - "DNBArchImplX86_64::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, - "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", - kret); - } -} - -bool DNBArchImplX86_64::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 DNBArchImplX86_64::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.__rip > 0) { - m_state.context.gpr.__rip = 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 DNBArchImplX86_64::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 DNBArchImplX86_64::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)); - switch (hw_index) { - case 0: - debug_state.__dr0 = addr; - break; - case 1: - debug_state.__dr1 = addr; - break; - case 2: - debug_state.__dr2 = addr; - break; - case 3: - debug_state.__dr3 = addr; - break; - default: - assert(0 && - "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; -} - -void DNBArchImplX86_64::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 DNBArchImplX86_64::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 DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) { - // See also IsWatchpointHit(). - debug_state.__dr6 = 0; - return; -} - -bool DNBArchImplX86_64::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 DNBArchImplX86_64::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 DNBArchImplX86_64::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 DNBArchImplX86_64::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, - "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", - kret); - - return kret == KERN_SUCCESS; -} -bool DNBArchImplX86_64::FinishTransForHWP() { - m_2pc_trans_state = Trans_Done; - return true; -} -DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() { - return m_2pc_dbg_checkpoint; -} - -uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr, - nub_size_t size, bool read, - bool write, - bool also_set_on_task) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" - "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, "DNBArchImplX86_64::" - "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, "DNBArchImplX86_64::" - "EnableHardwareWatchpoint(): All " - "hardware resources (%u) are in use.", - num_hw_watchpoints); - } - } - return INVALID_NUB_HW_INDEX; -} - -bool DNBArchImplX86_64::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, - "DNBArchImplX86_64::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 DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) { - // Read the debug state - kern_return_t kret = GetDBGState(true); - DNBLogThreadedIf( - LOG_WATCHPOINTS, - "DNBArchImplX86_64::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, "DNBArchImplX86_64::" - "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 DNBArchImplX86_64::EnableHardwareSingleStep(bool enable) { - if (GetGPRState(false) == KERN_SUCCESS) { - const uint32_t trace_bit = 0x100u; - if (enable) - m_state.context.gpr.__rflags |= trace_bit; - else - m_state.context.gpr.__rflags &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); -} - -//---------------------------------------------------------------------- -// Register information definitions -//---------------------------------------------------------------------- - -enum { - gpr_rax = 0, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_r8d, // Low 32 bits or r8 - gpr_r9d, // Low 32 bits or r9 - gpr_r10d, // Low 32 bits or r10 - gpr_r11d, // Low 32 bits or r11 - gpr_r12d, // Low 32 bits or r12 - gpr_r13d, // Low 32 bits or r13 - gpr_r14d, // Low 32 bits or r14 - gpr_r15d, // Low 32 bits or r15 - gpr_ax, - gpr_bx, - gpr_cx, - gpr_dx, - gpr_di, - gpr_si, - gpr_bp, - gpr_sp, - gpr_r8w, // Low 16 bits or r8 - gpr_r9w, // Low 16 bits or r9 - gpr_r10w, // Low 16 bits or r10 - gpr_r11w, // Low 16 bits or r11 - gpr_r12w, // Low 16 bits or r12 - gpr_r13w, // Low 16 bits or r13 - gpr_r14w, // Low 16 bits or r14 - gpr_r15w, // Low 16 bits or r15 - gpr_ah, - gpr_bh, - gpr_ch, - gpr_dh, - gpr_al, - gpr_bl, - gpr_cl, - gpr_dl, - gpr_dil, - gpr_sil, - gpr_bpl, - gpr_spl, - gpr_r8l, // Low 8 bits or r8 - gpr_r9l, // Low 8 bits or r9 - gpr_r10l, // Low 8 bits or r10 - gpr_r11l, // Low 8 bits or r11 - gpr_r12l, // Low 8 bits or r12 - gpr_r13l, // Low 8 bits or r13 - gpr_r14l, // Low 8 bits or r14 - gpr_r15l, // Low 8 bits or r15 - 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_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - fpu_ymm0, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - fpu_ymm8, - fpu_ymm9, - fpu_ymm10, - fpu_ymm11, - fpu_ymm12, - fpu_ymm13, - fpu_ymm14, - fpu_ymm15, - 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, - fpu_zmm8, - fpu_zmm9, - fpu_zmm10, - fpu_zmm11, - fpu_zmm12, - fpu_zmm13, - fpu_zmm14, - fpu_zmm15, - fpu_zmm16, - fpu_zmm17, - fpu_zmm18, - fpu_zmm19, - fpu_zmm20, - fpu_zmm21, - fpu_zmm22, - fpu_zmm23, - fpu_zmm24, - fpu_zmm25, - fpu_zmm26, - fpu_zmm27, - fpu_zmm28, - fpu_zmm29, - fpu_zmm30, - fpu_zmm31, - 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_dwarf_regnums { - ehframe_dwarf_rax = 0, - ehframe_dwarf_rdx = 1, - ehframe_dwarf_rcx = 2, - ehframe_dwarf_rbx = 3, - ehframe_dwarf_rsi = 4, - ehframe_dwarf_rdi = 5, - ehframe_dwarf_rbp = 6, - ehframe_dwarf_rsp = 7, - ehframe_dwarf_r8, - ehframe_dwarf_r9, - ehframe_dwarf_r10, - ehframe_dwarf_r11, - ehframe_dwarf_r12, - ehframe_dwarf_r13, - ehframe_dwarf_r14, - ehframe_dwarf_r15, - ehframe_dwarf_rip, - ehframe_dwarf_xmm0, - ehframe_dwarf_xmm1, - ehframe_dwarf_xmm2, - ehframe_dwarf_xmm3, - ehframe_dwarf_xmm4, - ehframe_dwarf_xmm5, - ehframe_dwarf_xmm6, - ehframe_dwarf_xmm7, - ehframe_dwarf_xmm8, - ehframe_dwarf_xmm9, - ehframe_dwarf_xmm10, - ehframe_dwarf_xmm11, - ehframe_dwarf_xmm12, - ehframe_dwarf_xmm13, - ehframe_dwarf_xmm14, - ehframe_dwarf_xmm15, - ehframe_dwarf_stmm0, - ehframe_dwarf_stmm1, - ehframe_dwarf_stmm2, - ehframe_dwarf_stmm3, - ehframe_dwarf_stmm4, - ehframe_dwarf_stmm5, - ehframe_dwarf_stmm6, - ehframe_dwarf_stmm7, - ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0, - ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1, - ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2, - ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3, - ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4, - ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5, - ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6, - ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7, - ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8, - ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9, - ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10, - ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11, - ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12, - ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13, - ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14, - ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15, - ehframe_dwarf_zmm0 = ehframe_dwarf_xmm0, - ehframe_dwarf_zmm1 = ehframe_dwarf_xmm1, - ehframe_dwarf_zmm2 = ehframe_dwarf_xmm2, - ehframe_dwarf_zmm3 = ehframe_dwarf_xmm3, - ehframe_dwarf_zmm4 = ehframe_dwarf_xmm4, - ehframe_dwarf_zmm5 = ehframe_dwarf_xmm5, - ehframe_dwarf_zmm6 = ehframe_dwarf_xmm6, - ehframe_dwarf_zmm7 = ehframe_dwarf_xmm7, - ehframe_dwarf_zmm8 = ehframe_dwarf_xmm8, - ehframe_dwarf_zmm9 = ehframe_dwarf_xmm9, - ehframe_dwarf_zmm10 = ehframe_dwarf_xmm10, - ehframe_dwarf_zmm11 = ehframe_dwarf_xmm11, - ehframe_dwarf_zmm12 = ehframe_dwarf_xmm12, - ehframe_dwarf_zmm13 = ehframe_dwarf_xmm13, - ehframe_dwarf_zmm14 = ehframe_dwarf_xmm14, - ehframe_dwarf_zmm15 = ehframe_dwarf_xmm15, - ehframe_dwarf_zmm16 = 67, - ehframe_dwarf_zmm17, - ehframe_dwarf_zmm18, - ehframe_dwarf_zmm19, - ehframe_dwarf_zmm20, - ehframe_dwarf_zmm21, - ehframe_dwarf_zmm22, - ehframe_dwarf_zmm23, - ehframe_dwarf_zmm24, - ehframe_dwarf_zmm25, - ehframe_dwarf_zmm26, - ehframe_dwarf_zmm27, - ehframe_dwarf_zmm28, - ehframe_dwarf_zmm29, - ehframe_dwarf_zmm30, - ehframe_dwarf_zmm31, - ehframe_dwarf_k0 = 118, - ehframe_dwarf_k1, - ehframe_dwarf_k2, - ehframe_dwarf_k3, - ehframe_dwarf_k4, - ehframe_dwarf_k5, - ehframe_dwarf_k6, - ehframe_dwarf_k7, -}; - -enum debugserver_regnums { - debugserver_rax = 0, - debugserver_rbx = 1, - debugserver_rcx = 2, - debugserver_rdx = 3, - debugserver_rsi = 4, - debugserver_rdi = 5, - debugserver_rbp = 6, - debugserver_rsp = 7, - debugserver_r8 = 8, - debugserver_r9 = 9, - debugserver_r10 = 10, - debugserver_r11 = 11, - debugserver_r12 = 12, - debugserver_r13 = 13, - debugserver_r14 = 14, - debugserver_r15 = 15, - debugserver_rip = 16, - debugserver_rflags = 17, - debugserver_cs = 18, - debugserver_ss = 19, - debugserver_ds = 20, - debugserver_es = 21, - debugserver_fs = 22, - debugserver_gs = 23, - debugserver_stmm0 = 24, - debugserver_stmm1 = 25, - debugserver_stmm2 = 26, - debugserver_stmm3 = 27, - debugserver_stmm4 = 28, - debugserver_stmm5 = 29, - debugserver_stmm6 = 30, - debugserver_stmm7 = 31, - debugserver_fctrl = 32, - debugserver_fcw = debugserver_fctrl, - debugserver_fstat = 33, - debugserver_fsw = debugserver_fstat, - debugserver_ftag = 34, - debugserver_ftw = debugserver_ftag, - debugserver_fiseg = 35, - debugserver_fpu_cs = debugserver_fiseg, - debugserver_fioff = 36, - debugserver_ip = debugserver_fioff, - debugserver_foseg = 37, - debugserver_fpu_ds = debugserver_foseg, - debugserver_fooff = 38, - debugserver_dp = debugserver_fooff, - debugserver_fop = 39, - debugserver_xmm0 = 40, - debugserver_xmm1 = 41, - debugserver_xmm2 = 42, - debugserver_xmm3 = 43, - debugserver_xmm4 = 44, - debugserver_xmm5 = 45, - debugserver_xmm6 = 46, - debugserver_xmm7 = 47, - debugserver_xmm8 = 48, - debugserver_xmm9 = 49, - debugserver_xmm10 = 50, - debugserver_xmm11 = 51, - debugserver_xmm12 = 52, - debugserver_xmm13 = 53, - debugserver_xmm14 = 54, - debugserver_xmm15 = 55, - debugserver_mxcsr = 56, - 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_ymm8 = debugserver_xmm8, - debugserver_ymm9 = debugserver_xmm9, - debugserver_ymm10 = debugserver_xmm10, - debugserver_ymm11 = debugserver_xmm11, - debugserver_ymm12 = debugserver_xmm12, - debugserver_ymm13 = debugserver_xmm13, - debugserver_ymm14 = debugserver_xmm14, - debugserver_ymm15 = debugserver_xmm15, - 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_zmm8 = debugserver_xmm8, - debugserver_zmm9 = debugserver_xmm9, - debugserver_zmm10 = debugserver_xmm10, - debugserver_zmm11 = debugserver_xmm11, - debugserver_zmm12 = debugserver_xmm12, - debugserver_zmm13 = debugserver_xmm13, - debugserver_zmm14 = debugserver_xmm14, - debugserver_zmm15 = debugserver_xmm15, - debugserver_zmm16 = 67, - debugserver_zmm17 = 68, - debugserver_zmm18 = 69, - debugserver_zmm19 = 70, - debugserver_zmm20 = 71, - debugserver_zmm21 = 72, - debugserver_zmm22 = 73, - debugserver_zmm23 = 74, - debugserver_zmm24 = 75, - debugserver_zmm25 = 76, - debugserver_zmm26 = 77, - debugserver_zmm27 = 78, - debugserver_zmm28 = 79, - debugserver_zmm29 = 80, - debugserver_zmm30 = 81, - debugserver_zmm31 = 82, - debugserver_k0 = 118, - debugserver_k1 = 119, - debugserver_k2 = 120, - debugserver_k3 = 121, - debugserver_k4 = 122, - debugserver_k5 = 123, - debugserver_k6 = 124, - debugserver_k7 = 125, -}; - -#define GPR_OFFSET(reg) (offsetof(DNBArchImplX86_64::GPR, __##reg)) -#define FPU_OFFSET(reg) \ - (offsetof(DNBArchImplX86_64::FPU, __fpu_##reg) + \ - offsetof(DNBArchImplX86_64::Context, fpu.no_avx)) -#define AVX_OFFSET(reg) \ - (offsetof(DNBArchImplX86_64::AVX, __fpu_##reg) + \ - offsetof(DNBArchImplX86_64::Context, fpu.avx)) -#define AVX512F_OFFSET(reg) \ - (offsetof(DNBArchImplX86_64::AVX512F, __fpu_##reg) + \ - offsetof(DNBArchImplX86_64::Context, fpu.avx512f)) -#define EXC_OFFSET(reg) \ - (offsetof(DNBArchImplX86_64::EXC, __##reg) + \ - offsetof(DNBArchImplX86_64::Context, exc)) -#define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n)) -#define AVX512F_OFFSET_ZMM(n) (AVX512F_OFFSET(zmmh0) + (64 * n)) - -#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) -#define FPU_SIZE_UINT(reg) \ - (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) -#define FPU_SIZE_MMST(reg) \ - (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) -#define FPU_SIZE_XMM(reg) \ - (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) -#define FPU_SIZE_YMM(reg) (32) -#define FPU_SIZE_ZMM(reg) (64) -#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) - -// 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(reg) \ - { \ - e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), \ - GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, \ - INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg \ - } -#define DEFINE_GPR_ALT(reg, alt, gen) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ - GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ - debugserver_##reg, NULL, g_invalidate_##reg \ - } -#define DEFINE_GPR_ALT2(reg, alt) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ - GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL \ - } -#define DEFINE_GPR_ALT3(reg, alt, gen) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ - GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, \ - debugserver_##reg, NULL, NULL \ - } -#define DEFINE_GPR_ALT4(reg, alt, gen) \ - { \ - e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ - GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ - debugserver_##reg, NULL, NULL \ - } - -#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ - { \ - e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ - } -#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ - { \ - e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ - } -#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ - { \ - e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - g_contained_##reg64, g_invalidate_##reg64 \ - } -#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ - { \ - e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \ - INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ - g_contained_##reg64, g_invalidate_##reg64 \ - } - -// General purpose registers for 64 bit - -const char *g_contained_rax[] = {"rax", NULL}; -const char *g_contained_rbx[] = {"rbx", NULL}; -const char *g_contained_rcx[] = {"rcx", NULL}; -const char *g_contained_rdx[] = {"rdx", NULL}; -const char *g_contained_rdi[] = {"rdi", NULL}; -const char *g_contained_rsi[] = {"rsi", NULL}; -const char *g_contained_rbp[] = {"rbp", NULL}; -const char *g_contained_rsp[] = {"rsp", NULL}; -const char *g_contained_r8[] = {"r8", NULL}; -const char *g_contained_r9[] = {"r9", NULL}; -const char *g_contained_r10[] = {"r10", NULL}; -const char *g_contained_r11[] = {"r11", NULL}; -const char *g_contained_r12[] = {"r12", NULL}; -const char *g_contained_r13[] = {"r13", NULL}; -const char *g_contained_r14[] = {"r14", NULL}; -const char *g_contained_r15[] = {"r15", NULL}; - -const char *g_invalidate_rax[] = {"rax", "eax", "ax", "ah", "al", NULL}; -const char *g_invalidate_rbx[] = {"rbx", "ebx", "bx", "bh", "bl", NULL}; -const char *g_invalidate_rcx[] = {"rcx", "ecx", "cx", "ch", "cl", NULL}; -const char *g_invalidate_rdx[] = {"rdx", "edx", "dx", "dh", "dl", NULL}; -const char *g_invalidate_rdi[] = {"rdi", "edi", "di", "dil", NULL}; -const char *g_invalidate_rsi[] = {"rsi", "esi", "si", "sil", NULL}; -const char *g_invalidate_rbp[] = {"rbp", "ebp", "bp", "bpl", NULL}; -const char *g_invalidate_rsp[] = {"rsp", "esp", "sp", "spl", NULL}; -const char *g_invalidate_r8[] = {"r8", "r8d", "r8w", "r8l", NULL}; -const char *g_invalidate_r9[] = {"r9", "r9d", "r9w", "r9l", NULL}; -const char *g_invalidate_r10[] = {"r10", "r10d", "r10w", "r10l", NULL}; -const char *g_invalidate_r11[] = {"r11", "r11d", "r11w", "r11l", NULL}; -const char *g_invalidate_r12[] = {"r12", "r12d", "r12w", "r12l", NULL}; -const char *g_invalidate_r13[] = {"r13", "r13d", "r13w", "r13l", NULL}; -const char *g_invalidate_r14[] = {"r14", "r14d", "r14w", "r14l", NULL}; -const char *g_invalidate_r15[] = {"r15", "r15d", "r15w", "r15l", NULL}; - -const DNBRegisterInfo DNBArchImplX86_64::g_gpr_registers[] = { - DEFINE_GPR(rax), - DEFINE_GPR(rbx), - DEFINE_GPR_ALT(rcx, "arg4", GENERIC_REGNUM_ARG4), - DEFINE_GPR_ALT(rdx, "arg3", GENERIC_REGNUM_ARG3), - DEFINE_GPR_ALT(rdi, "arg1", GENERIC_REGNUM_ARG1), - DEFINE_GPR_ALT(rsi, "arg2", GENERIC_REGNUM_ARG2), - DEFINE_GPR_ALT(rbp, "fp", GENERIC_REGNUM_FP), - DEFINE_GPR_ALT(rsp, "sp", GENERIC_REGNUM_SP), - DEFINE_GPR_ALT(r8, "arg5", GENERIC_REGNUM_ARG5), - DEFINE_GPR_ALT(r9, "arg6", GENERIC_REGNUM_ARG6), - DEFINE_GPR(r10), - DEFINE_GPR(r11), - DEFINE_GPR(r12), - DEFINE_GPR(r13), - DEFINE_GPR(r14), - DEFINE_GPR(r15), - DEFINE_GPR_ALT4(rip, "pc", GENERIC_REGNUM_PC), - DEFINE_GPR_ALT3(rflags, "flags", GENERIC_REGNUM_FLAGS), - DEFINE_GPR_ALT2(cs, NULL), - DEFINE_GPR_ALT2(fs, NULL), - DEFINE_GPR_ALT2(gs, NULL), - DEFINE_GPR_PSEUDO_32(eax, rax), - DEFINE_GPR_PSEUDO_32(ebx, rbx), - DEFINE_GPR_PSEUDO_32(ecx, rcx), - DEFINE_GPR_PSEUDO_32(edx, rdx), - DEFINE_GPR_PSEUDO_32(edi, rdi), - DEFINE_GPR_PSEUDO_32(esi, rsi), - DEFINE_GPR_PSEUDO_32(ebp, rbp), - DEFINE_GPR_PSEUDO_32(esp, rsp), - DEFINE_GPR_PSEUDO_32(r8d, r8), - DEFINE_GPR_PSEUDO_32(r9d, r9), - DEFINE_GPR_PSEUDO_32(r10d, r10), - DEFINE_GPR_PSEUDO_32(r11d, r11), - DEFINE_GPR_PSEUDO_32(r12d, r12), - DEFINE_GPR_PSEUDO_32(r13d, r13), - DEFINE_GPR_PSEUDO_32(r14d, r14), - DEFINE_GPR_PSEUDO_32(r15d, r15), - DEFINE_GPR_PSEUDO_16(ax, rax), - DEFINE_GPR_PSEUDO_16(bx, rbx), - DEFINE_GPR_PSEUDO_16(cx, rcx), - DEFINE_GPR_PSEUDO_16(dx, rdx), - DEFINE_GPR_PSEUDO_16(di, rdi), - DEFINE_GPR_PSEUDO_16(si, rsi), - DEFINE_GPR_PSEUDO_16(bp, rbp), - DEFINE_GPR_PSEUDO_16(sp, rsp), - DEFINE_GPR_PSEUDO_16(r8w, r8), - DEFINE_GPR_PSEUDO_16(r9w, r9), - DEFINE_GPR_PSEUDO_16(r10w, r10), - DEFINE_GPR_PSEUDO_16(r11w, r11), - DEFINE_GPR_PSEUDO_16(r12w, r12), - DEFINE_GPR_PSEUDO_16(r13w, r13), - DEFINE_GPR_PSEUDO_16(r14w, r14), - DEFINE_GPR_PSEUDO_16(r15w, r15), - DEFINE_GPR_PSEUDO_8H(ah, rax), - DEFINE_GPR_PSEUDO_8H(bh, rbx), - DEFINE_GPR_PSEUDO_8H(ch, rcx), - DEFINE_GPR_PSEUDO_8H(dh, rdx), - DEFINE_GPR_PSEUDO_8L(al, rax), - DEFINE_GPR_PSEUDO_8L(bl, rbx), - DEFINE_GPR_PSEUDO_8L(cl, rcx), - DEFINE_GPR_PSEUDO_8L(dl, rdx), - DEFINE_GPR_PSEUDO_8L(dil, rdi), - DEFINE_GPR_PSEUDO_8L(sil, rsi), - DEFINE_GPR_PSEUDO_8L(bpl, rbp), - DEFINE_GPR_PSEUDO_8L(spl, rsp), - DEFINE_GPR_PSEUDO_8L(r8l, r8), - DEFINE_GPR_PSEUDO_8L(r9l, r9), - DEFINE_GPR_PSEUDO_8L(r10l, r10), - DEFINE_GPR_PSEUDO_8L(r11l, r11), - DEFINE_GPR_PSEUDO_8L(r12l, r12), - DEFINE_GPR_PSEUDO_8L(r13l, r13), - DEFINE_GPR_PSEUDO_8L(r14l, r14), - DEFINE_GPR_PSEUDO_8L(r15l, r15)}; - -// Floating point registers 64 bit -const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_no_avx[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - FPU_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - FPU_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - FPU_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - FPU_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - FPU_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - FPU_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - FPU_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - FPU_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - FPU_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, - NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0, - ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1, - ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2, - ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3, - ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4, - ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5, - ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6, - ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7, - ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, - - {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), ehframe_dwarf_xmm0, - ehframe_dwarf_xmm0, -1U, debugserver_xmm0, NULL, NULL}, - {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), ehframe_dwarf_xmm1, - ehframe_dwarf_xmm1, -1U, debugserver_xmm1, NULL, NULL}, - {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), ehframe_dwarf_xmm2, - ehframe_dwarf_xmm2, -1U, debugserver_xmm2, NULL, NULL}, - {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), ehframe_dwarf_xmm3, - ehframe_dwarf_xmm3, -1U, debugserver_xmm3, NULL, NULL}, - {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), ehframe_dwarf_xmm4, - ehframe_dwarf_xmm4, -1U, debugserver_xmm4, NULL, NULL}, - {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), ehframe_dwarf_xmm5, - ehframe_dwarf_xmm5, -1U, debugserver_xmm5, NULL, NULL}, - {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), ehframe_dwarf_xmm6, - ehframe_dwarf_xmm6, -1U, debugserver_xmm6, NULL, NULL}, - {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), ehframe_dwarf_xmm7, - ehframe_dwarf_xmm7, -1U, debugserver_xmm7, NULL, NULL}, - {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm8), FPU_OFFSET(xmm8), ehframe_dwarf_xmm8, - ehframe_dwarf_xmm8, -1U, debugserver_xmm8, NULL, NULL}, - {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm9), FPU_OFFSET(xmm9), ehframe_dwarf_xmm9, - ehframe_dwarf_xmm9, -1U, debugserver_xmm9, NULL, NULL}, - {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm10), FPU_OFFSET(xmm10), ehframe_dwarf_xmm10, - ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL}, - {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm11), FPU_OFFSET(xmm11), ehframe_dwarf_xmm11, - ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL}, - {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm12), FPU_OFFSET(xmm12), ehframe_dwarf_xmm12, - ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL}, - {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm13), FPU_OFFSET(xmm13), ehframe_dwarf_xmm13, - ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL}, - {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm14), FPU_OFFSET(xmm14), ehframe_dwarf_xmm14, - ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL}, - {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm15), FPU_OFFSET(xmm15), ehframe_dwarf_xmm15, - ehframe_dwarf_xmm15, -1U, debugserver_xmm15, 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}; -static const char *g_contained_ymm8[] = {"ymm8", NULL}; -static const char *g_contained_ymm9[] = {"ymm9", NULL}; -static const char *g_contained_ymm10[] = {"ymm10", NULL}; -static const char *g_contained_ymm11[] = {"ymm11", NULL}; -static const char *g_contained_ymm12[] = {"ymm12", NULL}; -static const char *g_contained_ymm13[] = {"ymm13", NULL}; -static const char *g_contained_ymm14[] = {"ymm14", NULL}; -static const char *g_contained_ymm15[] = {"ymm15", NULL}; - -const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_avx[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - AVX_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - AVX_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - AVX_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - AVX_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - AVX_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - AVX_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - AVX_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - AVX_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - AVX_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, - NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, - ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, - ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, - ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, - ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, - ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, - ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, - ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, - ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, - - {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), ehframe_dwarf_ymm0, - ehframe_dwarf_ymm0, -1U, debugserver_ymm0, NULL, NULL}, - {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), ehframe_dwarf_ymm1, - ehframe_dwarf_ymm1, -1U, debugserver_ymm1, NULL, NULL}, - {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), ehframe_dwarf_ymm2, - ehframe_dwarf_ymm2, -1U, debugserver_ymm2, NULL, NULL}, - {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), ehframe_dwarf_ymm3, - ehframe_dwarf_ymm3, -1U, debugserver_ymm3, NULL, NULL}, - {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), ehframe_dwarf_ymm4, - ehframe_dwarf_ymm4, -1U, debugserver_ymm4, NULL, NULL}, - {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), ehframe_dwarf_ymm5, - ehframe_dwarf_ymm5, -1U, debugserver_ymm5, NULL, NULL}, - {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), ehframe_dwarf_ymm6, - ehframe_dwarf_ymm6, -1U, debugserver_ymm6, NULL, NULL}, - {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), ehframe_dwarf_ymm7, - ehframe_dwarf_ymm7, -1U, debugserver_ymm7, NULL, NULL}, - {e_regSetFPU, fpu_ymm8, "ymm8", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm8), AVX_OFFSET_YMM(8), ehframe_dwarf_ymm8, - ehframe_dwarf_ymm8, -1U, debugserver_ymm8, NULL, NULL}, - {e_regSetFPU, fpu_ymm9, "ymm9", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm9), AVX_OFFSET_YMM(9), ehframe_dwarf_ymm9, - ehframe_dwarf_ymm9, -1U, debugserver_ymm9, NULL, NULL}, - {e_regSetFPU, fpu_ymm10, "ymm10", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm10), AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10, - ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL}, - {e_regSetFPU, fpu_ymm11, "ymm11", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm11), AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11, - ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL}, - {e_regSetFPU, fpu_ymm12, "ymm12", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm12), AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12, - ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL}, - {e_regSetFPU, fpu_ymm13, "ymm13", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm13), AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13, - ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL}, - {e_regSetFPU, fpu_ymm14, "ymm14", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm14), AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14, - ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL}, - {e_regSetFPU, fpu_ymm15, "ymm15", NULL, Vector, VectorOfUInt8, - FPU_SIZE_YMM(ymm15), AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15, - ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL}, - - {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm0), 0, ehframe_dwarf_xmm0, ehframe_dwarf_xmm0, -1U, - debugserver_xmm0, g_contained_ymm0, NULL}, - {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm1), 0, ehframe_dwarf_xmm1, ehframe_dwarf_xmm1, -1U, - debugserver_xmm1, g_contained_ymm1, NULL}, - {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm2), 0, ehframe_dwarf_xmm2, ehframe_dwarf_xmm2, -1U, - debugserver_xmm2, g_contained_ymm2, NULL}, - {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm3), 0, ehframe_dwarf_xmm3, ehframe_dwarf_xmm3, -1U, - debugserver_xmm3, g_contained_ymm3, NULL}, - {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm4), 0, ehframe_dwarf_xmm4, ehframe_dwarf_xmm4, -1U, - debugserver_xmm4, g_contained_ymm4, NULL}, - {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm5), 0, ehframe_dwarf_xmm5, ehframe_dwarf_xmm5, -1U, - debugserver_xmm5, g_contained_ymm5, NULL}, - {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm6), 0, ehframe_dwarf_xmm6, ehframe_dwarf_xmm6, -1U, - debugserver_xmm6, g_contained_ymm6, NULL}, - {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm7), 0, ehframe_dwarf_xmm7, ehframe_dwarf_xmm7, -1U, - debugserver_xmm7, g_contained_ymm7, NULL}, - {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm8), 0, ehframe_dwarf_xmm8, ehframe_dwarf_xmm8, -1U, - debugserver_xmm8, g_contained_ymm8, NULL}, - {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm9), 0, ehframe_dwarf_xmm9, ehframe_dwarf_xmm9, -1U, - debugserver_xmm9, g_contained_ymm9, NULL}, - {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm10), 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, - debugserver_xmm10, g_contained_ymm10, NULL}, - {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm11), 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, - debugserver_xmm11, g_contained_ymm11, NULL}, - {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm12), 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, - debugserver_xmm12, g_contained_ymm12, NULL}, - {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm13), 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, - debugserver_xmm13, g_contained_ymm13, NULL}, - {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm14), 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, - debugserver_xmm14, g_contained_ymm14, NULL}, - {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, - FPU_SIZE_XMM(xmm15), 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, - debugserver_xmm15, g_contained_ymm15, 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}; -static const char *g_contained_zmm8[] = {"zmm8", NULL}; -static const char *g_contained_zmm9[] = {"zmm9", NULL}; -static const char *g_contained_zmm10[] = {"zmm10", NULL}; -static const char *g_contained_zmm11[] = {"zmm11", NULL}; -static const char *g_contained_zmm12[] = {"zmm12", NULL}; -static const char *g_contained_zmm13[] = {"zmm13", NULL}; -static const char *g_contained_zmm14[] = {"zmm14", NULL}; -static const char *g_contained_zmm15[] = {"zmm15", 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), \ - ehframe_dwarf_zmm##reg, ehframe_dwarf_zmm##reg, -1U, \ - 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, ehframe_dwarf_ymm##reg, \ - ehframe_dwarf_ymm##reg, -1U, 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, ehframe_dwarf_xmm##reg, \ - ehframe_dwarf_xmm##reg, -1U, 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), ehframe_dwarf_k##reg, ehframe_dwarf_k##reg, \ - -1U, debugserver_k##reg, NULL, NULL \ - } - -const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_avx512f[] = { - {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), - AVX_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), - AVX_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, - AVX_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), - AVX_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), - AVX_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), - AVX_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), - AVX_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), - AVX_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), - AVX_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, - FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, - NULL}, - - {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, - ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, - {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, - ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, - {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, - ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, - {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, - ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, - {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, - ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, - {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, - ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, - {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, - ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, - {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, - FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, - ehframe_dwarf_stmm7, -1U, 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), - ZMM_REG_DEF(8), - ZMM_REG_DEF(9), - ZMM_REG_DEF(10), - ZMM_REG_DEF(11), - ZMM_REG_DEF(12), - ZMM_REG_DEF(13), - ZMM_REG_DEF(14), - ZMM_REG_DEF(15), - ZMM_REG_DEF(16), - ZMM_REG_DEF(17), - ZMM_REG_DEF(18), - ZMM_REG_DEF(19), - ZMM_REG_DEF(20), - ZMM_REG_DEF(21), - ZMM_REG_DEF(22), - ZMM_REG_DEF(23), - ZMM_REG_DEF(24), - ZMM_REG_DEF(25), - ZMM_REG_DEF(26), - ZMM_REG_DEF(27), - ZMM_REG_DEF(28), - ZMM_REG_DEF(29), - ZMM_REG_DEF(30), - ZMM_REG_DEF(31), - - 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), - YMM_REG_ALIAS(8), - YMM_REG_ALIAS(9), - YMM_REG_ALIAS(10), - YMM_REG_ALIAS(11), - YMM_REG_ALIAS(12), - YMM_REG_ALIAS(13), - YMM_REG_ALIAS(14), - YMM_REG_ALIAS(15), - - 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), - XMM_REG_ALIAS(8), - XMM_REG_ALIAS(9), - XMM_REG_ALIAS(10), - XMM_REG_ALIAS(11), - XMM_REG_ALIAS(12), - XMM_REG_ALIAS(13), - XMM_REG_ALIAS(14), - XMM_REG_ALIAS(15), - -}; - - -// Exception registers - -const DNBRegisterInfo DNBArchImplX86_64::g_exc_registers[] = { - {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno), - EXC_OFFSET(trapno), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err), - EXC_OFFSET(err), -1U, -1U, -1U, -1U, NULL, NULL}, - {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, - EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), -1U, -1U, -1U, -1U, NULL, - NULL}}; - -// Number of registers in each register set -const size_t DNBArchImplX86_64::k_num_gpr_registers = - sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = - sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = - sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_exc_registers = - sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = - k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; -const size_t DNBArchImplX86_64::k_num_all_registers_avx = - k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; -const size_t DNBArchImplX86_64::k_num_fpu_registers_avx512f = - sizeof(g_fpu_registers_avx512f) / sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::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 DNBArchImplX86_64::g_reg_sets_no_avx[] = { - {"x86_64 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 DNBArchImplX86_64::g_reg_sets_avx[] = { - {"x86_64 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 DNBArchImplX86_64::g_reg_sets_avx512f[] = { - {"x86_64 Registers", NULL, k_num_all_registers_avx}, - {"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 DNBArchImplX86_64::k_num_register_sets = - sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo); - -DNBArchProtocol *DNBArchImplX86_64::Create(MachThread *thread) { - DNBArchImplX86_64 *obj = new DNBArchImplX86_64(thread); - return obj; -} - -const uint8_t * -DNBArchImplX86_64::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 * -DNBArchImplX86_64::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() || FORCE_AVX_REGS) - return g_reg_sets_avx; - else - return g_reg_sets_no_avx; -} - -void DNBArchImplX86_64::Initialize() { - DNBArchPluginInfo arch_plugin_info = { - CPU_TYPE_X86_64, DNBArchImplX86_64::Create, - DNBArchImplX86_64::GetRegisterSetInfo, - DNBArchImplX86_64::SoftwareBreakpointOpcode}; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); -} - -bool DNBArchImplX86_64::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_rip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_rsp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_rbp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_rflags; - 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.uint64 = ((uint64_t *)(&m_state.context.gpr))[reg]; - return true; - } - break; - - case e_regSetFPU: - if (reg > fpu_xmm15 && !(CPUHasAVX() || FORCE_AVX_REGS)) - return false; - if (reg > fpu_ymm15 && !(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: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy(&value->value.uint8, - &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); - return true; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy(&value->value.uint8, - &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); - return true; - - case fpu_ymm0: - case fpu_ymm1: - case fpu_ymm2: - case fpu_ymm3: - case fpu_ymm4: - case fpu_ymm5: - case fpu_ymm6: - case fpu_ymm7: - case fpu_ymm8: - case fpu_ymm9: - case fpu_ymm10: - case fpu_ymm11: - case fpu_ymm12: - case fpu_ymm13: - case fpu_ymm14: - case fpu_ymm15: - memcpy(&value->value.uint8, - &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16); - memcpy((&value->value.uint8) + 16, - &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16); - return true; - 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: - case fpu_zmm8: - case fpu_zmm9: - case fpu_zmm10: - case fpu_zmm11: - case fpu_zmm12: - case fpu_zmm13: - case fpu_zmm14: - case fpu_zmm15: - 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; - case fpu_zmm16: - case fpu_zmm17: - case fpu_zmm18: - case fpu_zmm19: - case fpu_zmm20: - case fpu_zmm21: - case fpu_zmm22: - case fpu_zmm23: - case fpu_zmm24: - case fpu_zmm25: - case fpu_zmm26: - case fpu_zmm27: - case fpu_zmm28: - case fpu_zmm29: - case fpu_zmm30: - case fpu_zmm31: - memcpy(&value->value.uint8, - &m_state.context.fpu.avx512f.__fpu_zmm16 + (reg - fpu_zmm16), 64); - return true; - } - break; - - case e_regSetEXC: - switch (reg) { - case exc_trapno: - value->value.uint32 = m_state.context.exc.__trapno; - return true; - case exc_err: - value->value.uint32 = m_state.context.exc.__err; - return true; - case exc_faultvaddr: - value->value.uint64 = m_state.context.exc.__faultvaddr; - return true; - } - break; - } - } - return false; -} - -bool DNBArchImplX86_64::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_rip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_rsp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_rbp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_rflags; - 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) { - ((uint64_t *)(&m_state.context.gpr))[reg] = value->value.uint64; - success = true; - } - break; - if (reg > fpu_xmm15 && !(CPUHasAVX() || FORCE_AVX_REGS)) - return false; - if (reg > fpu_ymm15 && !(CPUHasAVX512f() || FORCE_AVX_REGS)) - return false; - case e_regSetFPU: - 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.uint8, 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: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), - &value->value.uint8, 10); - success = true; - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), - &value->value.uint8, 16); - success = true; - break; - - case fpu_ymm0: - case fpu_ymm1: - case fpu_ymm2: - case fpu_ymm3: - case fpu_ymm4: - case fpu_ymm5: - case fpu_ymm6: - case fpu_ymm7: - case fpu_ymm8: - case fpu_ymm9: - case fpu_ymm10: - case fpu_ymm11: - case fpu_ymm12: - case fpu_ymm13: - case fpu_ymm14: - case fpu_ymm15: - memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), - &value->value.uint8, 16); - memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), - (&value->value.uint8) + 16, 16); - return true; - 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: - case fpu_zmm8: - case fpu_zmm9: - case fpu_zmm10: - case fpu_zmm11: - case fpu_zmm12: - case fpu_zmm13: - case fpu_zmm14: - case fpu_zmm15: - 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; - case fpu_zmm16: - case fpu_zmm17: - case fpu_zmm18: - case fpu_zmm19: - case fpu_zmm20: - case fpu_zmm21: - case fpu_zmm22: - case fpu_zmm23: - case fpu_zmm24: - case fpu_zmm25: - case fpu_zmm26: - case fpu_zmm27: - case fpu_zmm28: - case fpu_zmm29: - case fpu_zmm30: - case fpu_zmm31: - memcpy(&m_state.context.fpu.avx512f.__fpu_zmm16 + (reg - fpu_zmm16), - &value->value.uint8, 64); - return true; - } - break; - - case e_regSetEXC: - switch (reg) { - case exc_trapno: - m_state.context.exc.__trapno = value->value.uint32; - success = true; - break; - case exc_err: - m_state.context.exc.__err = value->value.uint32; - success = true; - break; - case exc_faultvaddr: - m_state.context.exc.__faultvaddr = value->value.uint64; - success = true; - break; - } - break; - } - } - - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; -} - -uint32_t DNBArchImplX86_64::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() || FORCE_AVX_REGS) { - 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 DNBArchImplX86_64::GetRegisterContext(void *buf, - nub_size_t buf_len) { - uint32_t size = GetRegisterContextSize(); - - if (buf && buf_len) { - bool force = false; - kern_return_t kret; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::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, "DNBArchImplX86_64::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, "DNBArchImplX86_64::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); - // We read 5 bytes, but we skip 6 to account for __fpu_rsrv1 - // to match the g_fpu_registers_* tables. - p += 6; - 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 < 16; ++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 < 16; ++i) { - memcpy(p, &m_state.context.fpu.avx512f.__fpu_zmmh0 + i, 32); - p += 32; - } - for (size_t i = 0; i < 16; ++i) { - memcpy(p, &m_state.context.fpu.avx512f.__fpu_zmm16 + i, 64); - p += 64; - } - } - } else { - // Copy the XMM registers in a single block - memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16); - p += 16 * 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, - "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, - (uint64_t)buf_len, size); - // Return the size of the register context even if NULL was passed in - return size; -} - -nub_size_t DNBArchImplX86_64::SetRegisterContext(const void *buf, - nub_size_t buf_len) { - uint32_t size = GetRegisterContextSize(); - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) { - if (size > buf_len) - size = static_cast<uint32_t>(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); - // We wrote 5 bytes, but we skip 6 to account for __fpu_rsrv1 - // to match the g_fpu_registers_* tables. - p += 6; - 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 < 16; ++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 < 16; ++i) { - memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + i, p, 32); - p += 32; - } - for (size_t i = 0; i < 16; ++i) { - memcpy(&m_state.context.fpu.avx512f.__fpu_zmm16 + i, p, 64); - p += 64; - } - } - } else { - // Copy the XMM registers in a single block - memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16); - p += 16 * 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, "DNBArchImplX86_64::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, "DNBArchImplX86_64::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, "DNBArchImplX86_64::SetRegisterContext (buf " - "= %p, len = %llu) error: EXP regs failed " - "to write: %u", - buf, (uint64_t)buf_len, kret); - } - DNBLogThreadedIf( - LOG_THREAD, - "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", - buf, (uint64_t)buf_len, (uint64_t)size); - return size; -} - -uint32_t DNBArchImplX86_64::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, "DNBArchImplX86_64::SaveRegisterState () " - "error: GPR regs failed to read: %u ", - kret); - } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::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 DNBArchImplX86_64::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.SetError(e_regSetGPR, Read, 0); - m_state.SetError(e_regSetFPU, Read, 0); - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) { - DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::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, "DNBArchImplX86_64::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 DNBArchImplX86_64::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 DNBArchImplX86_64::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 DNBArchImplX86_64::RegisterSetStateIsValid(int set) const { - return m_state.RegsAreValid(set); -} - -#endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h deleted file mode 100644 index ef2ba1ee09a6..000000000000 --- a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ /dev/null @@ -1,242 +0,0 @@ -//===-- DNBArchImplX86_64.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/25/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __DNBArchImplX86_64_h__ -#define __DNBArchImplX86_64_h__ - -#if defined(__i386__) || defined(__x86_64__) -#include "DNBArch.h" -#include "MachRegisterStatesX86_64.h" - -#include <map> - -class MachThread; - -class DNBArchImplX86_64 : public DNBArchProtocol { -public: - DNBArchImplX86_64(MachThread *thread) - : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done), m_saved_register_states() {} - virtual ~DNBArchImplX86_64() {} - - static void Initialize(); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, - DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, - const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState(); - virtual bool RestoreRegisterState(uint32_t save_id); - - virtual kern_return_t GetRegisterState(int set, bool force); - virtual kern_return_t SetRegisterState(int set); - virtual bool RegisterSetStateIsValid(int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data &exc); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, - bool read, bool write, - bool also_set_on_task); - virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, - bool also_set_on_task); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - -protected: - kern_return_t EnableHardwareSingleStep(bool enable); - - typedef __x86_64_thread_state_t GPR; - typedef __x86_64_float_state_t FPU; - typedef __x86_64_exception_state_t EXC; - typedef __x86_64_avx_state_t AVX; - typedef __x86_64_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 __x86_64_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; - - typedef enum RegisterSetTag { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPU, - e_regSetEXC, - e_regSetDBG, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag { - 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) - } RegisterSetWordSize; - - 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(); - - // 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); - - virtual bool StartTransForHWP(); - virtual bool RollbackTransForHWP(); - virtual bool FinishTransForHWP(); - 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<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; -}; - -#endif // #if defined (__i386__) || defined (__x86_64__) -#endif // #ifndef __DNBArchImplX86_64_h__ diff --git a/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h b/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h deleted file mode 100644 index fcb648dac59e..000000000000 --- a/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h +++ /dev/null @@ -1,314 +0,0 @@ -//===-- MachRegisterStatesX86_64.h --------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Sean Callanan on 3/16/11. -// -//===----------------------------------------------------------------------===// - -#ifndef __MachRegisterStatesX86_64_h__ -#define __MachRegisterStatesX86_64_h__ - -#include <inttypes.h> - -#define __x86_64_THREAD_STATE 4 -#define __x86_64_FLOAT_STATE 5 -#define __x86_64_EXCEPTION_STATE 6 -#define __x86_64_DEBUG_STATE 11 -#define __x86_64_AVX_STATE 17 -#define __x86_64_AVX512F_STATE 20 - -typedef struct { - uint64_t __rax; - uint64_t __rbx; - uint64_t __rcx; - uint64_t __rdx; - uint64_t __rdi; - uint64_t __rsi; - uint64_t __rbp; - uint64_t __rsp; - uint64_t __r8; - uint64_t __r9; - uint64_t __r10; - uint64_t __r11; - uint64_t __r12; - uint64_t __r13; - uint64_t __r14; - uint64_t __r15; - uint64_t __rip; - uint64_t __rflags; - uint64_t __cs; - uint64_t __fs; - uint64_t __gs; -} __x86_64_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; -} __x86_64_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; -} __x86_64_fp_status_t; - -typedef struct { - uint8_t __mmst_reg[10]; - uint8_t __mmst_rsrv[6]; -} __x86_64_mmst_reg; - -typedef struct { uint8_t __xmm_reg[16]; } __x86_64_xmm_reg; - -typedef struct { - uint32_t __fpu_reserved[2]; - __x86_64_fp_control_t __fpu_fcw; - __x86_64_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; - __x86_64_mmst_reg __fpu_stmm0; - __x86_64_mmst_reg __fpu_stmm1; - __x86_64_mmst_reg __fpu_stmm2; - __x86_64_mmst_reg __fpu_stmm3; - __x86_64_mmst_reg __fpu_stmm4; - __x86_64_mmst_reg __fpu_stmm5; - __x86_64_mmst_reg __fpu_stmm6; - __x86_64_mmst_reg __fpu_stmm7; - __x86_64_xmm_reg __fpu_xmm0; - __x86_64_xmm_reg __fpu_xmm1; - __x86_64_xmm_reg __fpu_xmm2; - __x86_64_xmm_reg __fpu_xmm3; - __x86_64_xmm_reg __fpu_xmm4; - __x86_64_xmm_reg __fpu_xmm5; - __x86_64_xmm_reg __fpu_xmm6; - __x86_64_xmm_reg __fpu_xmm7; - __x86_64_xmm_reg __fpu_xmm8; - __x86_64_xmm_reg __fpu_xmm9; - __x86_64_xmm_reg __fpu_xmm10; - __x86_64_xmm_reg __fpu_xmm11; - __x86_64_xmm_reg __fpu_xmm12; - __x86_64_xmm_reg __fpu_xmm13; - __x86_64_xmm_reg __fpu_xmm14; - __x86_64_xmm_reg __fpu_xmm15; - uint8_t __fpu_rsrv4[6 * 16]; - uint32_t __fpu_reserved1; -} __x86_64_float_state_t; - -typedef struct { - uint32_t __fpu_reserved[2]; - __x86_64_fp_control_t __fpu_fcw; - __x86_64_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; - __x86_64_mmst_reg __fpu_stmm0; - __x86_64_mmst_reg __fpu_stmm1; - __x86_64_mmst_reg __fpu_stmm2; - __x86_64_mmst_reg __fpu_stmm3; - __x86_64_mmst_reg __fpu_stmm4; - __x86_64_mmst_reg __fpu_stmm5; - __x86_64_mmst_reg __fpu_stmm6; - __x86_64_mmst_reg __fpu_stmm7; - __x86_64_xmm_reg __fpu_xmm0; - __x86_64_xmm_reg __fpu_xmm1; - __x86_64_xmm_reg __fpu_xmm2; - __x86_64_xmm_reg __fpu_xmm3; - __x86_64_xmm_reg __fpu_xmm4; - __x86_64_xmm_reg __fpu_xmm5; - __x86_64_xmm_reg __fpu_xmm6; - __x86_64_xmm_reg __fpu_xmm7; - __x86_64_xmm_reg __fpu_xmm8; - __x86_64_xmm_reg __fpu_xmm9; - __x86_64_xmm_reg __fpu_xmm10; - __x86_64_xmm_reg __fpu_xmm11; - __x86_64_xmm_reg __fpu_xmm12; - __x86_64_xmm_reg __fpu_xmm13; - __x86_64_xmm_reg __fpu_xmm14; - __x86_64_xmm_reg __fpu_xmm15; - uint8_t __fpu_rsrv4[6 * 16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __x86_64_xmm_reg __fpu_ymmh0; - __x86_64_xmm_reg __fpu_ymmh1; - __x86_64_xmm_reg __fpu_ymmh2; - __x86_64_xmm_reg __fpu_ymmh3; - __x86_64_xmm_reg __fpu_ymmh4; - __x86_64_xmm_reg __fpu_ymmh5; - __x86_64_xmm_reg __fpu_ymmh6; - __x86_64_xmm_reg __fpu_ymmh7; - __x86_64_xmm_reg __fpu_ymmh8; - __x86_64_xmm_reg __fpu_ymmh9; - __x86_64_xmm_reg __fpu_ymmh10; - __x86_64_xmm_reg __fpu_ymmh11; - __x86_64_xmm_reg __fpu_ymmh12; - __x86_64_xmm_reg __fpu_ymmh13; - __x86_64_xmm_reg __fpu_ymmh14; - __x86_64_xmm_reg __fpu_ymmh15; -} __x86_64_avx_state_t; - -typedef struct { uint8_t __ymm_reg[32]; } __x86_64_ymm_reg; -typedef struct { uint8_t __zmm_reg[64]; } __x86_64_zmm_reg; -typedef struct { uint8_t __opmask_reg[8]; } __x86_64_opmask_reg; - -typedef struct { - uint32_t __fpu_reserved[2]; - __x86_64_fp_control_t __fpu_fcw; - __x86_64_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; - __x86_64_mmst_reg __fpu_stmm0; - __x86_64_mmst_reg __fpu_stmm1; - __x86_64_mmst_reg __fpu_stmm2; - __x86_64_mmst_reg __fpu_stmm3; - __x86_64_mmst_reg __fpu_stmm4; - __x86_64_mmst_reg __fpu_stmm5; - __x86_64_mmst_reg __fpu_stmm6; - __x86_64_mmst_reg __fpu_stmm7; - __x86_64_xmm_reg __fpu_xmm0; - __x86_64_xmm_reg __fpu_xmm1; - __x86_64_xmm_reg __fpu_xmm2; - __x86_64_xmm_reg __fpu_xmm3; - __x86_64_xmm_reg __fpu_xmm4; - __x86_64_xmm_reg __fpu_xmm5; - __x86_64_xmm_reg __fpu_xmm6; - __x86_64_xmm_reg __fpu_xmm7; - __x86_64_xmm_reg __fpu_xmm8; - __x86_64_xmm_reg __fpu_xmm9; - __x86_64_xmm_reg __fpu_xmm10; - __x86_64_xmm_reg __fpu_xmm11; - __x86_64_xmm_reg __fpu_xmm12; - __x86_64_xmm_reg __fpu_xmm13; - __x86_64_xmm_reg __fpu_xmm14; - __x86_64_xmm_reg __fpu_xmm15; - uint8_t __fpu_rsrv4[6 * 16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __x86_64_xmm_reg __fpu_ymmh0; - __x86_64_xmm_reg __fpu_ymmh1; - __x86_64_xmm_reg __fpu_ymmh2; - __x86_64_xmm_reg __fpu_ymmh3; - __x86_64_xmm_reg __fpu_ymmh4; - __x86_64_xmm_reg __fpu_ymmh5; - __x86_64_xmm_reg __fpu_ymmh6; - __x86_64_xmm_reg __fpu_ymmh7; - __x86_64_xmm_reg __fpu_ymmh8; - __x86_64_xmm_reg __fpu_ymmh9; - __x86_64_xmm_reg __fpu_ymmh10; - __x86_64_xmm_reg __fpu_ymmh11; - __x86_64_xmm_reg __fpu_ymmh12; - __x86_64_xmm_reg __fpu_ymmh13; - __x86_64_xmm_reg __fpu_ymmh14; - __x86_64_xmm_reg __fpu_ymmh15; - __x86_64_opmask_reg __fpu_k0; - __x86_64_opmask_reg __fpu_k1; - __x86_64_opmask_reg __fpu_k2; - __x86_64_opmask_reg __fpu_k3; - __x86_64_opmask_reg __fpu_k4; - __x86_64_opmask_reg __fpu_k5; - __x86_64_opmask_reg __fpu_k6; - __x86_64_opmask_reg __fpu_k7; - __x86_64_ymm_reg __fpu_zmmh0; - __x86_64_ymm_reg __fpu_zmmh1; - __x86_64_ymm_reg __fpu_zmmh2; - __x86_64_ymm_reg __fpu_zmmh3; - __x86_64_ymm_reg __fpu_zmmh4; - __x86_64_ymm_reg __fpu_zmmh5; - __x86_64_ymm_reg __fpu_zmmh6; - __x86_64_ymm_reg __fpu_zmmh7; - __x86_64_ymm_reg __fpu_zmmh8; - __x86_64_ymm_reg __fpu_zmmh9; - __x86_64_ymm_reg __fpu_zmmh10; - __x86_64_ymm_reg __fpu_zmmh11; - __x86_64_ymm_reg __fpu_zmmh12; - __x86_64_ymm_reg __fpu_zmmh13; - __x86_64_ymm_reg __fpu_zmmh14; - __x86_64_ymm_reg __fpu_zmmh15; - __x86_64_zmm_reg __fpu_zmm16; - __x86_64_zmm_reg __fpu_zmm17; - __x86_64_zmm_reg __fpu_zmm18; - __x86_64_zmm_reg __fpu_zmm19; - __x86_64_zmm_reg __fpu_zmm20; - __x86_64_zmm_reg __fpu_zmm21; - __x86_64_zmm_reg __fpu_zmm22; - __x86_64_zmm_reg __fpu_zmm23; - __x86_64_zmm_reg __fpu_zmm24; - __x86_64_zmm_reg __fpu_zmm25; - __x86_64_zmm_reg __fpu_zmm26; - __x86_64_zmm_reg __fpu_zmm27; - __x86_64_zmm_reg __fpu_zmm28; - __x86_64_zmm_reg __fpu_zmm29; - __x86_64_zmm_reg __fpu_zmm30; - __x86_64_zmm_reg __fpu_zmm31; - -} __x86_64_avx512f_state_t; - -typedef struct { - uint32_t __trapno; - uint32_t __err; - uint64_t __faultvaddr; -} __x86_64_exception_state_t; - -typedef struct { - uint64_t __dr0; - uint64_t __dr1; - uint64_t __dr2; - uint64_t __dr3; - uint64_t __dr4; - uint64_t __dr5; - uint64_t __dr6; - uint64_t __dr7; -} __x86_64_debug_state_t; - -#endif diff --git a/tools/debugserver/source/PThreadCondition.h b/tools/debugserver/source/PThreadCondition.h deleted file mode 100644 index 9cd64bf24723..000000000000 --- a/tools/debugserver/source/PThreadCondition.h +++ /dev/null @@ -1,35 +0,0 @@ -//===-- PThreadCondition.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/16/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __PThreadCondition_h__ -#define __PThreadCondition_h__ - -#include <pthread.h> - -class PThreadCondition { -public: - PThreadCondition() { ::pthread_cond_init(&m_condition, NULL); } - - ~PThreadCondition() { ::pthread_cond_destroy(&m_condition); } - - pthread_cond_t *Condition() { return &m_condition; } - - int Broadcast() { return ::pthread_cond_broadcast(&m_condition); } - - int Signal() { return ::pthread_cond_signal(&m_condition); } - -protected: - pthread_cond_t m_condition; -}; - -#endif diff --git a/tools/debugserver/source/PThreadEvent.cpp b/tools/debugserver/source/PThreadEvent.cpp deleted file mode 100644 index 1b0900ca7107..000000000000 --- a/tools/debugserver/source/PThreadEvent.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//===-- PThreadEvent.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/16/07. -// -//===----------------------------------------------------------------------===// - -#include "PThreadEvent.h" -#include "DNBLog.h" -#include "errno.h" - -PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) - : m_mutex(), m_set_condition(), m_reset_condition(), m_bits(bits), - m_validBits(validBits), m_reset_ack_mask(0) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", - // this, __FUNCTION__, bits, validBits); -} - -PThreadEvent::~PThreadEvent() { - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); -} - -uint32_t PThreadEvent::NewEventBit() { - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - uint32_t mask = 1; - while (mask & m_validBits) - mask <<= 1; - m_validBits |= mask; - return mask; -} - -void PThreadEvent::FreeEventBits(const uint32_t mask) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, - // __FUNCTION__, mask); - if (mask) { - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - m_bits &= ~mask; - m_validBits &= ~mask; - } -} - -uint32_t PThreadEvent::GetEventBits() const { - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - uint32_t bits = m_bits; - return bits; -} - -// Replace the event bits with a new bitmask value -void PThreadEvent::ReplaceEventBits(const uint32_t bits) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, - // __FUNCTION__, bits); - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - // Make sure we have some bits and that they aren't already set... - if (m_bits != bits) { - // Figure out which bits are changing - uint32_t changed_bits = m_bits ^ bits; - // Set the new bit values - m_bits = bits; - // If any new bits are set, then broadcast - if (changed_bits & m_bits) - m_set_condition.Broadcast(); - } -} - -// Set one or more event bits and broadcast if any new event bits get set -// that weren't already set. - -void PThreadEvent::SetEvents(const uint32_t mask) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, - // __FUNCTION__, mask); - // Make sure we have some bits to set - if (mask) { - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Set the all event bits that are set in 'mask' - m_bits |= mask; - // Broadcast only if any extra bits got set. - if (old != m_bits) - m_set_condition.Broadcast(); - } -} - -// Reset one or more event bits -void PThreadEvent::ResetEvents(const uint32_t mask) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, - // __FUNCTION__, mask); - if (mask) { - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Clear the all event bits that are set in 'mask' - m_bits &= ~mask; - // Broadcast only if any extra bits got reset. - if (old != m_bits) - m_reset_condition.Broadcast(); - } -} - -//---------------------------------------------------------------------- -// Wait until 'timeout_abstime' for any events that are set in -// 'mask'. If 'timeout_abstime' is NULL, then wait forever. -//---------------------------------------------------------------------- -uint32_t -PThreadEvent::WaitForSetEvents(const uint32_t mask, - const struct timespec *timeout_abstime) const { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, - // __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - do { - // Check our predicate (event bits) in case any are already set - if (mask & m_bits) { - uint32_t bits_set = mask & m_bits; - // Our PThreadMutex::Locker will automatically unlock our mutex - return bits_set; - } - if (timeout_abstime) { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait(m_set_condition.Condition(), - m_mutex.Mutex(), timeout_abstime); - // Retest our predicate in case of a race condition right at the end - // of the timeout. - if (err == ETIMEDOUT) { - uint32_t bits_set = mask & m_bits; - return bits_set; - } - } else { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait(m_set_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - return 0; -} - -//---------------------------------------------------------------------- -// Wait until 'timeout_abstime' for any events in 'mask' to reset. -// If 'timeout_abstime' is NULL, then wait forever. -//---------------------------------------------------------------------- -uint32_t PThreadEvent::WaitForEventsToReset( - const uint32_t mask, const struct timespec *timeout_abstime) const { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, - // __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER(locker, m_mutex); - do { - // Check our predicate (event bits) each time through this do loop - if ((mask & m_bits) == 0) { - // All the bits requested have been reset, return zero indicating - // which bits from the mask were still set (none of them) - return 0; - } - if (timeout_abstime) { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait(m_reset_condition.Condition(), - m_mutex.Mutex(), timeout_abstime); - } else { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait(m_reset_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - // Return a mask indicating which bits (if any) were still set - return mask & m_bits; -} - -uint32_t -PThreadEvent::WaitForResetAck(const uint32_t mask, - const struct timespec *timeout_abstime) const { - if (mask & m_reset_ack_mask) { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, - // __FUNCTION__, mask, timeout_abstime); - return WaitForEventsToReset(mask & m_reset_ack_mask, timeout_abstime); - } - return 0; -} diff --git a/tools/debugserver/source/PThreadEvent.h b/tools/debugserver/source/PThreadEvent.h deleted file mode 100644 index fbcd4593352b..000000000000 --- a/tools/debugserver/source/PThreadEvent.h +++ /dev/null @@ -1,64 +0,0 @@ -//===-- PThreadEvent.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/16/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __PThreadEvent_h__ -#define __PThreadEvent_h__ -#include "PThreadCondition.h" -#include "PThreadMutex.h" -#include <stdint.h> -#include <time.h> - -class PThreadEvent { -public: - PThreadEvent(uint32_t bits = 0, uint32_t validBits = 0); - ~PThreadEvent(); - - uint32_t NewEventBit(); - void FreeEventBits(const uint32_t mask); - - void ReplaceEventBits(const uint32_t bits); - uint32_t GetEventBits() const; - void SetEvents(const uint32_t mask); - void ResetEvents(const uint32_t mask); - // Wait for events to be set or reset. These functions take an optional - // timeout value. If timeout is NULL an infinite timeout will be used. - uint32_t - WaitForSetEvents(const uint32_t mask, - const struct timespec *timeout_abstime = NULL) const; - uint32_t - WaitForEventsToReset(const uint32_t mask, - const struct timespec *timeout_abstime = NULL) const; - - uint32_t GetResetAckMask() const { return m_reset_ack_mask; } - uint32_t SetResetAckMask(uint32_t mask) { return m_reset_ack_mask = mask; } - uint32_t WaitForResetAck(const uint32_t mask, - const struct timespec *timeout_abstime = NULL) const; - -protected: - //---------------------------------------------------------------------- - // pthread condition and mutex variable to control access and allow - // blocking between the main thread and the spotlight index thread. - //---------------------------------------------------------------------- - mutable PThreadMutex m_mutex; - mutable PThreadCondition m_set_condition; - mutable PThreadCondition m_reset_condition; - uint32_t m_bits; - uint32_t m_validBits; - uint32_t m_reset_ack_mask; - -private: - PThreadEvent(const PThreadEvent &); // Outlaw copy constructor - PThreadEvent &operator=(const PThreadEvent &rhs); -}; - -#endif // #ifndef __PThreadEvent_h__ diff --git a/tools/debugserver/source/PThreadMutex.cpp b/tools/debugserver/source/PThreadMutex.cpp deleted file mode 100644 index 0e9132e380bf..000000000000 --- a/tools/debugserver/source/PThreadMutex.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//===-- PThreadMutex.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/9/08. -// -//===----------------------------------------------------------------------===// - -#include "PThreadMutex.h" - -#include "DNBTimer.h" - -#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) - -PThreadMutex::Locker::Locker(PThreadMutex &m, const char *function, - const char *file, const int line) - : m_pMutex(m.Mutex()), m_function(function), m_file(file), m_line(line), - m_lock_time(0) { - Lock(); -} - -PThreadMutex::Locker::Locker(PThreadMutex *m, const char *function, - const char *file, const int line) - : m_pMutex(m ? m->Mutex() : NULL), m_function(function), m_file(file), - m_line(line), m_lock_time(0) { - Lock(); -} - -PThreadMutex::Locker::Locker(pthread_mutex_t *mutex, const char *function, - const char *file, const int line) - : m_pMutex(mutex), m_function(function), m_file(file), m_line(line), - m_lock_time(0) { - Lock(); -} - -PThreadMutex::Locker::~Locker() { Unlock(); } - -void PThreadMutex::Locker::Lock() { - if (m_pMutex) { - m_lock_time = DNBTimer::GetTimeOfDay(); - if (::pthread_mutex_trylock(m_pMutex) != 0) { - fprintf(stdout, "::pthread_mutex_trylock (%8.8p) mutex is locked " - "(function %s in %s:%i), waiting...\n", - m_pMutex, m_function, m_file, m_line); - ::pthread_mutex_lock(m_pMutex); - fprintf(stdout, "::pthread_mutex_lock (%8.8p) succeeded after %6llu " - "usecs (function %s in %s:%i)\n", - m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, - m_file, m_line); - } - } -} - -void PThreadMutex::Locker::Unlock() { - fprintf(stdout, "::pthread_mutex_unlock (%8.8p) had lock for %6llu usecs in " - "%s in %s:%i\n", - m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, - m_line); - ::pthread_mutex_unlock(m_pMutex); -} - -#endif diff --git a/tools/debugserver/source/PThreadMutex.h b/tools/debugserver/source/PThreadMutex.h deleted file mode 100644 index c6ec293c5e59..000000000000 --- a/tools/debugserver/source/PThreadMutex.h +++ /dev/null @@ -1,120 +0,0 @@ -//===-- PThreadMutex.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/16/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __PThreadMutex_h__ -#define __PThreadMutex_h__ - -#include <assert.h> -#include <pthread.h> -#include <stdint.h> - -//#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1 - -#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) -#define PTHREAD_MUTEX_LOCKER(var, mutex) \ - PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__) - -#else -#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex) -#endif - -class PThreadMutex { -public: - class Locker { - public: -#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) - - Locker(PThreadMutex &m, const char *function, const char *file, int line); - Locker(PThreadMutex *m, const char *function, const char *file, int line); - Locker(pthread_mutex_t *mutex, const char *function, const char *file, - int line); - ~Locker(); - void Lock(); - void Unlock(); - -#else - Locker(PThreadMutex &m) : m_pMutex(m.Mutex()) { Lock(); } - - Locker(PThreadMutex *m) : m_pMutex(m ? m->Mutex() : NULL) { Lock(); } - - Locker(pthread_mutex_t *mutex) : m_pMutex(mutex) { Lock(); } - - void Lock() { - if (m_pMutex) - ::pthread_mutex_lock(m_pMutex); - } - - void Unlock() { - if (m_pMutex) - ::pthread_mutex_unlock(m_pMutex); - } - - ~Locker() { Unlock(); } - -#endif - - // unlock any the current mutex and lock the new one if it is valid - void Reset(pthread_mutex_t *pMutex = NULL) { - Unlock(); - m_pMutex = pMutex; - Lock(); - } - pthread_mutex_t *m_pMutex; -#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) - const char *m_function; - const char *m_file; - int m_line; - uint64_t m_lock_time; -#endif - }; - - PThreadMutex() { - int err; - err = ::pthread_mutex_init(&m_mutex, NULL); - assert(err == 0); - } - - PThreadMutex(int type) { - int err; - ::pthread_mutexattr_t attr; - err = ::pthread_mutexattr_init(&attr); - assert(err == 0); - err = ::pthread_mutexattr_settype(&attr, type); - assert(err == 0); - err = ::pthread_mutex_init(&m_mutex, &attr); - assert(err == 0); - err = ::pthread_mutexattr_destroy(&attr); - assert(err == 0); - } - - ~PThreadMutex() { - int err; - err = ::pthread_mutex_destroy(&m_mutex); - if (err != 0) { - err = Unlock(); - if (err == 0) - ::pthread_mutex_destroy(&m_mutex); - } - } - - pthread_mutex_t *Mutex() { return &m_mutex; } - - int Lock() { return ::pthread_mutex_lock(&m_mutex); } - - int Unlock() { return ::pthread_mutex_unlock(&m_mutex); } - -protected: - pthread_mutex_t m_mutex; -}; - -#endif diff --git a/tools/debugserver/source/PseudoTerminal.cpp b/tools/debugserver/source/PseudoTerminal.cpp deleted file mode 100644 index 892574a61dcf..000000000000 --- a/tools/debugserver/source/PseudoTerminal.cpp +++ /dev/null @@ -1,196 +0,0 @@ -//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/8/08. -// -//===----------------------------------------------------------------------===// - -#include "PseudoTerminal.h" -#include <stdlib.h> -#include <sys/ioctl.h> -#include <unistd.h> - -//---------------------------------------------------------------------- -// PseudoTerminal constructor -//---------------------------------------------------------------------- -PseudoTerminal::PseudoTerminal() - : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {} - -//---------------------------------------------------------------------- -// Destructor -// The master and slave file descriptors will get closed if they are -// valid. Call the ReleaseMasterFD()/ReleaseSlaveFD() member functions -// to release any file descriptors that are needed beyond the lifespan -// of this object. -//---------------------------------------------------------------------- -PseudoTerminal::~PseudoTerminal() { - CloseMaster(); - CloseSlave(); -} - -//---------------------------------------------------------------------- -// Close the master file descriptor if it is valid. -//---------------------------------------------------------------------- -void PseudoTerminal::CloseMaster() { - if (m_master_fd > 0) { - ::close(m_master_fd); - m_master_fd = invalid_fd; - } -} - -//---------------------------------------------------------------------- -// Close the slave file descriptor if it is valid. -//---------------------------------------------------------------------- -void PseudoTerminal::CloseSlave() { - if (m_slave_fd > 0) { - ::close(m_slave_fd); - m_slave_fd = invalid_fd; - } -} - -//---------------------------------------------------------------------- -// Open the first available pseudo terminal with OFLAG as the -// permissions. The file descriptor is store in the m_master_fd member -// variable and can be accessed via the MasterFD() or ReleaseMasterFD() -// accessors. -// -// Suggested value for oflag is O_RDWR|O_NOCTTY -// -// RETURNS: -// Zero when successful, non-zero indicating an error occurred. -//---------------------------------------------------------------------- -PseudoTerminal::Status PseudoTerminal::OpenFirstAvailableMaster(int oflag) { - // Open the master side of a pseudo terminal - m_master_fd = ::posix_openpt(oflag); - if (m_master_fd < 0) { - return err_posix_openpt_failed; - } - - // Grant access to the slave pseudo terminal - if (::grantpt(m_master_fd) < 0) { - CloseMaster(); - return err_grantpt_failed; - } - - // Clear the lock flag on the slave pseudo terminal - if (::unlockpt(m_master_fd) < 0) { - CloseMaster(); - return err_unlockpt_failed; - } - - return success; -} - -//---------------------------------------------------------------------- -// Open the slave pseudo terminal for the current master pseudo -// terminal. A master pseudo terminal should already be valid prior to -// calling this function (see PseudoTerminal::OpenFirstAvailableMaster()). -// The file descriptor is stored in the m_slave_fd member variable and -// can be accessed via the SlaveFD() or ReleaseSlaveFD() accessors. -// -// RETURNS: -// Zero when successful, non-zero indicating an error occurred. -//---------------------------------------------------------------------- -PseudoTerminal::Status PseudoTerminal::OpenSlave(int oflag) { - CloseSlave(); - - // Open the master side of a pseudo terminal - const char *slave_name = SlaveName(); - - if (slave_name == NULL) - return err_ptsname_failed; - - m_slave_fd = ::open(slave_name, oflag); - - if (m_slave_fd < 0) - return err_open_slave_failed; - - return success; -} - -//---------------------------------------------------------------------- -// Get the name of the slave pseudo terminal. A master pseudo terminal -// should already be valid prior to calling this function (see -// PseudoTerminal::OpenFirstAvailableMaster()). -// -// RETURNS: -// NULL if no valid master pseudo terminal or if ptsname() fails. -// The name of the slave pseudo terminal as a NULL terminated C string -// that comes from static memory, so a copy of the string should be -// made as subsequent calls can change this value. -//---------------------------------------------------------------------- -const char *PseudoTerminal::SlaveName() const { - if (m_master_fd < 0) - return NULL; - return ::ptsname(m_master_fd); -} - -//---------------------------------------------------------------------- -// Fork a child process that and have its stdio routed to a pseudo -// terminal. -// -// In the parent process when a valid pid is returned, the master file -// descriptor can be used as a read/write access to stdio of the -// child process. -// -// In the child process the stdin/stdout/stderr will already be routed -// to the slave pseudo terminal and the master file descriptor will be -// closed as it is no longer needed by the child process. -// -// This class will close the file descriptors for the master/slave -// when the destructor is called, so be sure to call ReleaseMasterFD() -// or ReleaseSlaveFD() if any file descriptors are going to be used -// past the lifespan of this object. -// -// RETURNS: -// in the parent process: the pid of the child, or -1 if fork fails -// in the child process: zero -//---------------------------------------------------------------------- - -pid_t PseudoTerminal::Fork(PseudoTerminal::Status &error) { - pid_t pid = invalid_pid; - error = OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); - - if (error == 0) { - // Successfully opened our master pseudo terminal - - pid = ::fork(); - if (pid < 0) { - // Fork failed - error = err_fork_failed; - } else if (pid == 0) { - // Child Process - ::setsid(); - - error = OpenSlave(O_RDWR); - if (error == 0) { - // Successfully opened slave - // We are done with the master in the child process so lets close it - CloseMaster(); - -#if defined(TIOCSCTTY) - // Acquire the controlling terminal - if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) - error = err_failed_to_acquire_controlling_terminal; -#endif - // Duplicate all stdio file descriptors to the slave pseudo terminal - if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) - error = error ? error : err_dup2_failed_on_stdin; - if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) - error = error ? error : err_dup2_failed_on_stdout; - if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) - error = error ? error : err_dup2_failed_on_stderr; - } - } else { - // Parent Process - // Do nothing and let the pid get returned! - } - } - return pid; -} diff --git a/tools/debugserver/source/PseudoTerminal.h b/tools/debugserver/source/PseudoTerminal.h deleted file mode 100644 index f6b71f8909a6..000000000000 --- a/tools/debugserver/source/PseudoTerminal.h +++ /dev/null @@ -1,87 +0,0 @@ -//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 1/8/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __PseudoTerminal_h__ -#define __PseudoTerminal_h__ - -#include <fcntl.h> -#include <string> -#include <termios.h> - -class PseudoTerminal { -public: - enum { invalid_fd = -1, invalid_pid = -1 }; - - enum Status { - success = 0, - err_posix_openpt_failed = -2, - err_grantpt_failed = -3, - err_unlockpt_failed = -4, - err_ptsname_failed = -5, - err_open_slave_failed = -6, - err_fork_failed = -7, - err_setsid_failed = -8, - err_failed_to_acquire_controlling_terminal = -9, - err_dup2_failed_on_stdin = -10, - err_dup2_failed_on_stdout = -11, - err_dup2_failed_on_stderr = -12 - }; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - PseudoTerminal(); - ~PseudoTerminal(); - - void CloseMaster(); - void CloseSlave(); - Status OpenFirstAvailableMaster(int oflag); - Status OpenSlave(int oflag); - int MasterFD() const { return m_master_fd; } - int SlaveFD() const { return m_slave_fd; } - int ReleaseMasterFD() { - // Release ownership of the master pseudo terminal file - // descriptor without closing it. (the destructor for this - // class will close it otherwise!) - int fd = m_master_fd; - m_master_fd = invalid_fd; - return fd; - } - int ReleaseSlaveFD() { - // Release ownership of the slave pseudo terminal file - // descriptor without closing it (the destructor for this - // class will close it otherwise!) - int fd = m_slave_fd; - m_slave_fd = invalid_fd; - return fd; - } - - const char *SlaveName() const; - - pid_t Fork(Status &error); - -protected: - //------------------------------------------------------------------ - // Classes that inherit from PseudoTerminal can see and modify these - //------------------------------------------------------------------ - int m_master_fd; - int m_slave_fd; - -private: - //------------------------------------------------------------------ - // Outlaw copy and assignment constructors - //------------------------------------------------------------------ - PseudoTerminal(const PseudoTerminal &rhs); - PseudoTerminal &operator=(const PseudoTerminal &rhs); -}; - -#endif // #ifndef __PseudoTerminal_h__ diff --git a/tools/debugserver/source/RNBContext.cpp b/tools/debugserver/source/RNBContext.cpp deleted file mode 100644 index c86511c6e226..000000000000 --- a/tools/debugserver/source/RNBContext.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//===-- RNBContext.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#include "RNBContext.h" - -#include <sstream> -#include <sys/stat.h> - -#if defined(__APPLE__) -#include <pthread.h> -#include <sched.h> -#endif - -#include "CFString.h" -#include "DNB.h" -#include "DNBLog.h" -#include "RNBRemote.h" - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -RNBContext::~RNBContext() { SetProcessID(INVALID_NUB_PROCESS); } - -//---------------------------------------------------------------------- -// RNBContext constructor -//---------------------------------------------------------------------- - -const char *RNBContext::EnvironmentAtIndex(size_t index) { - if (index < m_env_vec.size()) - return m_env_vec[index].c_str(); - else - return NULL; -} - -static std::string GetEnvironmentKey(const std::string &env) { - std::string key = env.substr(0, env.find('=')); - if (!key.empty() && key.back() == '=') - key.pop_back(); - return key; -} - -void RNBContext::PushEnvironmentIfNeeded(const char *arg) { - if (!arg) - return; - std::string arg_key = GetEnvironmentKey(arg); - - for (const std::string &entry: m_env_vec) { - if (arg_key == GetEnvironmentKey(entry)) - return; - } - m_env_vec.push_back(arg); -} - -const char *RNBContext::ArgumentAtIndex(size_t index) { - if (index < m_arg_vec.size()) - return m_arg_vec[index].c_str(); - else - return NULL; -} - -bool RNBContext::SetWorkingDirectory(const char *path) { - struct stat working_directory_stat; - if (::stat(path, &working_directory_stat) != 0) { - m_working_directory.clear(); - return false; - } - m_working_directory.assign(path); - return true; -} - -void RNBContext::SetProcessID(nub_process_t pid) { - // Delete and events we created - if (m_pid != INVALID_NUB_PROCESS) { - StopProcessStatusThread(); - // Unregister this context as a client of the process's events. - } - // Assign our new process ID - m_pid = pid; - - if (pid != INVALID_NUB_PROCESS) { - StartProcessStatusThread(); - } -} - -void RNBContext::StartProcessStatusThread() { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); - if ((m_events.GetEventBits() & event_proc_thread_running) == 0) { - int err = ::pthread_create(&m_pid_pthread, NULL, - ThreadFunctionProcessStatus, this); - if (err == 0) { - // Our thread was successfully kicked off, wait for it to - // set the started event so we can safely continue - m_events.WaitForSetEvents(event_proc_thread_running); - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!", - __FUNCTION__); - } else { - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s thread failed to start: err = %i", - __FUNCTION__, err); - m_events.ResetEvents(event_proc_thread_running); - m_events.SetEvents(event_proc_thread_exiting); - } - } -} - -void RNBContext::StopProcessStatusThread() { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); - if ((m_events.GetEventBits() & event_proc_thread_running) == - event_proc_thread_running) { - struct timespec timeout_abstime; - DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); - // Wait for 2 seconds for the rx thread to exit - if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting, - &timeout_abstime) == - RNBContext::event_proc_thread_exiting) { - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s thread stopped as requeseted", - __FUNCTION__); - } else { - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s thread did not stop in 2 seconds...", - __FUNCTION__); - // Kill the RX thread??? - } - } -} - -//---------------------------------------------------------------------- -// This thread's sole purpose is to watch for any status changes in the -// child process. -//---------------------------------------------------------------------- -void *RNBContext::ThreadFunctionProcessStatus(void *arg) { - RNBRemoteSP remoteSP(g_remoteSP); - RNBRemote *remote = remoteSP.get(); - if (remote == NULL) - return NULL; - RNBContext &ctx = remote->Context(); - - nub_process_t pid = ctx.ProcessID(); - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", - __FUNCTION__, arg, pid); - ctx.Events().SetEvents(RNBContext::event_proc_thread_running); - -#if defined(__APPLE__) - pthread_setname_np("child process status watcher thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } -#endif -#endif - - bool done = false; - while (!done) { - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s calling DNBProcessWaitForEvent(pid, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged | eEventStdioAvailable " - "| eEventProfileDataAvailable, true)...", - __FUNCTION__); - nub_event_t pid_status_event = DNBProcessWaitForEvents( - pid, - eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | - eEventStdioAvailable | eEventProfileDataAvailable, - true, NULL); - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s calling DNBProcessWaitForEvent(pid, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged | eEventStdioAvailable " - "| eEventProfileDataAvailable, true) => 0x%8.8x", - __FUNCTION__, pid_status_event); - - if (pid_status_event == 0) { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back " - "from DNBProcessWaitForEvent....", - __FUNCTION__, pid); - // done = true; - } else { - if (pid_status_event & eEventStdioAvailable) { - DNBLogThreadedIf( - LOG_RNB_PROC, - "RNBContext::%s (pid=%4.4x) got stdio available event....", - __FUNCTION__, pid); - ctx.Events().SetEvents(RNBContext::event_proc_stdio_available); - // Wait for the main thread to consume this notification if it requested - // we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); - } - - if (pid_status_event & eEventProfileDataAvailable) { - DNBLogThreadedIf( - LOG_RNB_PROC, - "RNBContext::%s (pid=%4.4x) got profile data event....", - __FUNCTION__, pid); - ctx.Events().SetEvents(RNBContext::event_proc_profile_data); - // Wait for the main thread to consume this notification if it requested - // we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data); - } - - if (pid_status_event & (eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged)) { - nub_state_t pid_state = DNBProcessGetState(pid); - DNBLogThreadedIf( - LOG_RNB_PROC, - "RNBContext::%s (pid=%4.4x) got process state change: %s", - __FUNCTION__, pid, DNBStateAsString(pid_state)); - - // Let the main thread know there is a process state change to see - ctx.Events().SetEvents(RNBContext::event_proc_state_changed); - // Wait for the main thread to consume this notification if it requested - // we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); - - switch (pid_state) { - case eStateStopped: - break; - - case eStateInvalid: - case eStateExited: - case eStateDetached: - done = true; - break; - default: - break; - } - } - - // Reset any events that we consumed. - DNBProcessResetEvents(pid, pid_status_event); - } - } - DNBLogThreadedIf(LOG_RNB_PROC, - "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", - __FUNCTION__, arg, pid); - ctx.Events().ResetEvents(event_proc_thread_running); - ctx.Events().SetEvents(event_proc_thread_exiting); - return NULL; -} - -const char *RNBContext::EventsAsString(nub_event_t events, std::string &s) { - s.clear(); - if (events & event_proc_state_changed) - s += "proc_state_changed "; - if (events & event_proc_thread_running) - s += "proc_thread_running "; - if (events & event_proc_thread_exiting) - s += "proc_thread_exiting "; - if (events & event_proc_stdio_available) - s += "proc_stdio_available "; - if (events & event_proc_profile_data) - s += "proc_profile_data "; - if (events & event_darwin_log_data_available) - s += "darwin_log_data_available "; - if (events & event_read_packet_available) - s += "read_packet_available "; - if (events & event_read_thread_running) - s += "read_thread_running "; - if (events & event_read_thread_running) - s += "read_thread_running "; - return s.c_str(); -} - -const char *RNBContext::LaunchStatusAsString(std::string &s) { - s.clear(); - - const char *err_str = m_launch_status.AsString(); - if (err_str) - s = err_str; - else { - char error_num_str[64]; - snprintf(error_num_str, sizeof(error_num_str), "%u", - m_launch_status.Status()); - s = error_num_str; - } - return s.c_str(); -} - -bool RNBContext::ProcessStateRunning() const { - nub_state_t pid_state = DNBProcessGetState(m_pid); - return pid_state == eStateRunning || pid_state == eStateStepping; -} diff --git a/tools/debugserver/source/RNBContext.h b/tools/debugserver/source/RNBContext.h deleted file mode 100644 index 0c649ae41007..000000000000 --- a/tools/debugserver/source/RNBContext.h +++ /dev/null @@ -1,164 +0,0 @@ -//===-- RNBContext.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __RNBContext_h__ -#define __RNBContext_h__ - -#include "DNBError.h" -#include "PThreadEvent.h" -#include "RNBDefs.h" -#include <string> -#include <vector> - -class RNBContext { -public: - enum { - event_proc_state_changed = 0x001, - event_proc_thread_running = 0x002, // Sticky - event_proc_thread_exiting = 0x004, - event_proc_stdio_available = 0x008, - event_proc_profile_data = 0x010, - event_read_packet_available = 0x020, - event_read_thread_running = 0x040, // Sticky - event_read_thread_exiting = 0x080, - event_darwin_log_data_available = 0x100, - - normal_event_bits = event_proc_state_changed | event_proc_thread_exiting | - event_proc_stdio_available | event_proc_profile_data | - event_read_packet_available | - event_read_thread_exiting | - event_darwin_log_data_available, - - sticky_event_bits = event_proc_thread_running | event_read_thread_running, - - all_event_bits = sticky_event_bits | normal_event_bits - } event_t; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RNBContext() - : m_pid(INVALID_NUB_PROCESS), m_pid_stop_count(0), - m_events(0, all_event_bits), m_pid_pthread(), m_launch_status(), - m_arg_vec(), m_env_vec(), m_detach_on_error(false) {} - - virtual ~RNBContext(); - - nub_process_t ProcessID() const { return m_pid; } - bool HasValidProcessID() const { return m_pid != INVALID_NUB_PROCESS; } - void SetProcessID(nub_process_t pid); - nub_size_t GetProcessStopCount() const { return m_pid_stop_count; } - bool SetProcessStopCount(nub_size_t count) { - // Returns true if this class' notion of the PID state changed - if (m_pid_stop_count == count) - return false; // Didn't change - m_pid_stop_count = count; - return true; // The stop count has changed. - } - - bool ProcessStateRunning() const; - PThreadEvent &Events() { return m_events; } - nub_event_t AllEventBits() const { return all_event_bits; } - nub_event_t NormalEventBits() const { return normal_event_bits; } - nub_event_t StickyEventBits() const { return sticky_event_bits; } - const char *EventsAsString(nub_event_t events, std::string &s); - - size_t ArgumentCount() const { return m_arg_vec.size(); } - const char *ArgumentAtIndex(size_t index); - void PushArgument(const char *arg) { - if (arg) - m_arg_vec.push_back(arg); - } - void ClearArgv() { m_arg_vec.erase(m_arg_vec.begin(), m_arg_vec.end()); } - - size_t EnvironmentCount() const { return m_env_vec.size(); } - const char *EnvironmentAtIndex(size_t index); - void PushEnvironment(const char *arg) { - if (arg) - m_env_vec.push_back(arg); - } - void PushEnvironmentIfNeeded(const char *arg); - void ClearEnvironment() { - m_env_vec.erase(m_env_vec.begin(), m_env_vec.end()); - } - DNBError &LaunchStatus() { return m_launch_status; } - const char *LaunchStatusAsString(std::string &s); - nub_launch_flavor_t LaunchFlavor() const { return m_launch_flavor; } - void SetLaunchFlavor(nub_launch_flavor_t flavor) { m_launch_flavor = flavor; } - - const char *GetWorkingDirectory() const { - if (!m_working_directory.empty()) - return m_working_directory.c_str(); - return NULL; - } - - bool SetWorkingDirectory(const char *path); - - std::string &GetSTDIN() { return m_stdin; } - std::string &GetSTDOUT() { return m_stdout; } - std::string &GetSTDERR() { return m_stderr; } - std::string &GetWorkingDir() { return m_working_dir; } - - const char *GetSTDINPath() { - return m_stdin.empty() ? NULL : m_stdin.c_str(); - } - const char *GetSTDOUTPath() { - return m_stdout.empty() ? NULL : m_stdout.c_str(); - } - const char *GetSTDERRPath() { - return m_stderr.empty() ? NULL : m_stderr.c_str(); - } - const char *GetWorkingDirPath() { - return m_working_dir.empty() ? NULL : m_working_dir.c_str(); - } - - void PushProcessEvent(const char *p) { m_process_event.assign(p); } - const char *GetProcessEvent() { return m_process_event.c_str(); } - - void SetDetachOnError(bool detach) { m_detach_on_error = detach; } - bool GetDetachOnError() { return m_detach_on_error; } - -protected: - //------------------------------------------------------------------ - // Classes that inherit from RNBContext can see and modify these - //------------------------------------------------------------------ - nub_process_t m_pid; - std::string m_stdin; - std::string m_stdout; - std::string m_stderr; - std::string m_working_dir; - nub_size_t m_pid_stop_count; - PThreadEvent m_events; // Threaded events that we can wait for - pthread_t m_pid_pthread; - nub_launch_flavor_t m_launch_flavor; // How to launch our inferior process - DNBError - m_launch_status; // This holds the status from the last launch attempt. - std::vector<std::string> m_arg_vec; - std::vector<std::string> - m_env_vec; // This will be unparsed - entries FOO=value - std::string m_working_directory; - std::string m_process_event; - bool m_detach_on_error; - - void StartProcessStatusThread(); - void StopProcessStatusThread(); - static void *ThreadFunctionProcessStatus(void *arg); - -private: - //------------------------------------------------------------------ - // Outlaw copy and assignment operators - //------------------------------------------------------------------ - RNBContext(const RNBContext &rhs); - RNBContext &operator=(const RNBContext &rhs); -}; - -#endif // #ifndef __RNBContext_h__ diff --git a/tools/debugserver/source/RNBDefs.h b/tools/debugserver/source/RNBDefs.h deleted file mode 100644 index 5714099f5fcd..000000000000 --- a/tools/debugserver/source/RNBDefs.h +++ /dev/null @@ -1,99 +0,0 @@ -//===-- RNBDefs.h -----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/14/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __RNBDefs_h__ -#define __RNBDefs_h__ - -#include "DNBDefs.h" -#include <memory> - -#define CONCAT2(a, b) a##b -#define CONCAT(a, b) CONCAT2(a, b) -#define STRINGIZE2(x) #x -#define STRINGIZE(x) STRINGIZE2(x) - -#if !defined(DEBUGSERVER_PROGRAM_SYMBOL) -#define DEBUGSERVER_PROGRAM_SYMBOL debugserver -#endif - -#if !defined(DEBUGSERVER_PROGRAM_NAME) -#define DEBUGSERVER_PROGRAM_NAME STRINGIZE(DEBUGSERVER_PROGRAM_SYMBOL) -#endif - -#ifndef DEBUGSERVER_VERSION_NUM -extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, - VersionString)[]; -#define DEBUGSERVER_VERSION_NUM \ - CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber) -#endif - -#ifndef DEBUGSERVER_VERSION_STR -extern "C" const double CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber); -#define DEBUGSERVER_VERSION_STR \ - CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString) -#endif - -#if defined(__i386__) - -#define RNB_ARCH "i386" - -#elif defined(__x86_64__) - -#define RNB_ARCH "x86_64" - -#elif defined(__ppc64__) - -#define RNB_ARCH "ppc64" - -#elif defined(__powerpc__) || defined(__ppc__) - -#define RNB_ARCH "ppc" - -#elif defined(__arm64__) || defined(__aarch64__) - -#define RNB_ARCH "arm64" - -#elif defined(__arm__) - -#define RNB_ARCH "armv7" - -#else - -#error undefined architecture - -#endif - -class RNBRemote; -typedef std::shared_ptr<RNBRemote> RNBRemoteSP; - -typedef enum { rnb_success = 0, rnb_err = 1, rnb_not_connected = 2 } rnb_err_t; - -// Log bits -// reserve low bits for DNB -#define LOG_RNB_MINIMAL \ - ((LOG_LO_USER) << 0) // Minimal logging (min verbosity) -#define LOG_RNB_MEDIUM \ - ((LOG_LO_USER) << 1) // Medium logging (med verbosity) -#define LOG_RNB_MAX ((LOG_LO_USER) << 2) // Max logging (max verbosity) -#define LOG_RNB_COMM ((LOG_LO_USER) << 3) // Log communications (RNBSocket) -#define LOG_RNB_REMOTE ((LOG_LO_USER) << 4) // Log remote (RNBRemote) -#define LOG_RNB_EVENTS \ - ((LOG_LO_USER) << 5) // Log events (PThreadEvents) -#define LOG_RNB_PROC ((LOG_LO_USER) << 6) // Log process state (Process thread) -#define LOG_RNB_PACKETS ((LOG_LO_USER) << 7) // Log gdb remote packets -#define LOG_RNB_ALL (~((LOG_LO_USER)-1)) -#define LOG_RNB_DEFAULT (LOG_RNB_ALL) - -extern RNBRemoteSP g_remoteSP; - -#endif // #ifndef __RNBDefs_h__ diff --git a/tools/debugserver/source/RNBRemote.cpp b/tools/debugserver/source/RNBRemote.cpp deleted file mode 100644 index f611ec0d2199..000000000000 --- a/tools/debugserver/source/RNBRemote.cpp +++ /dev/null @@ -1,6256 +0,0 @@ -//===-- RNBRemote.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#include "RNBRemote.h" - -#include <errno.h> -#include <mach-o/loader.h> -#include <mach/exception_types.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <unistd.h> - -#if defined(__APPLE__) -#include <pthread.h> -#include <sched.h> -#endif - -#include "DNB.h" -#include "DNBDataRef.h" -#include "DNBLog.h" -#include "DNBThreadResumeActions.h" -#include "DarwinLogCollector.h" -#include "DarwinLogEvent.h" -#include "JSON.h" -#include "JSONGenerator.h" -#include "JSONGenerator.h" -#include "MacOSX/Genealogy.h" -#include "OsLogger.h" -#include "RNBContext.h" -#include "RNBServices.h" -#include "RNBSocket.h" -#include "StdStringExtractor.h" - -#include <compression.h> - -#include <TargetConditionals.h> -#include <iomanip> -#include <sstream> -#include <unordered_set> - -//---------------------------------------------------------------------- -// constants -//---------------------------------------------------------------------- - -static const std::string OS_LOG_EVENTS_KEY_NAME("events"); -static const std::string JSON_ASYNC_TYPE_KEY_NAME("type"); -static const DarwinLogEventVector::size_type DARWIN_LOG_MAX_EVENTS_PER_PACKET = - 10; - -//---------------------------------------------------------------------- -// std::iostream formatting macros -//---------------------------------------------------------------------- -#define RAW_HEXBASE std::setfill('0') << std::hex << std::right -#define HEXBASE '0' << 'x' << RAW_HEXBASE -#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x)) -#define RAWHEX16 RAW_HEXBASE << std::setw(4) -#define RAWHEX32 RAW_HEXBASE << std::setw(8) -#define RAWHEX64 RAW_HEXBASE << std::setw(16) -#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x)) -#define HEX16 HEXBASE << std::setw(4) -#define HEX32 HEXBASE << std::setw(8) -#define HEX64 HEXBASE << std::setw(16) -#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x) * 2) << (x) -#define HEX(x) HEXBASE << std::setw(sizeof(x) * 2) << (x) -#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x) -#define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x) -#define STRING_WIDTH(w) std::setfill(' ') << std::setw(w) -#define LEFT_STRING_WIDTH(s, w) \ - std::left << std::setfill(' ') << std::setw(w) << (s) << std::right -#define DECIMAL std::dec << std::setfill(' ') -#define DECIMAL_WIDTH(w) DECIMAL << std::setw(w) -#define FLOAT(n, d) \ - std::setfill(' ') << std::setw((n) + (d) + 1) << std::setprecision(d) \ - << std::showpoint << std::fixed -#define INDENT_WITH_SPACES(iword_idx) \ - std::setfill(' ') << std::setw((iword_idx)) << "" -#define INDENT_WITH_TABS(iword_idx) \ - std::setfill('\t') << std::setw((iword_idx)) << "" -// Class to handle communications via gdb remote protocol. - -//---------------------------------------------------------------------- -// Prototypes -//---------------------------------------------------------------------- - -static std::string binary_encode_string(const std::string &s); - -//---------------------------------------------------------------------- -// Decode a single hex character and return the hex value as a number or -// -1 if "ch" is not a hex character. -//---------------------------------------------------------------------- -static inline int xdigit_to_sint(char ch) { - if (ch >= 'a' && ch <= 'f') - return 10 + ch - 'a'; - if (ch >= 'A' && ch <= 'F') - return 10 + ch - 'A'; - if (ch >= '0' && ch <= '9') - return ch - '0'; - return -1; -} - -//---------------------------------------------------------------------- -// Decode a single hex ASCII byte. Return -1 on failure, a value 0-255 -// on success. -//---------------------------------------------------------------------- -static inline int decoded_hex_ascii_char(const char *p) { - const int hi_nibble = xdigit_to_sint(p[0]); - if (hi_nibble == -1) - return -1; - const int lo_nibble = xdigit_to_sint(p[1]); - if (lo_nibble == -1) - return -1; - return (uint8_t)((hi_nibble << 4) + lo_nibble); -} - -//---------------------------------------------------------------------- -// Decode a hex ASCII string back into a string -//---------------------------------------------------------------------- -static std::string decode_hex_ascii_string(const char *p, - uint32_t max_length = UINT32_MAX) { - std::string arg; - if (p) { - for (const char *c = p; ((c - p) / 2) < max_length; c += 2) { - int ch = decoded_hex_ascii_char(c); - if (ch == -1) - break; - else - arg.push_back(ch); - } - } - return arg; -} - -uint64_t decode_uint64(const char *p, int base, char **end = nullptr, - uint64_t fail_value = 0) { - nub_addr_t addr = strtoull(p, end, 16); - if (addr == 0 && errno != 0) - return fail_value; - return addr; -} - -extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, - va_list args); - -#if defined(__APPLE__) && \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) -// from System.framework/Versions/B/PrivateHeaders/sys/codesign.h -extern "C" { -#define CS_OPS_STATUS 0 /* return status */ -#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ -int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize); - -// from rootless.h -bool rootless_allows_task_for_pid(pid_t pid); - -// from sys/csr.h -typedef uint32_t csr_config_t; -#define CSR_ALLOW_TASK_FOR_PID (1 << 2) -int csr_check(csr_config_t mask); -} -#endif - -RNBRemote::RNBRemote() - : m_ctx(), m_comm(), m_arch(), m_continue_thread(-1), m_thread(-1), - m_mutex(), m_dispatch_queue_offsets(), - m_dispatch_queue_offsets_addr(INVALID_NUB_ADDRESS), - m_qSymbol_index(UINT32_MAX), m_packets_recvd(0), m_packets(), - m_rx_packets(), m_rx_partial_data(), m_rx_pthread(0), - m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), - m_extended_mode(false), m_noack_mode(false), - m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false), - m_compression_minsize(384), m_enable_compression_next_send_packet(false), - m_compression_mode(compression_types::none) { - DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); - CreatePacketTable(); -} - -RNBRemote::~RNBRemote() { - DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); - StopReadRemoteDataThread(); -} - -void RNBRemote::CreatePacketTable() { - // Step required to add new packets: - // 1 - Add new enumeration to RNBRemote::PacketEnum - // 2 - Create the RNBRemote::HandlePacket_ function if a new function is - // needed - // 3 - Register the Packet definition with any needed callbacks in this - // function - // - If no response is needed for a command, then use NULL for the - // normal callback - // - If the packet is not supported while the target is running, use - // NULL for the async callback - // 4 - If the packet is a standard packet (starts with a '$' character - // followed by the payload and then '#' and checksum, then you are done - // else go on to step 5 - // 5 - if the packet is a fixed length packet: - // - modify the switch statement for the first character in the payload - // in RNBRemote::CommDataReceived so it doesn't reject the new packet - // type as invalid - // - modify the switch statement for the first character in the payload - // in RNBRemote::GetPacketPayload and make sure the payload of the - // packet - // is returned correctly - - std::vector<Packet> &t = m_packets; - t.push_back(Packet(ack, NULL, NULL, "+", "ACK")); - t.push_back(Packet(nack, NULL, NULL, "-", "!ACK")); - t.push_back(Packet(read_memory, &RNBRemote::HandlePacket_m, NULL, "m", - "Read memory")); - t.push_back(Packet(read_register, &RNBRemote::HandlePacket_p, NULL, "p", - "Read one register")); - t.push_back(Packet(read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g", - "Read registers")); - t.push_back(Packet(write_memory, &RNBRemote::HandlePacket_M, NULL, "M", - "Write memory")); - t.push_back(Packet(write_register, &RNBRemote::HandlePacket_P, NULL, "P", - "Write one register")); - t.push_back(Packet(write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G", - "Write registers")); - t.push_back(Packet(insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0", - "Insert memory breakpoint")); - t.push_back(Packet(remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0", - "Remove memory breakpoint")); - t.push_back(Packet(single_step, &RNBRemote::HandlePacket_s, NULL, "s", - "Single step")); - t.push_back(Packet(cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue")); - t.push_back(Packet(single_step_with_sig, &RNBRemote::HandlePacket_S, NULL, - "S", "Single step with signal")); - t.push_back( - Packet(set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread")); - t.push_back(Packet(halt, &RNBRemote::HandlePacket_last_signal, - &RNBRemote::HandlePacket_stop_process, "\x03", "^C")); - // t.push_back (Packet (use_extended_mode, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode")); - t.push_back(Packet(why_halted, &RNBRemote::HandlePacket_last_signal, NULL, - "?", "Why did target halt")); - t.push_back( - Packet(set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv")); - // t.push_back (Packet (set_bp, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear - // breakpoint")); - t.push_back(Packet(continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C", - "Continue with signal")); - t.push_back(Packet(detach, &RNBRemote::HandlePacket_D, NULL, "D", - "Detach gdb from remote system")); - // t.push_back (Packet (step_inferior_one_cycle, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one - // clock cycle")); - // t.push_back (Packet (signal_and_step_inf_one_cycle, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then - // step one clock cycle")); - t.push_back(Packet(kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill")); - // t.push_back (Packet (restart, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior")); - // t.push_back (Packet (search_mem_backwards, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory - // backwards")); - t.push_back(Packet(thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", - "Is thread alive")); - t.push_back(Packet(query_supported_features, - &RNBRemote::HandlePacket_qSupported, NULL, "qSupported", - "Query about supported features")); - t.push_back(Packet(vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", - "Attach to a new process")); - t.push_back(Packet(vattachwait, &RNBRemote::HandlePacket_v, NULL, - "vAttachWait", - "Wait for a process to start up then attach to it")); - t.push_back(Packet(vattachorwait, &RNBRemote::HandlePacket_v, NULL, - "vAttachOrWait", "Attach to the process or if it doesn't " - "exist, wait for the process to start up " - "then attach to it")); - t.push_back(Packet(vattachname, &RNBRemote::HandlePacket_v, NULL, - "vAttachName", "Attach to an existing process by name")); - t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, - "vCont;", "Verbose resume with thread actions")); - t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, - "vCont?", - "List valid continue-with-thread-actions actions")); - t.push_back(Packet(read_data_from_memory, &RNBRemote::HandlePacket_x, NULL, - "x", "Read data from memory")); - t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL, - "X", "Write data to memory")); - // t.push_back (Packet (insert_hardware_bp, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware - // breakpoint")); - // t.push_back (Packet (remove_hardware_bp, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware - // breakpoint")); - t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "Z2", "Insert write watchpoint")); - t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "z2", "Remove write watchpoint")); - t.push_back(Packet(insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "Z3", "Insert read watchpoint")); - t.push_back(Packet(remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "z3", "Remove read watchpoint")); - t.push_back(Packet(insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "Z4", "Insert access watchpoint")); - t.push_back(Packet(remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, - "z4", "Remove access watchpoint")); - t.push_back(Packet(query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL, - "qRcmd", "Monitor command")); - t.push_back(Packet(query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL, - "qC", "Query current thread ID")); - t.push_back(Packet(query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:", - "Echo the packet back to allow the debugger to sync up " - "with this server")); - t.push_back(Packet(query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL, - "qGetPid", "Query process id")); - t.push_back(Packet(query_thread_ids_first, - &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo", - "Get list of active threads (first req)")); - t.push_back(Packet(query_thread_ids_subsequent, - &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo", - "Get list of active threads (subsequent req)")); - // APPLE LOCAL: qThreadStopInfo - // syntax: qThreadStopInfoTTTT - // TTTT is hex thread ID - t.push_back(Packet(query_thread_stop_info, - &RNBRemote::HandlePacket_qThreadStopInfo, NULL, - "qThreadStopInfo", - "Get detailed info on why the specified thread stopped")); - t.push_back(Packet(query_thread_extra_info, - &RNBRemote::HandlePacket_qThreadExtraInfo, NULL, - "qThreadExtraInfo", "Get printable status of a thread")); - // t.push_back (Packet (query_image_offsets, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset - // of loaded program")); - t.push_back(Packet( - query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess, NULL, - "qLaunchSuccess", "Report the success or failure of the launch attempt")); - t.push_back( - Packet(query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, - "qRegisterInfo", - "Dynamically discover remote register context information.")); - t.push_back(Packet( - query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr, - NULL, "qShlibInfoAddr", "Returns the address that contains info needed " - "for getting shared library notifications")); - t.push_back(Packet(query_step_packet_supported, - &RNBRemote::HandlePacket_qStepPacketSupported, NULL, - "qStepPacketSupported", - "Replys with OK if the 's' packet is supported.")); - t.push_back( - Packet(query_vattachorwait_supported, - &RNBRemote::HandlePacket_qVAttachOrWaitSupported, NULL, - "qVAttachOrWaitSupported", - "Replys with OK if the 'vAttachOrWait' packet is supported.")); - t.push_back( - Packet(query_sync_thread_state_supported, - &RNBRemote::HandlePacket_qSyncThreadStateSupported, NULL, - "qSyncThreadStateSupported", - "Replys with OK if the 'QSyncThreadState:' packet is supported.")); - t.push_back(Packet( - query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", - "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back(Packet( - query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion, - NULL, "qGDBServerVersion", - "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back(Packet( - query_process_info, &RNBRemote::HandlePacket_qProcessInfo, NULL, - "qProcessInfo", - "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back(Packet( - query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol, NULL, "qSymbol:", - "Notify that host debugger is ready to do symbol lookups")); - t.push_back(Packet(json_query_thread_extended_info, - &RNBRemote::HandlePacket_jThreadExtendedInfo, NULL, - "jThreadExtendedInfo", - "Replies with JSON data of thread extended information.")); - t.push_back(Packet(json_query_get_loaded_dynamic_libraries_infos, - &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos, - NULL, "jGetLoadedDynamicLibrariesInfos", - "Replies with JSON data of all the shared libraries " - "loaded in this process.")); - t.push_back( - Packet(json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo, - NULL, "jThreadsInfo", - "Replies with JSON data with information about all threads.")); - t.push_back(Packet(json_query_get_shared_cache_info, - &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL, - "jGetSharedCacheInfo", "Replies with JSON data about the " - "location and uuid of the shared " - "cache in the inferior process.")); - t.push_back(Packet(start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode, - NULL, "QStartNoAckMode", - "Request that " DEBUGSERVER_PROGRAM_NAME - " stop acking remote protocol packets")); - t.push_back(Packet(prefix_reg_packets_with_tid, - &RNBRemote::HandlePacket_QThreadSuffixSupported, NULL, - "QThreadSuffixSupported", - "Check if thread specific packets (register packets 'g', " - "'G', 'p', and 'P') support having the thread ID appended " - "to the end of the command")); - t.push_back(Packet(set_logging_mode, &RNBRemote::HandlePacket_QSetLogging, - NULL, "QSetLogging:", "Check if register packets ('g', " - "'G', 'p', and 'P' support having " - "the thread ID prefix")); - t.push_back(Packet( - set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize, NULL, - "QSetMaxPacketSize:", - "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle")); - t.push_back(Packet( - set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize, NULL, - "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME - " the max sized payload gdb can handle")); - t.push_back( - Packet(set_environment_variable, &RNBRemote::HandlePacket_QEnvironment, - NULL, "QEnvironment:", - "Add an environment variable to the inferior's environment")); - t.push_back( - Packet(set_environment_variable_hex, - &RNBRemote::HandlePacket_QEnvironmentHexEncoded, NULL, - "QEnvironmentHexEncoded:", - "Add an environment variable to the inferior's environment")); - t.push_back(Packet(set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch, - NULL, "QLaunchArch:", "Set the architecture to use when " - "launching a process for hosts that " - "can run multiple architecture " - "slices from universal files.")); - t.push_back(Packet(set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR, - NULL, "QSetDisableASLR:", - "Set whether to disable ASLR when launching the process " - "with the set argv ('A') packet")); - t.push_back(Packet(set_stdin, &RNBRemote::HandlePacket_QSetSTDIO, NULL, - "QSetSTDIN:", "Set the standard input for a process to be " - "launched with the 'A' packet")); - t.push_back(Packet(set_stdout, &RNBRemote::HandlePacket_QSetSTDIO, NULL, - "QSetSTDOUT:", "Set the standard output for a process to " - "be launched with the 'A' packet")); - t.push_back(Packet(set_stderr, &RNBRemote::HandlePacket_QSetSTDIO, NULL, - "QSetSTDERR:", "Set the standard error for a process to " - "be launched with the 'A' packet")); - t.push_back(Packet(set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir, - NULL, "QSetWorkingDir:", "Set the working directory for a " - "process to be launched with the " - "'A' packet")); - t.push_back(Packet(set_list_threads_in_stop_reply, - &RNBRemote::HandlePacket_QListThreadsInStopReply, NULL, - "QListThreadsInStopReply", - "Set if the 'threads' key should be added to the stop " - "reply packets with a list of all thread IDs.")); - t.push_back(Packet( - sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState, NULL, - "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is " - "in a safe state to call functions on.")); - // t.push_back (Packet (pass_signals_to_inferior, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify - // which signals are passed to the inferior")); - t.push_back(Packet(allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, - NULL, "_M", "Allocate memory in the inferior process.")); - t.push_back(Packet(deallocate_memory, - &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", - "Deallocate memory in the inferior process.")); - t.push_back(Packet( - save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL, - "QSaveRegisterState", "Save the register state for the current thread " - "and return a decimal save ID.")); - t.push_back(Packet(restore_register_state, - &RNBRemote::HandlePacket_RestoreRegisterState, NULL, - "QRestoreRegisterState:", - "Restore the register state given a save ID previously " - "returned from a call to QSaveRegisterState.")); - t.push_back(Packet( - memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, - "qMemoryRegionInfo", "Return size and attributes of a memory region that " - "contains the given address")); - t.push_back(Packet(get_profile_data, &RNBRemote::HandlePacket_GetProfileData, - NULL, "qGetProfileData", - "Return profiling data of the current target.")); - t.push_back(Packet(set_enable_profiling, - &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, - "QSetEnableAsyncProfiling", - "Enable or disable the profiling of current target.")); - t.push_back(Packet(enable_compression, - &RNBRemote::HandlePacket_QEnableCompression, NULL, - "QEnableCompression:", - "Enable compression for the remainder of the connection")); - t.push_back(Packet(watchpoint_support_info, - &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, - "qWatchpointSupportInfo", - "Return the number of supported hardware watchpoints")); - t.push_back(Packet(set_process_event, - &RNBRemote::HandlePacket_QSetProcessEvent, NULL, - "QSetProcessEvent:", "Set a process event, to be passed " - "to the process, can be set before " - "the process is started, or after.")); - t.push_back( - Packet(set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, - NULL, "QSetDetachOnError:", - "Set whether debugserver will detach (1) or kill (0) from the " - "process it is controlling if it loses connection to lldb.")); - t.push_back(Packet( - speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", - "Test the maximum speed at which packet can be sent/received.")); - t.push_back(Packet(query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, - "qXfer:", "Support the qXfer packet.")); - t.push_back( - Packet(query_supported_async_json_packets, - &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL, - "qStructuredDataPlugins", - "Query for the structured data plugins supported by the remote.")); - t.push_back( - Packet(configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog, - NULL, "QConfigureDarwinLog:", - "Configure the DarwinLog structured data plugin support.")); -} - -void RNBRemote::FlushSTDIO() { - if (m_ctx.HasValidProcessID()) { - nub_process_t pid = m_ctx.ProcessID(); - char buf[256]; - nub_size_t count; - do { - count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf)); - if (count > 0) { - SendSTDOUTPacket(buf, count); - } - } while (count > 0); - - do { - count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf)); - if (count > 0) { - SendSTDERRPacket(buf, count); - } - } while (count > 0); - } -} - -void RNBRemote::SendAsyncProfileData() { - if (m_ctx.HasValidProcessID()) { - nub_process_t pid = m_ctx.ProcessID(); - char buf[1024]; - nub_size_t count; - do { - count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf)); - if (count > 0) { - SendAsyncProfileDataPacket(buf, count); - } - } while (count > 0); - } -} - -void RNBRemote::SendAsyncDarwinLogData() { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter", __FUNCTION__); - - if (!m_ctx.HasValidProcessID()) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to" - "invalid process id", - __FUNCTION__); - return; - } - - nub_process_t pid = m_ctx.ProcessID(); - DarwinLogEventVector::size_type entry_count = 0; - - // NOTE: the current looping structure here does nothing - // to guarantee that we can send off async packets faster - // than we generate them. It will keep sending as long - // as there's data to send. - do { - DarwinLogEventVector events = DNBProcessGetAvailableDarwinLogEvents(pid); - entry_count = events.size(); - - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter", - __FUNCTION__); - - for (DarwinLogEventVector::size_type base_entry = 0; - base_entry < entry_count; - base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter", - __FUNCTION__); - - // We limit the total number of entries we pack - // into a single JSON async packet just so it - // doesn't get too large. - JSONGenerator::Dictionary async_dictionary; - - // Specify the type of the JSON async data we're sending. - async_dictionary.AddStringItem(JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog"); - - // Create an array entry in the dictionary to hold all - // the events going in this packet. - JSONGenerator::ArraySP events_array(new JSONGenerator::Array()); - async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array); - - // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in - // a single packet. - const auto inner_loop_bound = - std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET, entry_count); - for (DarwinLogEventVector::size_type i = base_entry; i < inner_loop_bound; - ++i) { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding " - "entry index %lu to the JSON packet", - __FUNCTION__, i); - events_array->AddItem(events[i]); - } - - // Send off the packet. - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON " - "packet, %lu entries remain", - __FUNCTION__, entry_count - inner_loop_bound); - SendAsyncJSONPacket(async_dictionary); - } - - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit", - __FUNCTION__); - - } while (entry_count > 0); - - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit", - __PRETTY_FUNCTION__); -} - -rnb_err_t RNBRemote::SendHexEncodedBytePacket(const char *header, - const void *buf, size_t buf_len, - const char *footer) { - std::ostringstream packet_sstrm; - // Append the header cstr if there was one - if (header && header[0]) - packet_sstrm << header; - nub_size_t i; - const uint8_t *ubuf8 = (const uint8_t *)buf; - for (i = 0; i < buf_len; i++) { - packet_sstrm << RAWHEX8(ubuf8[i]); - } - // Append the footer cstr if there was one - if (footer && footer[0]) - packet_sstrm << footer; - - return SendPacket(packet_sstrm.str()); -} - -rnb_err_t RNBRemote::SendSTDOUTPacket(char *buf, nub_size_t buf_size) { - if (buf_size == 0) - return rnb_success; - return SendHexEncodedBytePacket("O", buf, buf_size, NULL); -} - -rnb_err_t RNBRemote::SendSTDERRPacket(char *buf, nub_size_t buf_size) { - if (buf_size == 0) - return rnb_success; - return SendHexEncodedBytePacket("O", buf, buf_size, NULL); -} - -// This makes use of asynchronous bit 'A' in the gdb remote protocol. -rnb_err_t RNBRemote::SendAsyncProfileDataPacket(char *buf, - nub_size_t buf_size) { - if (buf_size == 0) - return rnb_success; - - std::string packet("A"); - packet.append(buf, buf_size); - return SendPacket(packet); -} - -rnb_err_t -RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary) { - std::ostringstream stream; - // We're choosing something that is easy to spot if we somehow get one - // of these coming out at the wrong time (i.e. when the remote side - // is not waiting for a process control completion response). - stream << "JSON-async:"; - dictionary.Dump(stream); - const std::string payload = binary_encode_string(stream.str()); - return SendPacket(payload); -} - -// Given a std::string packet contents to send, possibly encode/compress it. -// If compression is enabled, the returned std::string will be in one of two -// forms: -// -// N<original packet contents uncompressed> -// C<size of original decompressed packet>:<packet compressed with the -// requested compression scheme> -// -// If compression is not requested, the original packet contents are returned - -std::string RNBRemote::CompressString(const std::string &orig) { - std::string compressed; - compression_types compression_type = GetCompressionType(); - if (compression_type != compression_types::none) { - bool compress_this_packet = false; - - if (orig.size() > m_compression_minsize) { - compress_this_packet = true; - } - - if (compress_this_packet) { - const size_t encoded_data_buf_size = orig.size() + 128; - std::vector<uint8_t> encoded_data(encoded_data_buf_size); - size_t compressed_size = 0; - - // Allocate a scratch buffer for libcompression the first - // time we see a different compression type; reuse it in - // all compression_encode_buffer calls so it doesn't need - // to allocate / free its own scratch buffer each time. - // This buffer will only be freed when compression type - // changes; otherwise it will persist until debugserver - // exit. - - static compression_types g_libcompress_scratchbuf_type = compression_types::none; - static void *g_libcompress_scratchbuf = nullptr; - - if (g_libcompress_scratchbuf_type != compression_type) { - if (g_libcompress_scratchbuf) { - free (g_libcompress_scratchbuf); - g_libcompress_scratchbuf = nullptr; - } - size_t scratchbuf_size = 0; - switch (compression_type) { - case compression_types::lz4: - scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZ4_RAW); - break; - case compression_types::zlib_deflate: - scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_ZLIB); - break; - case compression_types::lzma: - scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZMA); - break; - case compression_types::lzfse: - scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZFSE); - break; - default: - break; - } - if (scratchbuf_size > 0) { - g_libcompress_scratchbuf = (void*) malloc (scratchbuf_size); - g_libcompress_scratchbuf_type = compression_type; - } - } - - if (compression_type == compression_types::lz4) { - compressed_size = compression_encode_buffer( - encoded_data.data(), encoded_data_buf_size, - (const uint8_t *)orig.c_str(), orig.size(), - g_libcompress_scratchbuf, - COMPRESSION_LZ4_RAW); - } - if (compression_type == compression_types::zlib_deflate) { - compressed_size = compression_encode_buffer( - encoded_data.data(), encoded_data_buf_size, - (const uint8_t *)orig.c_str(), orig.size(), - g_libcompress_scratchbuf, - COMPRESSION_ZLIB); - } - if (compression_type == compression_types::lzma) { - compressed_size = compression_encode_buffer( - encoded_data.data(), encoded_data_buf_size, - (const uint8_t *)orig.c_str(), orig.size(), - g_libcompress_scratchbuf, - COMPRESSION_LZMA); - } - if (compression_type == compression_types::lzfse) { - compressed_size = compression_encode_buffer( - encoded_data.data(), encoded_data_buf_size, - (const uint8_t *)orig.c_str(), orig.size(), - g_libcompress_scratchbuf, - COMPRESSION_LZFSE); - } - - if (compressed_size > 0) { - compressed.clear(); - compressed.reserve(compressed_size); - compressed = "C"; - char numbuf[16]; - snprintf(numbuf, sizeof(numbuf), "%zu:", orig.size()); - numbuf[sizeof(numbuf) - 1] = '\0'; - compressed.append(numbuf); - - for (size_t i = 0; i < compressed_size; i++) { - uint8_t byte = encoded_data[i]; - if (byte == '#' || byte == '$' || byte == '}' || byte == '*' || - byte == '\0') { - compressed.push_back(0x7d); - compressed.push_back(byte ^ 0x20); - } else { - compressed.push_back(byte); - } - } - } else { - compressed = "N" + orig; - } - } else { - compressed = "N" + orig; - } - } else { - compressed = orig; - } - - return compressed; -} - -rnb_err_t RNBRemote::SendPacket(const std::string &s) { - DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, s.c_str()); - - std::string s_compressed = CompressString(s); - - std::string sendpacket = "$" + s_compressed + "#"; - int cksum = 0; - char hexbuf[5]; - - if (m_noack_mode) { - sendpacket += "00"; - } else { - for (size_t i = 0; i != s_compressed.size(); ++i) - cksum += s_compressed[i]; - snprintf(hexbuf, sizeof hexbuf, "%02x", cksum & 0xff); - sendpacket += hexbuf; - } - - rnb_err_t err = m_comm.Write(sendpacket.c_str(), sendpacket.size()); - if (err != rnb_success) - return err; - - if (m_noack_mode) - return rnb_success; - - std::string reply; - RNBRemote::Packet packet; - err = GetPacket(reply, packet, true); - - if (err != rnb_success) { - DNBLogThreadedIf(LOG_RNB_REMOTE, - "%8d RNBRemote::%s (%s) got error trying to get reply...", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, sendpacket.c_str()); - return err; - } - - DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, sendpacket.c_str(), reply.c_str()); - - if (packet.type == ack) - return rnb_success; - - // Should we try to resend the packet at this layer? - // if (packet.command == nack) - return rnb_err; -} - -/* Get a packet via gdb remote protocol. - Strip off the prefix/suffix, verify the checksum to make sure - a valid packet was received, send an ACK if they match. */ - -rnb_err_t RNBRemote::GetPacketPayload(std::string &return_packet) { - // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - - PThreadMutex::Locker locker(m_mutex); - if (m_rx_packets.empty()) { - // Only reset the remote command available event if we have no more packets - m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available); - // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets - // available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - // __FUNCTION__); - return rnb_err; - } - - // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, - // m_rx_packets.size()); - return_packet.swap(m_rx_packets.front()); - m_rx_packets.pop_front(); - locker.Reset(); // Release our lock on the mutex - - if (m_rx_packets.empty()) { - // Reset the remote command available event if we have no more packets - m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available); - } - - // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, - // return_packet.c_str()); - - switch (return_packet[0]) { - case '+': - case '-': - case '\x03': - break; - - case '$': { - long packet_checksum = 0; - if (!m_noack_mode) { - for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i) { - char checksum_char = tolower(return_packet[i]); - if (!isxdigit(checksum_char)) { - m_comm.Write("-", 1); - DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet " - "with invalid checksum characters: " - "%s", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, return_packet.c_str()); - return rnb_err; - } - } - packet_checksum = - strtol(&return_packet[return_packet.size() - 2], NULL, 16); - } - - return_packet.erase(0, 1); // Strip the leading '$' - return_packet.erase(return_packet.size() - 3); // Strip the #XX checksum - - if (!m_noack_mode) { - // Compute the checksum - int computed_checksum = 0; - for (std::string::iterator it = return_packet.begin(); - it != return_packet.end(); ++it) { - computed_checksum += *it; - } - - if (packet_checksum == (computed_checksum & 0xff)) { - // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for - // '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - // __FUNCTION__, return_packet.c_str()); - m_comm.Write("+", 1); - } else { - DNBLogThreadedIf( - LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: " - "packet checksum mismatch (0x%2.2lx != 0x%2.2x))", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, - return_packet.c_str(), packet_checksum, computed_checksum); - m_comm.Write("-", 1); - return rnb_err; - } - } - } break; - - default: - DNBLogThreadedIf(LOG_RNB_REMOTE, - "%8u RNBRemote::%s tossing unexpected packet???? %s", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, return_packet.c_str()); - if (!m_noack_mode) - m_comm.Write("-", 1); - return rnb_err; - } - - return rnb_success; -} - -rnb_err_t RNBRemote::HandlePacket_UNIMPLEMENTED(const char *p) { - DNBLogThreadedIf(LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, p ? p : "NULL"); - return SendPacket(""); -} - -rnb_err_t RNBRemote::HandlePacket_ILLFORMED(const char *file, int line, - const char *p, - const char *description) { - DNBLogThreadedIf(LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, - line, __FUNCTION__, p); - return SendPacket("E03"); -} - -rnb_err_t RNBRemote::GetPacket(std::string &packet_payload, - RNBRemote::Packet &packet_info, bool wait) { - std::string payload; - rnb_err_t err = GetPacketPayload(payload); - if (err != rnb_success) { - PThreadEvent &events = m_ctx.Events(); - nub_event_t set_events = events.GetEventBits(); - // TODO: add timeout version of GetPacket?? We would then need to pass - // that timeout value along to DNBProcessTimedWaitForEvent. - if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0)) - return err; - - const nub_event_t events_to_wait_for = - RNBContext::event_read_packet_available | - RNBContext::event_read_thread_exiting; - - while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0) { - if (set_events & RNBContext::event_read_packet_available) { - // Try the queue again now that we got an event - err = GetPacketPayload(payload); - if (err == rnb_success) - break; - } - - if (set_events & RNBContext::event_read_thread_exiting) - err = rnb_not_connected; - - if (err == rnb_not_connected) - return err; - } - while (err == rnb_err) - ; - - if (set_events == 0) - err = rnb_not_connected; - } - - if (err == rnb_success) { - Packet::iterator it; - for (it = m_packets.begin(); it != m_packets.end(); ++it) { - if (payload.compare(0, it->abbrev.size(), it->abbrev) == 0) - break; - } - - // A packet we don't have an entry for. This can happen when we - // get a packet that we don't know about or support. We just reply - // accordingly and go on. - if (it == m_packets.end()) { - DNBLogThreadedIf(LOG_RNB_PACKETS, "unimplemented packet: '%s'", - payload.c_str()); - HandlePacket_UNIMPLEMENTED(payload.c_str()); - return rnb_err; - } else { - packet_info = *it; - packet_payload = payload; - } - } - return err; -} - -rnb_err_t RNBRemote::HandleAsyncPacket(PacketEnum *type) { - DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__); - static DNBTimer g_packetTimer(true); - rnb_err_t err = rnb_err; - std::string packet_data; - RNBRemote::Packet packet_info; - err = GetPacket(packet_data, packet_info, false); - - if (err == rnb_success) { - if (!packet_data.empty() && isprint(packet_data[0])) - DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS, - "HandleAsyncPacket (\"%s\");", packet_data.c_str()); - else - DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS, - "HandleAsyncPacket (%s);", - packet_info.printable_name.c_str()); - - HandlePacketCallback packet_callback = packet_info.async; - if (packet_callback != NULL) { - if (type != NULL) - *type = packet_info.type; - return (this->*packet_callback)(packet_data.c_str()); - } - } - - return err; -} - -rnb_err_t RNBRemote::HandleReceivedPacket(PacketEnum *type) { - static DNBTimer g_packetTimer(true); - - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - rnb_err_t err = rnb_err; - std::string packet_data; - RNBRemote::Packet packet_info; - err = GetPacket(packet_data, packet_info, false); - - if (err == rnb_success) { - DNBLogThreadedIf(LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", - packet_data.c_str()); - HandlePacketCallback packet_callback = packet_info.normal; - if (packet_callback != NULL) { - if (type != NULL) - *type = packet_info.type; - return (this->*packet_callback)(packet_data.c_str()); - } else { - // Do not fall through to end of this function, if we have valid - // packet_info and it has a NULL callback, then we need to respect - // that it may not want any response or anything to be done. - return err; - } - } - return rnb_err; -} - -void RNBRemote::CommDataReceived(const std::string &new_data) { - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - { - // Put the packet data into the buffer in a thread safe fashion - PThreadMutex::Locker locker(m_mutex); - - std::string data; - // See if we have any left over data from a previous call to this - // function? - if (!m_rx_partial_data.empty()) { - // We do, so lets start with that data - data.swap(m_rx_partial_data); - } - // Append the new incoming data - data += new_data; - - // Parse up the packets into gdb remote packets - size_t idx = 0; - const size_t data_size = data.size(); - - while (idx < data_size) { - // end_idx must be one past the last valid packet byte. Start - // it off with an invalid value that is the same as the current - // index. - size_t end_idx = idx; - - switch (data[idx]) { - case '+': // Look for ack - case '-': // Look for cancel - case '\x03': // ^C to halt target - end_idx = idx + 1; // The command is one byte long... - break; - - case '$': - // Look for a standard gdb packet? - end_idx = data.find('#', idx + 1); - if (end_idx == std::string::npos || end_idx + 3 > data_size) { - end_idx = std::string::npos; - } else { - // Add two for the checksum bytes and 1 to point to the - // byte just past the end of this packet - end_idx += 3; - } - break; - - default: - break; - } - - if (end_idx == std::string::npos) { - // Not all data may be here for the packet yet, save it for - // next time through this function. - m_rx_partial_data += data.substr(idx); - // DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for - // later[%u, npos): - // '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - // __FUNCTION__, idx, m_rx_partial_data.c_str()); - idx = end_idx; - } else if (idx < end_idx) { - m_packets_recvd++; - // Hack to get rid of initial '+' ACK??? - if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+') { - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first - // ACK away....[%u, npos): - // '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - // __FUNCTION__, idx); - } else { - // We have a valid packet... - m_rx_packets.push_back(data.substr(idx, end_idx - idx)); - DNBLogThreadedIf(LOG_RNB_PACKETS, "getpkt: %s", - m_rx_packets.back().c_str()); - } - idx = end_idx; - } else { - DNBLogThreadedIf(LOG_RNB_MAX, - "%8d RNBRemote::%s tossing junk byte at %c", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, data[idx]); - idx = idx + 1; - } - } - } - - if (!m_rx_packets.empty()) { - // Let the main thread know we have received a packet - - // DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called - // events.SetEvent(RNBContext::event_read_packet_available)", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - PThreadEvent &events = m_ctx.Events(); - events.SetEvents(RNBContext::event_read_packet_available); - } -} - -rnb_err_t RNBRemote::GetCommData() { - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", - // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - std::string comm_data; - rnb_err_t err = m_comm.Read(comm_data); - if (err == rnb_success) { - if (!comm_data.empty()) - CommDataReceived(comm_data); - } - return err; -} - -void RNBRemote::StartReadRemoteDataThread() { - DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__); - PThreadEvent &events = m_ctx.Events(); - if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0) { - events.ResetEvents(RNBContext::event_read_thread_exiting); - int err = ::pthread_create(&m_rx_pthread, NULL, - ThreadFunctionReadRemoteData, this); - if (err == 0) { - // Our thread was successfully kicked off, wait for it to - // set the started event so we can safely continue - events.WaitForSetEvents(RNBContext::event_read_thread_running); - } else { - events.ResetEvents(RNBContext::event_read_thread_running); - events.SetEvents(RNBContext::event_read_thread_exiting); - } - } -} - -void RNBRemote::StopReadRemoteDataThread() { - DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__); - PThreadEvent &events = m_ctx.Events(); - if ((events.GetEventBits() & RNBContext::event_read_thread_running) == - RNBContext::event_read_thread_running) { - m_comm.Disconnect(true); - struct timespec timeout_abstime; - DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); - - // Wait for 2 seconds for the remote data thread to exit - if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, - &timeout_abstime) == 0) { - // Kill the remote data thread??? - } - } -} - -void *RNBRemote::ThreadFunctionReadRemoteData(void *arg) { - // Keep a shared pointer reference so this doesn't go away on us before the - // thread is killed. - DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", - __FUNCTION__, arg); - RNBRemoteSP remoteSP(g_remoteSP); - if (remoteSP.get() != NULL) { - -#if defined(__APPLE__) - pthread_setname_np("read gdb-remote packets thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } -#endif -#endif - - RNBRemote *remote = remoteSP.get(); - PThreadEvent &events = remote->Context().Events(); - events.SetEvents(RNBContext::event_read_thread_running); - // START: main receive remote command thread loop - bool done = false; - while (!done) { - rnb_err_t err = remote->GetCommData(); - - switch (err) { - case rnb_success: - break; - - case rnb_err: - DNBLogThreadedIf(LOG_RNB_REMOTE, - "RNBSocket::GetCommData returned error %u", err); - done = true; - break; - - case rnb_not_connected: - DNBLogThreadedIf(LOG_RNB_REMOTE, - "RNBSocket::GetCommData returned not connected..."); - done = true; - break; - } - } - // START: main receive remote command thread loop - events.ResetEvents(RNBContext::event_read_thread_running); - events.SetEvents(RNBContext::event_read_thread_exiting); - } - DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", - __FUNCTION__, arg); - return NULL; -} - -// If we fail to get back a valid CPU type for the remote process, -// make a best guess for the CPU type based on the currently running -// debugserver binary -- the debugger may not handle the case of an -// un-specified process CPU type correctly. - -static cpu_type_t best_guess_cpu_type() { -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - if (sizeof(char *) == 8) { - return CPU_TYPE_ARM64; - } else { - return CPU_TYPE_ARM; - } -#elif defined(__i386__) || defined(__x86_64__) - if (sizeof(char *) == 8) { - return CPU_TYPE_X86_64; - } else { - return CPU_TYPE_I386; - } -#endif - return 0; -} - -/* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes - (8-bit bytes). - This encoding uses 0x7d ('}') as an escape character for - 0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*'). - LEN is the number of bytes to be processed. If a character is escaped, - it is 2 characters for LEN. A LEN of -1 means decode-until-nul-byte - (end of string). */ - -std::vector<uint8_t> decode_binary_data(const char *str, size_t len) { - std::vector<uint8_t> bytes; - if (len == 0) { - return bytes; - } - if (len == (size_t)-1) - len = strlen(str); - - while (len--) { - unsigned char c = *str++; - if (c == 0x7d && len > 0) { - len--; - c = *str++ ^ 0x20; - } - bytes.push_back(c); - } - return bytes; -} - -// Quote any meta characters in a std::string as per the binary -// packet convention in the gdb-remote protocol. - -static std::string binary_encode_string(const std::string &s) { - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); - - for (size_t i = 0; i < s_size; i++) { - unsigned char ch = *(s_chars + i); - if (ch == '#' || ch == '$' || ch == '}' || ch == '*') { - output.push_back('}'); // 0x7d - output.push_back(ch ^ 0x20); - } else { - output.push_back(ch); - } - } - return output; -} - -// If the value side of a key-value pair in JSON is a string, -// and that string has a " character in it, the " character must -// be escaped. - -std::string json_string_quote_metachars(const std::string &s) { - if (s.find('"') == std::string::npos) - return s; - - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); - for (size_t i = 0; i < s_size; i++) { - unsigned char ch = *(s_chars + i); - if (ch == '"') { - output.push_back('\\'); - } - output.push_back(ch); - } - return output; -} - -typedef struct register_map_entry { - uint32_t debugserver_regnum; // debugserver register number - uint32_t offset; // Offset in bytes into the register context data with no - // padding between register values - DNBRegisterInfo nub_info; // debugnub register info - std::vector<uint32_t> value_regnums; - std::vector<uint32_t> invalidate_regnums; -} register_map_entry_t; - -// If the notion of registers differs from what is handed out by the -// architecture, then flavors can be defined here. - -static std::vector<register_map_entry_t> g_dynamic_register_map; -static register_map_entry_t *g_reg_entries = NULL; -static size_t g_num_reg_entries = 0; - -void RNBRemote::Initialize() { DNBInitialize(); } - -bool RNBRemote::InitializeRegisters(bool force) { - pid_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return false; - - DNBLogThreadedIf( - LOG_RNB_PROC, - "RNBRemote::%s() getting native registers from DNB interface", - __FUNCTION__); - // Discover the registers by querying the DNB interface and letting it - // state the registers that it would like to export. This allows the - // registers to be discovered using multiple qRegisterInfo calls to get - // all register information after the architecture for the process is - // determined. - if (force) { - g_dynamic_register_map.clear(); - g_reg_entries = NULL; - g_num_reg_entries = 0; - } - - if (g_dynamic_register_map.empty()) { - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets); - - assert(num_reg_sets > 0 && reg_sets != NULL); - - uint32_t regnum = 0; - uint32_t reg_data_offset = 0; - typedef std::map<std::string, uint32_t> NameToRegNum; - NameToRegNum name_to_regnum; - for (nub_size_t set = 0; set < num_reg_sets; ++set) { - if (reg_sets[set].registers == NULL) - continue; - - for (uint32_t reg = 0; reg < reg_sets[set].num_registers; ++reg) { - register_map_entry_t reg_entry = { - regnum++, // register number starts at zero and goes up with no gaps - reg_data_offset, // Offset into register context data, no gaps - // between registers - reg_sets[set].registers[reg], // DNBRegisterInfo - {}, - {}, - }; - - name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum; - - if (reg_entry.nub_info.value_regs == NULL) { - reg_data_offset += reg_entry.nub_info.size; - } - - g_dynamic_register_map.push_back(reg_entry); - } - } - - // Now we must find any registers whose values are in other registers and - // fix up - // the offsets since we removed all gaps... - for (auto ®_entry : g_dynamic_register_map) { - if (reg_entry.nub_info.value_regs) { - uint32_t new_offset = UINT32_MAX; - for (size_t i = 0; reg_entry.nub_info.value_regs[i] != NULL; ++i) { - const char *name = reg_entry.nub_info.value_regs[i]; - auto pos = name_to_regnum.find(name); - if (pos != name_to_regnum.end()) { - regnum = pos->second; - reg_entry.value_regnums.push_back(regnum); - if (regnum < g_dynamic_register_map.size()) { - // The offset for value_regs registers is the offset within the - // register with the lowest offset - const uint32_t reg_offset = - g_dynamic_register_map[regnum].offset + - reg_entry.nub_info.offset; - if (new_offset > reg_offset) - new_offset = reg_offset; - } - } - } - - if (new_offset != UINT32_MAX) { - reg_entry.offset = new_offset; - } else { - DNBLogThreaded("no offset was calculated entry for register %s", - reg_entry.nub_info.name); - reg_entry.offset = UINT32_MAX; - } - } - - if (reg_entry.nub_info.update_regs) { - for (size_t i = 0; reg_entry.nub_info.update_regs[i] != NULL; ++i) { - const char *name = reg_entry.nub_info.update_regs[i]; - auto pos = name_to_regnum.find(name); - if (pos != name_to_regnum.end()) { - regnum = pos->second; - reg_entry.invalidate_regnums.push_back(regnum); - } - } - } - } - - // for (auto ®_entry: g_dynamic_register_map) - // { - // DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s", - // reg_entry.offset, - // reg_entry.nub_info.size, - // reg_entry.nub_info.value_regs != NULL, - // reg_entry.nub_info.name); - // } - - g_reg_entries = g_dynamic_register_map.data(); - g_num_reg_entries = g_dynamic_register_map.size(); - } - return true; -} - -/* The inferior has stopped executing; send a packet - to gdb to let it know. */ - -void RNBRemote::NotifyThatProcessStopped(void) { - RNBRemote::HandlePacket_last_signal(NULL); - return; -} - -/* 'A arglen,argnum,arg,...' - Update the inferior context CTX with the program name and arg - list. - The documentation for this packet is underwhelming but my best reading - of this is that it is a series of (len, position #, arg)'s, one for - each argument with "arg" hex encoded (two 0-9a-f chars?). - Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either - is sufficient to get around the "," position separator escape issue. - - e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is - - 6,0,676462,4,1,2d71,10,2,612e6f7574 - - Note that "argnum" and "arglen" are numbers in base 10. Again, that's - not documented either way but I'm assuming it's so. */ - -rnb_err_t RNBRemote::HandlePacket_A(const char *p) { - if (p == NULL || *p == '\0') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Null packet for 'A' pkt"); - } - p++; - if (*p == '\0' || !isdigit(*p)) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "arglen not specified on 'A' pkt"); - } - - /* I promise I don't modify it anywhere in this function. strtoul()'s - 2nd arg has to be non-const which makes it problematic to step - through the string easily. */ - char *buf = const_cast<char *>(p); - - RNBContext &ctx = Context(); - - while (*buf != '\0') { - unsigned long arglen, argnum; - std::string arg; - char *c; - - errno = 0; - arglen = strtoul(buf, &c, 10); - if (errno != 0 && arglen == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "arglen not a number on 'A' pkt"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "arglen not followed by comma on 'A' pkt"); - } - buf = c + 1; - - errno = 0; - argnum = strtoul(buf, &c, 10); - if (errno != 0 && argnum == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "argnum not a number on 'A' pkt"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "arglen not followed by comma on 'A' pkt"); - } - buf = c + 1; - - c = buf; - buf = buf + arglen; - while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') { - char smallbuf[3]; - smallbuf[0] = *c; - smallbuf[1] = *(c + 1); - smallbuf[2] = '\0'; - - errno = 0; - int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "non-hex char in arg on 'A' pkt"); - } - - arg.push_back(ch); - c += 2; - } - - ctx.PushArgument(arg.c_str()); - if (*buf == ',') - buf++; - } - SendPacket("OK"); - - return rnb_success; -} - -/* 'H c t' - Set the thread for subsequent actions; 'c' for step/continue ops, - 'g' for other ops. -1 means all threads, 0 means any thread. */ - -rnb_err_t RNBRemote::HandlePacket_H(const char *p) { - p++; // skip 'H' - if (*p != 'c' && *p != 'g') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Missing 'c' or 'g' type in H packet"); - } - - if (!m_ctx.HasValidProcessID()) { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - } - - errno = 0; - nub_thread_t tid = strtoul(p + 1, NULL, 16); - if (errno != 0 && tid == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid thread number in H packet"); - } - if (*p == 'c') - SetContinueThread(tid); - if (*p == 'g') - SetCurrentThread(tid); - - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_qLaunchSuccess(const char *p) { - if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Status() == 0) - return SendPacket("OK"); - std::ostringstream ret_str; - std::string status_str; - ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); - - return SendPacket(ret_str.str()); -} - -rnb_err_t RNBRemote::HandlePacket_qShlibInfoAddr(const char *p) { - if (m_ctx.HasValidProcessID()) { - nub_addr_t shlib_info_addr = - DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID()); - if (shlib_info_addr != INVALID_NUB_ADDRESS) { - std::ostringstream ostrm; - ostrm << RAW_HEXBASE << shlib_info_addr; - return SendPacket(ostrm.str()); - } - } - return SendPacket("E44"); -} - -rnb_err_t RNBRemote::HandlePacket_qStepPacketSupported(const char *p) { - // Normally the "s" packet is mandatory, yet in gdb when using ARM, they - // get around the need for this packet by implementing software single - // stepping from gdb. Current versions of debugserver do support the "s" - // packet, yet some older versions do not. We need a way to tell if this - // packet is supported so we can disable software single stepping in gdb - // for remote targets (so the "s" packet will get used). - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_qSyncThreadStateSupported(const char *p) { - // We support attachOrWait meaning attach if the process exists, otherwise - // wait to attach. - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_qVAttachOrWaitSupported(const char *p) { - // We support attachOrWait meaning attach if the process exists, otherwise - // wait to attach. - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_qThreadStopInfo(const char *p) { - p += strlen("qThreadStopInfo"); - nub_thread_t tid = strtoul(p, 0, 16); - return SendStopReplyPacketForThread(tid); -} - -rnb_err_t RNBRemote::HandlePacket_qThreadInfo(const char *p) { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("OK"); - - // Only "qfThreadInfo" and "qsThreadInfo" get into this function so - // we only need to check the second byte to tell which is which - if (p[1] == 'f') { - nub_size_t numthreads = DNBProcessGetNumThreads(pid); - std::ostringstream ostrm; - ostrm << "m"; - bool first = true; - for (nub_size_t i = 0; i < numthreads; ++i) { - if (first) - first = false; - else - ostrm << ","; - nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i); - ostrm << std::hex << th; - } - return SendPacket(ostrm.str()); - } else { - return SendPacket("l"); - } -} - -rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("OK"); - - /* This is supposed to return a string like 'Runnable' or - 'Blocked on Mutex'. - The returned string is formatted like the "A" packet - a - sequence of letters encoded in as 2-hex-chars-per-letter. */ - p += strlen("qThreadExtraInfo"); - if (*p++ != ',') - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Illformed qThreadExtraInfo packet"); - errno = 0; - nub_thread_t tid = strtoul(p, NULL, 16); - if (errno != 0 && tid == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "Invalid thread number in qThreadExtraInfo packet"); - } - - const char *threadInfo = DNBThreadGetInfo(pid, tid); - if (threadInfo != NULL && threadInfo[0]) { - return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL); - } else { - // "OK" == 4f6b - // Return "OK" as a ASCII hex byte stream if things go wrong - return SendPacket("4f6b"); - } - - return SendPacket(""); -} - -const char *k_space_delimiters = " \t"; -static void skip_spaces(std::string &line) { - if (!line.empty()) { - size_t space_pos = line.find_first_not_of(k_space_delimiters); - if (space_pos > 0) - line.erase(0, space_pos); - } -} - -static std::string get_identifier(std::string &line) { - std::string word; - skip_spaces(line); - const size_t line_size = line.size(); - size_t end_pos; - for (end_pos = 0; end_pos < line_size; ++end_pos) { - if (end_pos == 0) { - if (isalpha(line[end_pos]) || line[end_pos] == '_') - continue; - } else if (isalnum(line[end_pos]) || line[end_pos] == '_') - continue; - break; - } - word.assign(line, 0, end_pos); - line.erase(0, end_pos); - return word; -} - -static std::string get_operator(std::string &line) { - std::string op; - skip_spaces(line); - if (!line.empty()) { - if (line[0] == '=') { - op = '='; - line.erase(0, 1); - } - } - return op; -} - -static std::string get_value(std::string &line) { - std::string value; - skip_spaces(line); - if (!line.empty()) { - value.swap(line); - } - return value; -} - -extern void FileLogCallback(void *baton, uint32_t flags, const char *format, - va_list args); -extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, - va_list args); - -rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) { - const char *c = p + strlen("qRcmd,"); - std::string line; - while (c[0] && c[1]) { - char smallbuf[3] = {c[0], c[1], '\0'}; - errno = 0; - int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "non-hex char in payload of qRcmd packet"); - line.push_back(ch); - c += 2; - } - if (*c == '\0') { - std::string command = get_identifier(line); - if (command == "set") { - std::string variable = get_identifier(line); - std::string op = get_operator(line); - std::string value = get_value(line); - if (variable == "logfile") { - FILE *log_file = fopen(value.c_str(), "w"); - if (log_file) { - DNBLogSetLogCallback(FileLogCallback, log_file); - return SendPacket("OK"); - } - return SendPacket("E71"); - } else if (variable == "logmask") { - char *end; - errno = 0; - uint32_t logmask = - static_cast<uint32_t>(strtoul(value.c_str(), &end, 0)); - if (errno == 0 && end && *end == '\0') { - DNBLogSetLogMask(logmask); - if (!DNBLogGetLogCallback()) - DNBLogSetLogCallback(ASLLogCallback, NULL); - return SendPacket("OK"); - } - errno = 0; - logmask = static_cast<uint32_t>(strtoul(value.c_str(), &end, 16)); - if (errno == 0 && end && *end == '\0') { - DNBLogSetLogMask(logmask); - return SendPacket("OK"); - } - return SendPacket("E72"); - } - return SendPacket("E70"); - } - return SendPacket("E69"); - } - return SendPacket("E73"); -} - -rnb_err_t RNBRemote::HandlePacket_qC(const char *p) { - nub_thread_t tid; - std::ostringstream rep; - // If we haven't run the process yet, we tell the debugger the - // pid is 0. That way it can know to tell use to run later on. - if (!m_ctx.HasValidProcessID()) - tid = 0; - else { - // Grab the current thread. - tid = DNBProcessGetCurrentThread(m_ctx.ProcessID()); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThread(tid); - } - rep << "QC" << std::hex << tid; - return SendPacket(rep.str()); -} - -rnb_err_t RNBRemote::HandlePacket_qEcho(const char *p) { - // Just send the exact same packet back that we received to - // synchronize the response packets after a previous packet - // timed out. This allows the debugger to get back on track - // with responses after a packet timeout. - return SendPacket(p); -} - -rnb_err_t RNBRemote::HandlePacket_qGetPid(const char *p) { - nub_process_t pid; - std::ostringstream rep; - // If we haven't run the process yet, we tell the debugger the - // pid is 0. That way it can know to tell use to run later on. - if (m_ctx.HasValidProcessID()) - pid = m_ctx.ProcessID(); - else - pid = 0; - rep << std::hex << pid; - return SendPacket(rep.str()); -} - -rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) { - if (g_num_reg_entries == 0) - InitializeRegisters(); - - p += strlen("qRegisterInfo"); - - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo(&num_reg_sets); - uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16)); - - if (reg_num < g_num_reg_entries) { - const register_map_entry_t *reg_entry = &g_reg_entries[reg_num]; - std::ostringstream ostrm; - if (reg_entry->nub_info.name) - ostrm << "name:" << reg_entry->nub_info.name << ';'; - if (reg_entry->nub_info.alt) - ostrm << "alt-name:" << reg_entry->nub_info.alt << ';'; - - ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';'; - ostrm << "offset:" << std::dec << reg_entry->offset << ';'; - - switch (reg_entry->nub_info.type) { - case Uint: - ostrm << "encoding:uint;"; - break; - case Sint: - ostrm << "encoding:sint;"; - break; - case IEEE754: - ostrm << "encoding:ieee754;"; - break; - case Vector: - ostrm << "encoding:vector;"; - break; - } - - switch (reg_entry->nub_info.format) { - case Binary: - ostrm << "format:binary;"; - break; - case Decimal: - ostrm << "format:decimal;"; - break; - case Hex: - ostrm << "format:hex;"; - break; - case Float: - ostrm << "format:float;"; - break; - case VectorOfSInt8: - ostrm << "format:vector-sint8;"; - break; - case VectorOfUInt8: - ostrm << "format:vector-uint8;"; - break; - case VectorOfSInt16: - ostrm << "format:vector-sint16;"; - break; - case VectorOfUInt16: - ostrm << "format:vector-uint16;"; - break; - case VectorOfSInt32: - ostrm << "format:vector-sint32;"; - break; - case VectorOfUInt32: - ostrm << "format:vector-uint32;"; - break; - case VectorOfFloat32: - ostrm << "format:vector-float32;"; - break; - case VectorOfUInt128: - ostrm << "format:vector-uint128;"; - break; - }; - - if (reg_set_info && reg_entry->nub_info.set < num_reg_sets) - ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';'; - - if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM) - ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';'; - - if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM) - ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';'; - - switch (reg_entry->nub_info.reg_generic) { - case GENERIC_REGNUM_FP: - ostrm << "generic:fp;"; - break; - case GENERIC_REGNUM_PC: - ostrm << "generic:pc;"; - break; - case GENERIC_REGNUM_SP: - ostrm << "generic:sp;"; - break; - case GENERIC_REGNUM_RA: - ostrm << "generic:ra;"; - break; - case GENERIC_REGNUM_FLAGS: - ostrm << "generic:flags;"; - break; - case GENERIC_REGNUM_ARG1: - ostrm << "generic:arg1;"; - break; - case GENERIC_REGNUM_ARG2: - ostrm << "generic:arg2;"; - break; - case GENERIC_REGNUM_ARG3: - ostrm << "generic:arg3;"; - break; - case GENERIC_REGNUM_ARG4: - ostrm << "generic:arg4;"; - break; - case GENERIC_REGNUM_ARG5: - ostrm << "generic:arg5;"; - break; - case GENERIC_REGNUM_ARG6: - ostrm << "generic:arg6;"; - break; - case GENERIC_REGNUM_ARG7: - ostrm << "generic:arg7;"; - break; - case GENERIC_REGNUM_ARG8: - ostrm << "generic:arg8;"; - break; - default: - break; - } - - if (!reg_entry->value_regnums.empty()) { - ostrm << "container-regs:"; - for (size_t i = 0, n = reg_entry->value_regnums.size(); i < n; ++i) { - if (i > 0) - ostrm << ','; - ostrm << RAW_HEXBASE << reg_entry->value_regnums[i]; - } - ostrm << ';'; - } - - if (!reg_entry->invalidate_regnums.empty()) { - ostrm << "invalidate-regs:"; - for (size_t i = 0, n = reg_entry->invalidate_regnums.size(); i < n; ++i) { - if (i > 0) - ostrm << ','; - ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i]; - } - ostrm << ';'; - } - - return SendPacket(ostrm.str()); - } - return SendPacket("E45"); -} - -/* This expects a packet formatted like - - QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE; - - with the "QSetLogging:" already removed from the start. Maybe in the - future this packet will include other keyvalue pairs like - - QSetLogging:bitmask=LOG_ALL;mode=asl; - */ - -rnb_err_t set_logging(const char *p) { - int bitmask = 0; - while (p && *p != '\0') { - if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) { - p += sizeof("bitmask=") - 1; - while (p && *p != '\0' && *p != ';') { - if (*p == '|') - p++; - - // to regenerate the LOG_ entries (not including the LOG_RNB entries) - // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v - // 'LOG_HI|LOG_LO' | awk '{print $2}'` - // do - // echo " else if (strncmp (p, \"$logname\", sizeof - // (\"$logname\") - 1) == 0)" - // echo " {" - // echo " p += sizeof (\"$logname\") - 1;" - // echo " bitmask |= $logname;" - // echo " }" - // done - if (strncmp(p, "LOG_VERBOSE", sizeof("LOG_VERBOSE") - 1) == 0) { - p += sizeof("LOG_VERBOSE") - 1; - bitmask |= LOG_VERBOSE; - } else if (strncmp(p, "LOG_PROCESS", sizeof("LOG_PROCESS") - 1) == 0) { - p += sizeof("LOG_PROCESS") - 1; - bitmask |= LOG_PROCESS; - } else if (strncmp(p, "LOG_THREAD", sizeof("LOG_THREAD") - 1) == 0) { - p += sizeof("LOG_THREAD") - 1; - bitmask |= LOG_THREAD; - } else if (strncmp(p, "LOG_EXCEPTIONS", sizeof("LOG_EXCEPTIONS") - 1) == - 0) { - p += sizeof("LOG_EXCEPTIONS") - 1; - bitmask |= LOG_EXCEPTIONS; - } else if (strncmp(p, "LOG_SHLIB", sizeof("LOG_SHLIB") - 1) == 0) { - p += sizeof("LOG_SHLIB") - 1; - bitmask |= LOG_SHLIB; - } else if (strncmp(p, "LOG_MEMORY", sizeof("LOG_MEMORY") - 1) == 0) { - p += sizeof("LOG_MEMORY") - 1; - bitmask |= LOG_MEMORY; - } else if (strncmp(p, "LOG_MEMORY_DATA_SHORT", - sizeof("LOG_MEMORY_DATA_SHORT") - 1) == 0) { - p += sizeof("LOG_MEMORY_DATA_SHORT") - 1; - bitmask |= LOG_MEMORY_DATA_SHORT; - } else if (strncmp(p, "LOG_MEMORY_DATA_LONG", - sizeof("LOG_MEMORY_DATA_LONG") - 1) == 0) { - p += sizeof("LOG_MEMORY_DATA_LONG") - 1; - bitmask |= LOG_MEMORY_DATA_LONG; - } else if (strncmp(p, "LOG_MEMORY_PROTECTIONS", - sizeof("LOG_MEMORY_PROTECTIONS") - 1) == 0) { - p += sizeof("LOG_MEMORY_PROTECTIONS") - 1; - bitmask |= LOG_MEMORY_PROTECTIONS; - } else if (strncmp(p, "LOG_BREAKPOINTS", - sizeof("LOG_BREAKPOINTS") - 1) == 0) { - p += sizeof("LOG_BREAKPOINTS") - 1; - bitmask |= LOG_BREAKPOINTS; - } else if (strncmp(p, "LOG_EVENTS", sizeof("LOG_EVENTS") - 1) == 0) { - p += sizeof("LOG_EVENTS") - 1; - bitmask |= LOG_EVENTS; - } else if (strncmp(p, "LOG_WATCHPOINTS", - sizeof("LOG_WATCHPOINTS") - 1) == 0) { - p += sizeof("LOG_WATCHPOINTS") - 1; - bitmask |= LOG_WATCHPOINTS; - } else if (strncmp(p, "LOG_STEP", sizeof("LOG_STEP") - 1) == 0) { - p += sizeof("LOG_STEP") - 1; - bitmask |= LOG_STEP; - } else if (strncmp(p, "LOG_TASK", sizeof("LOG_TASK") - 1) == 0) { - p += sizeof("LOG_TASK") - 1; - bitmask |= LOG_TASK; - } else if (strncmp(p, "LOG_ALL", sizeof("LOG_ALL") - 1) == 0) { - p += sizeof("LOG_ALL") - 1; - bitmask |= LOG_ALL; - } else if (strncmp(p, "LOG_DEFAULT", sizeof("LOG_DEFAULT") - 1) == 0) { - p += sizeof("LOG_DEFAULT") - 1; - bitmask |= LOG_DEFAULT; - } - // end of auto-generated entries - - else if (strncmp(p, "LOG_NONE", sizeof("LOG_NONE") - 1) == 0) { - p += sizeof("LOG_NONE") - 1; - bitmask = 0; - } else if (strncmp(p, "LOG_RNB_MINIMAL", - sizeof("LOG_RNB_MINIMAL") - 1) == 0) { - p += sizeof("LOG_RNB_MINIMAL") - 1; - bitmask |= LOG_RNB_MINIMAL; - } else if (strncmp(p, "LOG_RNB_MEDIUM", sizeof("LOG_RNB_MEDIUM") - 1) == - 0) { - p += sizeof("LOG_RNB_MEDIUM") - 1; - bitmask |= LOG_RNB_MEDIUM; - } else if (strncmp(p, "LOG_RNB_MAX", sizeof("LOG_RNB_MAX") - 1) == 0) { - p += sizeof("LOG_RNB_MAX") - 1; - bitmask |= LOG_RNB_MAX; - } else if (strncmp(p, "LOG_RNB_COMM", sizeof("LOG_RNB_COMM") - 1) == - 0) { - p += sizeof("LOG_RNB_COMM") - 1; - bitmask |= LOG_RNB_COMM; - } else if (strncmp(p, "LOG_RNB_REMOTE", sizeof("LOG_RNB_REMOTE") - 1) == - 0) { - p += sizeof("LOG_RNB_REMOTE") - 1; - bitmask |= LOG_RNB_REMOTE; - } else if (strncmp(p, "LOG_RNB_EVENTS", sizeof("LOG_RNB_EVENTS") - 1) == - 0) { - p += sizeof("LOG_RNB_EVENTS") - 1; - bitmask |= LOG_RNB_EVENTS; - } else if (strncmp(p, "LOG_RNB_PROC", sizeof("LOG_RNB_PROC") - 1) == - 0) { - p += sizeof("LOG_RNB_PROC") - 1; - bitmask |= LOG_RNB_PROC; - } else if (strncmp(p, "LOG_RNB_PACKETS", - sizeof("LOG_RNB_PACKETS") - 1) == 0) { - p += sizeof("LOG_RNB_PACKETS") - 1; - bitmask |= LOG_RNB_PACKETS; - } else if (strncmp(p, "LOG_RNB_ALL", sizeof("LOG_RNB_ALL") - 1) == 0) { - p += sizeof("LOG_RNB_ALL") - 1; - bitmask |= LOG_RNB_ALL; - } else if (strncmp(p, "LOG_RNB_DEFAULT", - sizeof("LOG_RNB_DEFAULT") - 1) == 0) { - p += sizeof("LOG_RNB_DEFAULT") - 1; - bitmask |= LOG_RNB_DEFAULT; - } else if (strncmp(p, "LOG_DARWIN_LOG", sizeof("LOG_DARWIN_LOG") - 1) == - 0) { - p += sizeof("LOG_DARWIN_LOG") - 1; - bitmask |= LOG_DARWIN_LOG; - } else if (strncmp(p, "LOG_RNB_NONE", sizeof("LOG_RNB_NONE") - 1) == - 0) { - p += sizeof("LOG_RNB_NONE") - 1; - bitmask = 0; - } else { - /* Unrecognized logging bit; ignore it. */ - const char *c = strchr(p, '|'); - if (c) { - p = c; - } else { - c = strchr(p, ';'); - if (c) { - p = c; - } else { - // Improperly terminated word; just go to end of str - p = strchr(p, '\0'); - } - } - } - } - // Did we get a properly formatted logging bitmask? - if (p && *p == ';') { - // Enable DNB logging. - // Use the existing log callback if one was already configured. - if (!DNBLogGetLogCallback()) { - // Use the os_log()-based logger if available; otherwise, - // fallback to ASL. - auto log_callback = OsLogger::GetLogFunction(); - if (log_callback) - DNBLogSetLogCallback(log_callback, nullptr); - else - DNBLogSetLogCallback(ASLLogCallback, nullptr); - } - - // Update logging to use the configured log channel bitmask. - DNBLogSetLogMask(bitmask); - p++; - } - } -// We're not going to support logging to a file for now. All logging -// goes through ASL or the previously arranged log callback. -#if 0 - else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0) - { - p += sizeof ("mode=") - 1; - if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0) - { - DNBLogToASL (); - p += sizeof ("asl;") - 1; - } - else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0) - { - DNBLogToFile (); - p += sizeof ("file;") - 1; - } - else - { - // Ignore unknown argument - const char *c = strchr (p, ';'); - if (c) - p = c + 1; - else - p = strchr (p, '\0'); - } - } - else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0) - { - p += sizeof ("filename=") - 1; - const char *c = strchr (p, ';'); - if (c == NULL) - { - c = strchr (p, '\0'); - continue; - } - char *fn = (char *) alloca (c - p + 1); - strlcpy (fn, p, c - p); - fn[c - p] = '\0'; - - // A file name of "asl" is special and is another way to indicate - // that logging should be done via ASL, not by file. - if (strcmp (fn, "asl") == 0) - { - DNBLogToASL (); - } - else - { - FILE *f = fopen (fn, "w"); - if (f) - { - DNBLogSetLogFile (f); - DNBEnableLogging (f, DNBLogGetLogMask ()); - DNBLogToFile (); - } - } - p = c + 1; - } -#endif /* #if 0 to enforce ASL logging only. */ - else { - // Ignore unknown argument - const char *c = strchr(p, ';'); - if (c) - p = c + 1; - else - p = strchr(p, '\0'); - } - } - - return rnb_success; -} - -rnb_err_t RNBRemote::HandlePacket_QThreadSuffixSupported(const char *p) { - m_thread_suffix_supported = true; - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QStartNoAckMode(const char *p) { - // Send the OK packet first so the correct checksum is appended... - rnb_err_t result = SendPacket("OK"); - m_noack_mode = true; - return result; -} - -rnb_err_t RNBRemote::HandlePacket_QSetLogging(const char *p) { - p += sizeof("QSetLogging:") - 1; - rnb_err_t result = set_logging(p); - if (result == rnb_success) - return SendPacket("OK"); - else - return SendPacket("E35"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetDisableASLR(const char *p) { - extern int g_disable_aslr; - p += sizeof("QSetDisableASLR:") - 1; - switch (*p) { - case '0': - g_disable_aslr = 0; - break; - case '1': - g_disable_aslr = 1; - break; - default: - return SendPacket("E56"); - } - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetSTDIO(const char *p) { - // Only set stdin/out/err if we don't already have a process - if (!m_ctx.HasValidProcessID()) { - bool success = false; - // Check the seventh character since the packet will be one of: - // QSetSTDIN - // QSetSTDOUT - // QSetSTDERR - StdStringExtractor packet(p); - packet.SetFilePos(7); - char ch = packet.GetChar(); - while (packet.GetChar() != ':') - /* Do nothing. */; - - switch (ch) { - case 'I': // STDIN - packet.GetHexByteString(m_ctx.GetSTDIN()); - success = !m_ctx.GetSTDIN().empty(); - break; - - case 'O': // STDOUT - packet.GetHexByteString(m_ctx.GetSTDOUT()); - success = !m_ctx.GetSTDOUT().empty(); - break; - - case 'E': // STDERR - packet.GetHexByteString(m_ctx.GetSTDERR()); - success = !m_ctx.GetSTDERR().empty(); - break; - - default: - break; - } - if (success) - return SendPacket("OK"); - return SendPacket("E57"); - } - return SendPacket("E58"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetWorkingDir(const char *p) { - // Only set the working directory if we don't already have a process - if (!m_ctx.HasValidProcessID()) { - StdStringExtractor packet(p += sizeof("QSetWorkingDir:") - 1); - if (packet.GetHexByteString(m_ctx.GetWorkingDir())) { - struct stat working_dir_stat; - if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) { - m_ctx.GetWorkingDir().clear(); - return SendPacket("E61"); // Working directory doesn't exist... - } else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) { - return SendPacket("OK"); - } else { - m_ctx.GetWorkingDir().clear(); - return SendPacket("E62"); // Working directory isn't a directory... - } - } - return SendPacket("E59"); // Invalid path - } - return SendPacket( - "E60"); // Already had a process, too late to set working dir -} - -rnb_err_t RNBRemote::HandlePacket_QSyncThreadState(const char *p) { - if (!m_ctx.HasValidProcessID()) { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - return SendPacket("OK"); - } - - errno = 0; - p += strlen("QSyncThreadState:"); - nub_thread_t tid = strtoul(p, NULL, 16); - if (errno != 0 && tid == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "Invalid thread number in QSyncThreadState packet"); - } - if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid)) - return SendPacket("OK"); - else - return SendPacket("E61"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetDetachOnError(const char *p) { - p += sizeof("QSetDetachOnError:") - 1; - bool should_detach = true; - switch (*p) { - case '0': - should_detach = false; - break; - case '1': - should_detach = true; - break; - default: - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "Invalid value for QSetDetachOnError - should be 0 or 1"); - break; - } - - m_ctx.SetDetachOnError(should_detach); - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) { - // We'll return a JSON array of supported packet types. - // The type is significant. For each of the supported - // packet types that have been enabled, there will be a - // 'J' async packet sent to the client with payload data. - // This payload data will be a JSON dictionary, and the - // top level dictionary will contain a string field with - // its value set to the relevant packet type from this list. - JSONGenerator::Array supported_json_packets; - - // Check for DarwinLog (libtrace os_log/activity support). - if (DarwinLogCollector::IsSupported()) - supported_json_packets.AddItem( - JSONGenerator::StringSP(new JSONGenerator::String("DarwinLog"))); - - // Send back the array. - std::ostringstream stream; - supported_json_packets.Dump(stream); - return SendPacket(stream.str()); -} - -rnb_err_t RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) { - if (!DarwinLogCollector::IsSupported()) { - // We should never have been given this request. - return SendPacket("E89"); - } - - // Ensure we have a process. We expect a separate configure request for - // each process launched/attached. - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E94"); - - // Get the configuration dictionary. - p += strlen("QConfigureDarwinLog:"); - - // The configuration dictionary is binary encoded. - std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1); - std::string unescaped_config_string((const char *)&unescaped_config_data[0], - unescaped_config_data.size()); - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"", - unescaped_config_string.c_str()); - auto configuration_sp = - JSONParser(unescaped_config_string.c_str()).ParseJSONValue(); - if (!configuration_sp) { - // Malformed request - we require configuration data - // indicating whether we're enabling or disabling. - return SendPacket("E90"); - } - - if (!JSONObject::classof(configuration_sp.get())) { - // Configuration data is not of the right type. - return SendPacket("E91"); - } - JSONObject &config_dict = *static_cast<JSONObject *>(configuration_sp.get()); - - // Check if we're enabling or disabling. - auto enabled_sp = config_dict.GetObject("enabled"); - if (!enabled_sp) { - // Missing required "enabled" field. - return SendPacket("E92"); - } - if (!JSONTrue::classof(enabled_sp.get()) && - !JSONFalse::classof(enabled_sp.get())) { - // Should be a boolean type, but wasn't. - return SendPacket("E93"); - } - const bool enabling = JSONTrue::classof(enabled_sp.get()); - - // TODO - handle other configuration parameters here. - - // Shut down any active activity stream for the process. - DarwinLogCollector::CancelStreamForProcess(pid); - - if (enabling) { - // Look up the procecess. - if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict)) - return SendPacket("E95"); - } - - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QListThreadsInStopReply(const char *p) { - // If this packet is received, it allows us to send an extra key/value - // pair in the stop reply packets where we will list all of the thread IDs - // separated by commas: - // - // "threads:10a,10b,10c;" - // - // This will get included in the stop reply packet as something like: - // - // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;" - // - // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and - // speed things up a bit. - // - // Send the OK packet first so the correct checksum is appended... - rnb_err_t result = SendPacket("OK"); - m_list_threads_in_stop_reply = true; - - return result; -} - -rnb_err_t RNBRemote::HandlePacket_QSetMaxPayloadSize(const char *p) { - /* The number of characters in a packet payload that gdb is - prepared to accept. The packet-start char, packet-end char, - 2 checksum chars and terminating null character are not included - in this size. */ - p += sizeof("QSetMaxPayloadSize:") - 1; - errno = 0; - uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16)); - if (errno != 0 && size == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet"); - } - m_max_payload_size = size; - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetMaxPacketSize(const char *p) { - /* This tells us the largest packet that gdb can handle. - i.e. the size of gdb's packet-reading buffer. - QSetMaxPayloadSize is preferred because it is less ambiguous. */ - p += sizeof("QSetMaxPacketSize:") - 1; - errno = 0; - uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16)); - if (errno != 0 && size == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in QSetMaxPacketSize packet"); - } - m_max_payload_size = size - 5; - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QEnvironment(const char *p) { - /* This sets the environment for the target program. The packet is of the - form: - - QEnvironment:VARIABLE=VALUE - - */ - - DNBLogThreadedIf( - LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); - - p += sizeof("QEnvironment:") - 1; - RNBContext &ctx = Context(); - - ctx.PushEnvironment(p); - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QEnvironmentHexEncoded(const char *p) { - /* This sets the environment for the target program. The packet is of the - form: - - QEnvironmentHexEncoded:VARIABLE=VALUE - - The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with - special - meaning in the remote protocol won't break it. - */ - - DNBLogThreadedIf(LOG_RNB_REMOTE, - "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, p); - - p += sizeof("QEnvironmentHexEncoded:") - 1; - - std::string arg; - const char *c; - c = p; - while (*c != '\0') { - if (*(c + 1) == '\0') { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); - } - char smallbuf[3]; - smallbuf[0] = *c; - smallbuf[1] = *(c + 1); - smallbuf[2] = '\0'; - errno = 0; - int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); - } - arg.push_back(ch); - c += 2; - } - - RNBContext &ctx = Context(); - if (arg.length() > 0) - ctx.PushEnvironment(arg.c_str()); - - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_QLaunchArch(const char *p) { - p += sizeof("QLaunchArch:") - 1; - if (DNBSetArchitecture(p)) - return SendPacket("OK"); - return SendPacket("E63"); -} - -rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) { - p += sizeof("QSetProcessEvent:") - 1; - // If the process is running, then send the event to the process, otherwise - // store it in the context. - if (Context().HasValidProcessID()) { - if (DNBProcessSendEvent(Context().ProcessID(), p)) - return SendPacket("OK"); - else - return SendPacket("E80"); - } else { - Context().PushProcessEvent(p); - } - return SendPacket("OK"); -} - -void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size, - bool swap) { - int i; - const uint8_t *p = (const uint8_t *)buf; - if (swap) { - for (i = static_cast<int>(buf_size) - 1; i >= 0; i--) - ostrm << RAWHEX8(p[i]); - } else { - for (size_t i = 0; i < buf_size; i++) - ostrm << RAWHEX8(p[i]); - } -} - -void append_hexified_string(std::ostream &ostrm, const std::string &string) { - size_t string_size = string.size(); - const char *string_buf = string.c_str(); - for (size_t i = 0; i < string_size; i++) { - ostrm << RAWHEX8(*(string_buf + i)); - } -} - -void register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid, - nub_thread_t tid, - const register_map_entry_t *reg, - const DNBRegisterValue *reg_value_ptr) { - if (reg != NULL) { - DNBRegisterValue reg_value; - if (reg_value_ptr == NULL) { - if (DNBThreadGetRegisterValueByID(pid, tid, reg->nub_info.set, - reg->nub_info.reg, ®_value)) - reg_value_ptr = ®_value; - } - - if (reg_value_ptr) { - append_hex_value(ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size, - false); - } else { - // If we fail to read a register value, check if it has a default - // fail value. If it does, return this instead in case some of - // the registers are not available on the current system. - if (reg->nub_info.size > 0) { - std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0'); - append_hex_value(ostrm, zeros.data(), zeros.size(), false); - } - } - } -} - -void debugserver_regnum_with_fixed_width_hex_register_value( - std::ostream &ostrm, nub_process_t pid, nub_thread_t tid, - const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr) { - // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX - // gdb register number, and VVVVVVVV is the correct number of hex bytes - // as ASCII for the register value. - if (reg != NULL) { - ostrm << RAWHEX8(reg->debugserver_regnum) << ':'; - register_value_in_hex_fixed_width(ostrm, pid, tid, reg, reg_value_ptr); - ostrm << ';'; - } -} - -void RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo( - nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t, - std::string &queue_name, uint64_t &queue_width, - uint64_t &queue_serialnum) const { - queue_name.clear(); - queue_width = 0; - queue_serialnum = 0; - - if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS && - dispatch_qaddr != 0) { - dispatch_queue_t = DNBProcessMemoryReadPointer(pid, dispatch_qaddr); - if (dispatch_queue_t) { - queue_width = DNBProcessMemoryReadInteger( - pid, dispatch_queue_t + dqo_width, dqo_width_size, 0); - queue_serialnum = DNBProcessMemoryReadInteger( - pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0); - - if (dqo_version >= 4) { - // libdispatch versions 4+, pointer to dispatch name is in the - // queue structure. - nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label; - nub_addr_t label_addr = - DNBProcessMemoryReadPointer(pid, pointer_to_label_address); - if (label_addr) - queue_name = DNBProcessMemoryReadCString(pid, label_addr); - } else { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - queue_name = DNBProcessMemoryReadCStringFixed( - pid, dispatch_queue_t + dqo_label, dqo_label_size); - } - } - } -} - -struct StackMemory { - uint8_t bytes[2 * sizeof(nub_addr_t)]; - nub_size_t length; -}; -typedef std::map<nub_addr_t, StackMemory> StackMemoryMap; - -static void ReadStackMemory(nub_process_t pid, nub_thread_t tid, - StackMemoryMap &stack_mmap, - uint32_t backtrace_limit = 256) { - DNBRegisterValue reg_value; - if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, - GENERIC_REGNUM_FP, ®_value)) { - uint32_t frame_count = 0; - uint64_t fp = 0; - if (reg_value.info.size == 4) - fp = reg_value.value.uint32; - else - fp = reg_value.value.uint64; - while (fp != 0) { - // Make sure we never recurse more than 256 times so we don't recurse too - // far or - // store up too much memory in the expedited cache - if (++frame_count > backtrace_limit) - break; - - const nub_size_t read_size = reg_value.info.size * 2; - StackMemory stack_memory; - stack_memory.length = read_size; - if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) != - read_size) - break; - // Make sure we don't try to put the same stack memory in more than once - if (stack_mmap.find(fp) != stack_mmap.end()) - break; - // Put the entry into the cache - stack_mmap[fp] = stack_memory; - // Dereference the frame pointer to get to the previous frame pointer - if (reg_value.info.size == 4) - fp = ((uint32_t *)stack_memory.bytes)[0]; - else - fp = ((uint64_t *)stack_memory.bytes)[0]; - } - } -} - -rnb_err_t RNBRemote::SendStopReplyPacketForThread(nub_thread_t tid) { - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E50"); - - struct DNBThreadStopInfo tid_stop_info; - - /* Fill the remaining space in this packet with as many registers - as we can stuff in there. */ - - if (DNBThreadGetStopReason(pid, tid, &tid_stop_info)) { - const bool did_exec = tid_stop_info.reason == eStopTypeExec; - if (did_exec) { - RNBRemote::InitializeRegisters(true); - - // Reset any symbols that need resetting when we exec - m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS; - m_dispatch_queue_offsets.Clear(); - } - - std::ostringstream ostrm; - // Output the T packet with the thread - ostrm << 'T'; - int signum = tid_stop_info.details.signal.signo; - DNBLogThreadedIf( - LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, - signum, tid_stop_info.details.exception.type); - - // Translate any mach exceptions to gdb versions, unless they are - // common exceptions like a breakpoint or a soft signal. - switch (tid_stop_info.details.exception.type) { - default: - signum = 0; - break; - case EXC_BREAKPOINT: - signum = SIGTRAP; - break; - case EXC_BAD_ACCESS: - signum = TARGET_EXC_BAD_ACCESS; - break; - case EXC_BAD_INSTRUCTION: - signum = TARGET_EXC_BAD_INSTRUCTION; - break; - case EXC_ARITHMETIC: - signum = TARGET_EXC_ARITHMETIC; - break; - case EXC_EMULATION: - signum = TARGET_EXC_EMULATION; - break; - case EXC_SOFTWARE: - if (tid_stop_info.details.exception.data_count == 2 && - tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL) - signum = static_cast<int>(tid_stop_info.details.exception.data[1]); - else - signum = TARGET_EXC_SOFTWARE; - break; - } - - ostrm << RAWHEX8(signum & 0xff); - - ostrm << std::hex << "thread:" << tid << ';'; - - const char *thread_name = DNBThreadGetName(pid, tid); - if (thread_name && thread_name[0]) { - size_t thread_name_len = strlen(thread_name); - - if (::strcspn(thread_name, "$#+-;:") == thread_name_len) - ostrm << std::hex << "name:" << thread_name << ';'; - else { - // the thread name contains special chars, send as hex bytes - ostrm << std::hex << "hexname:"; - const uint8_t *u_thread_name = (const uint8_t *)thread_name; - for (size_t i = 0; i < thread_name_len; i++) - ostrm << RAWHEX8(u_thread_name[i]); - ostrm << ';'; - } - } - - // If a 'QListThreadsInStopReply' was sent to enable this feature, we - // will send all thread IDs back in the "threads" key whose value is - // a list of hex thread IDs separated by commas: - // "threads:10a,10b,10c;" - // This will save the debugger from having to send a pair of qfThreadInfo - // and qsThreadInfo packets, but it also might take a lot of room in the - // stop reply packet, so it must be enabled only on systems where there - // are no limits on packet lengths. - if (m_list_threads_in_stop_reply) { - const nub_size_t numthreads = DNBProcessGetNumThreads(pid); - if (numthreads > 0) { - std::vector<uint64_t> pc_values; - ostrm << std::hex << "threads:"; - for (nub_size_t i = 0; i < numthreads; ++i) { - nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i); - if (i > 0) - ostrm << ','; - ostrm << std::hex << th; - DNBRegisterValue pc_regval; - if (DNBThreadGetRegisterValueByID(pid, th, REGISTER_SET_GENERIC, - GENERIC_REGNUM_PC, &pc_regval)) { - uint64_t pc = INVALID_NUB_ADDRESS; - if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) { - if (pc_regval.info.size == 4) { - pc = pc_regval.value.uint32; - } else if (pc_regval.info.size == 8) { - pc = pc_regval.value.uint64; - } - if (pc != INVALID_NUB_ADDRESS) { - pc_values.push_back(pc); - } - } - } - } - ostrm << ';'; - - // If we failed to get any of the thread pc values, the size of our - // vector will not - // be the same as the # of threads. Don't provide any expedited thread - // pc values in - // that case. This should not happen. - if (pc_values.size() == numthreads) { - ostrm << std::hex << "thread-pcs:"; - for (nub_size_t i = 0; i < numthreads; ++i) { - if (i > 0) - ostrm << ','; - ostrm << std::hex << pc_values[i]; - } - ostrm << ';'; - } - } - - // Include JSON info that describes the stop reason for any threads - // that actually have stop reasons. We use the new "jstopinfo" key - // whose values is hex ascii JSON that contains the thread IDs - // thread stop info only for threads that have stop reasons. Only send - // this if we have more than one thread otherwise this packet has all - // the info it needs. - if (numthreads > 1) { - const bool threads_with_valid_stop_info_only = true; - JSONGenerator::ObjectSP threads_info_sp = - GetJSONThreadsInfo(threads_with_valid_stop_info_only); - if (threads_info_sp) { - ostrm << std::hex << "jstopinfo:"; - std::ostringstream json_strm; - threads_info_sp->Dump(json_strm); - append_hexified_string(ostrm, json_strm.str()); - ostrm << ';'; - } - } - } - - if (g_num_reg_entries == 0) - InitializeRegisters(); - - if (g_reg_entries != NULL) { - DNBRegisterValue reg_value; - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) { - // Expedite all registers in the first register set that aren't - // contained in other registers - if (g_reg_entries[reg].nub_info.set == 1 && - g_reg_entries[reg].nub_info.value_regs == NULL) { - if (!DNBThreadGetRegisterValueByID( - pid, tid, g_reg_entries[reg].nub_info.set, - g_reg_entries[reg].nub_info.reg, ®_value)) - continue; - - debugserver_regnum_with_fixed_width_hex_register_value( - ostrm, pid, tid, &g_reg_entries[reg], ®_value); - } - } - } - - if (did_exec) { - ostrm << "reason:exec;"; - } else if (tid_stop_info.details.exception.type) { - ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type - << ';'; - ostrm << "mecount:" << std::hex - << tid_stop_info.details.exception.data_count << ';'; - for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count; - ++i) - ostrm << "medata:" << std::hex - << tid_stop_info.details.exception.data[i] << ';'; - } - - // Add expedited stack memory so stack backtracing doesn't need to read - // anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory(pid, tid, stack_mmap, 2); - if (!stack_mmap.empty()) { - for (const auto &stack_memory : stack_mmap) { - ostrm << "memory:" << HEXBASE << stack_memory.first << '='; - append_hex_value(ostrm, stack_memory.second.bytes, - stack_memory.second.length, false); - ostrm << ';'; - } - } - - return SendPacket(ostrm.str()); - } - return SendPacket("E51"); -} - -/* '?' - The stop reply packet - tell gdb what the status of the inferior is. - Often called the questionmark_packet. */ - -rnb_err_t RNBRemote::HandlePacket_last_signal(const char *unused) { - if (!m_ctx.HasValidProcessID()) { - // Inferior is not yet specified/running - return SendPacket("E02"); - } - - nub_process_t pid = m_ctx.ProcessID(); - nub_state_t pid_state = DNBProcessGetState(pid); - - switch (pid_state) { - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - return rnb_success; // Ignore - - case eStateSuspended: - case eStateStopped: - case eStateCrashed: { - nub_thread_t tid = DNBProcessGetCurrentThread(pid); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThread(tid); - - SendStopReplyPacketForThread(tid); - } break; - - case eStateInvalid: - case eStateUnloaded: - case eStateExited: { - char pid_exited_packet[16] = ""; - int pid_status = 0; - // Process exited with exit status - if (!DNBProcessGetExitStatus(pid, &pid_status)) - pid_status = 0; - - if (pid_status) { - if (WIFEXITED(pid_status)) - snprintf(pid_exited_packet, sizeof(pid_exited_packet), "W%02x", - WEXITSTATUS(pid_status)); - else if (WIFSIGNALED(pid_status)) - snprintf(pid_exited_packet, sizeof(pid_exited_packet), "X%02x", - WEXITSTATUS(pid_status)); - else if (WIFSTOPPED(pid_status)) - snprintf(pid_exited_packet, sizeof(pid_exited_packet), "S%02x", - WSTOPSIG(pid_status)); - } - - // If we have an empty exit packet, lets fill one in to be safe. - if (!pid_exited_packet[0]) { - strlcpy(pid_exited_packet, "W00", sizeof(pid_exited_packet) - 1); - pid_exited_packet[sizeof(pid_exited_packet) - 1] = '\0'; - } - - const char *exit_info = DNBProcessGetExitInfo(pid); - if (exit_info != NULL && *exit_info != '\0') { - std::ostringstream exit_packet; - exit_packet << pid_exited_packet; - exit_packet << ';'; - exit_packet << RAW_HEXBASE << "description"; - exit_packet << ':'; - for (size_t i = 0; exit_info[i] != '\0'; i++) - exit_packet << RAWHEX8(exit_info[i]); - exit_packet << ';'; - return SendPacket(exit_packet.str()); - } else - return SendPacket(pid_exited_packet); - } break; - } - return rnb_success; -} - -rnb_err_t RNBRemote::HandlePacket_M(const char *p) { - if (p == NULL || p[0] == '\0' || strlen(p) < 3) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short M packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull(p, &c, 16); - if (errno != 0 && addr == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid address in M packet"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma sep missing in M packet"); - } - - /* Advance 'p' to the length part of the packet. */ - p += (c - p) + 1; - - errno = 0; - unsigned long length = strtoul(p, &c, 16); - if (errno != 0 && length == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in M packet"); - } - if (length == 0) { - return SendPacket("OK"); - } - - if (*c != ':') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Missing colon in M packet"); - } - /* Advance 'p' to the data part of the packet. */ - p += (c - p) + 1; - - size_t datalen = strlen(p); - if (datalen & 0x1) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Uneven # of hex chars for data in M packet"); - } - if (datalen == 0) { - return SendPacket("OK"); - } - - uint8_t *buf = (uint8_t *)alloca(datalen / 2); - uint8_t *i = buf; - - while (*p != '\0' && *(p + 1) != '\0') { - char hexbuf[3]; - hexbuf[0] = *p; - hexbuf[1] = *(p + 1); - hexbuf[2] = '\0'; - errno = 0; - uint8_t byte = strtoul(hexbuf, NULL, 16); - if (errno != 0 && byte == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid hex byte in M packet"); - } - *i++ = byte; - p += 2; - } - - nub_size_t wrote = - DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, length, buf); - if (wrote != length) - return SendPacket("E09"); - else - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_m(const char *p) { - if (p == NULL || p[0] == '\0' || strlen(p) < 3) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short m packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull(p, &c, 16); - if (errno != 0 && addr == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid address in m packet"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma sep missing in m packet"); - } - - /* Advance 'p' to the length part of the packet. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul(p, NULL, 16); - if (errno != 0 && length == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in m packet"); - } - if (length == 0) { - return SendPacket(""); - } - - std::string buf(length, '\0'); - if (buf.empty()) { - return SendPacket("E78"); - } - nub_size_t bytes_read = - DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]); - if (bytes_read == 0) { - return SendPacket("E08"); - } - - // "The reply may contain fewer bytes than requested if the server was able - // to read only part of the region of memory." - length = bytes_read; - - std::ostringstream ostrm; - for (unsigned long i = 0; i < length; i++) - ostrm << RAWHEX8(buf[i]); - return SendPacket(ostrm.str()); -} - -// Read memory, sent it up as binary data. -// Usage: xADDR,LEN -// ADDR and LEN are both base 16. - -// Responds with 'OK' for zero-length request -// or -// -// DATA -// -// where DATA is the binary data payload. - -rnb_err_t RNBRemote::HandlePacket_x(const char *p) { - if (p == NULL || p[0] == '\0' || strlen(p) < 3) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull(p, &c, 16); - if (errno != 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid address in X packet"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma sep missing in X packet"); - } - - /* Advance 'p' to the number of bytes to be read. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul(p, NULL, 16); - if (errno != 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in x packet"); - } - - // zero length read means this is a test of whether that packet is implemented - // or not. - if (length == 0) { - return SendPacket("OK"); - } - - std::vector<uint8_t> buf(length); - - if (buf.capacity() != length) { - return SendPacket("E79"); - } - nub_size_t bytes_read = - DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]); - if (bytes_read == 0) { - return SendPacket("E80"); - } - - std::vector<uint8_t> buf_quoted; - buf_quoted.reserve(bytes_read + 30); - for (nub_size_t i = 0; i < bytes_read; i++) { - if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') { - buf_quoted.push_back(0x7d); - buf_quoted.push_back(buf[i] ^ 0x20); - } else { - buf_quoted.push_back(buf[i]); - } - } - length = buf_quoted.size(); - - std::ostringstream ostrm; - for (unsigned long i = 0; i < length; i++) - ostrm << buf_quoted[i]; - - return SendPacket(ostrm.str()); -} - -rnb_err_t RNBRemote::HandlePacket_X(const char *p) { - if (p == NULL || p[0] == '\0' || strlen(p) < 3) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull(p, &c, 16); - if (errno != 0 && addr == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid address in X packet"); - } - if (*c != ',') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma sep missing in X packet"); - } - - /* Advance 'p' to the length part of the packet. NB this is the length of the - packet - including any escaped chars. The data payload may be a little bit smaller - after - decoding. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul(p, NULL, 16); - if (errno != 0 && length == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in X packet"); - } - - // I think gdb sends a zero length write request to test whether this - // packet is accepted. - if (length == 0) { - return SendPacket("OK"); - } - - std::vector<uint8_t> data = decode_binary_data(c, -1); - std::vector<uint8_t>::const_iterator it; - uint8_t *buf = (uint8_t *)alloca(data.size()); - uint8_t *i = buf; - for (it = data.begin(); it != data.end(); ++it) { - *i++ = *it; - } - - nub_size_t wrote = - DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, data.size(), buf); - if (wrote != data.size()) - return SendPacket("E08"); - return SendPacket("OK"); -} - -/* 'g' -- read registers - Get the contents of the registers for the current thread, - send them to gdb. - Should the setting of the Hg packet determine which thread's registers - are returned? */ - -rnb_err_t RNBRemote::HandlePacket_g(const char *p) { - std::ostringstream ostrm; - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E11"); - } - - if (g_num_reg_entries == 0) - InitializeRegisters(); - - nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in p packet"); - - // Get the register context size first by calling with NULL buffer - nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); - if (reg_ctx_size) { - // Now allocate enough space for the entire register context - std::vector<uint8_t> reg_ctx; - reg_ctx.resize(reg_ctx_size); - // Now read the register context - reg_ctx_size = - DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size()); - if (reg_ctx_size) { - append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false); - return SendPacket(ostrm.str()); - } - } - return SendPacket("E74"); -} - -/* 'G XXX...' -- write registers - How is the thread for these specified, beyond "the current thread"? - Does gdb actually use the Hg packet to set this? */ - -rnb_err_t RNBRemote::HandlePacket_G(const char *p) { - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E11"); - } - - if (g_num_reg_entries == 0) - InitializeRegisters(); - - StdStringExtractor packet(p); - packet.SetFilePos(1); // Skip the 'G' - - nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in p packet"); - - // Get the register context size first by calling with NULL buffer - nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); - if (reg_ctx_size) { - // Now allocate enough space for the entire register context - std::vector<uint8_t> reg_ctx; - reg_ctx.resize(reg_ctx_size); - - const nub_size_t bytes_extracted = - packet.GetHexBytes(®_ctx[0], reg_ctx.size(), 0xcc); - if (bytes_extracted == reg_ctx.size()) { - // Now write the register context - reg_ctx_size = - DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size()); - if (reg_ctx_size == reg_ctx.size()) - return SendPacket("OK"); - else - return SendPacket("E55"); - } else { - DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu " - "bytes, size mismatch\n", - p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size); - return SendPacket("E64"); - } - } - return SendPacket("E65"); -} - -static bool RNBRemoteShouldCancelCallback(void *not_used) { - RNBRemoteSP remoteSP(g_remoteSP); - if (remoteSP.get() != NULL) { - RNBRemote *remote = remoteSP.get(); - return !remote->Comm().IsConnected(); - } - return true; -} - -// FORMAT: _MXXXXXX,PPP -// XXXXXX: big endian hex chars -// PPP: permissions can be any combo of r w x chars -// -// RESPONSE: XXXXXX -// XXXXXX: hex address of the newly allocated memory -// EXX: error code -// -// EXAMPLES: -// _M123000,rw -// _M123000,rwx -// _M123000,xw - -rnb_err_t RNBRemote::HandlePacket_AllocateMemory(const char *p) { - StdStringExtractor packet(p); - packet.SetFilePos(2); // Skip the "_M" - - nub_addr_t size = packet.GetHexMaxU64(StdStringExtractor::BigEndian, 0); - if (size != 0) { - if (packet.GetChar() == ',') { - uint32_t permissions = 0; - char ch; - bool success = true; - while (success && (ch = packet.GetChar()) != '\0') { - switch (ch) { - case 'r': - permissions |= eMemoryPermissionsReadable; - break; - case 'w': - permissions |= eMemoryPermissionsWritable; - break; - case 'x': - permissions |= eMemoryPermissionsExecutable; - break; - default: - success = false; - break; - } - } - - if (success) { - nub_addr_t addr = - DNBProcessMemoryAllocate(m_ctx.ProcessID(), size, permissions); - if (addr != INVALID_NUB_ADDRESS) { - std::ostringstream ostrm; - ostrm << RAW_HEXBASE << addr; - return SendPacket(ostrm.str()); - } - } - } - } - return SendPacket("E53"); -} - -// FORMAT: _mXXXXXX -// XXXXXX: address that was previously allocated -// -// RESPONSE: XXXXXX -// OK: address was deallocated -// EXX: error code -// -// EXAMPLES: -// _m123000 - -rnb_err_t RNBRemote::HandlePacket_DeallocateMemory(const char *p) { - StdStringExtractor packet(p); - packet.SetFilePos(2); // Skip the "_m" - nub_addr_t addr = - packet.GetHexMaxU64(StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS); - - if (addr != INVALID_NUB_ADDRESS) { - if (DNBProcessMemoryDeallocate(m_ctx.ProcessID(), addr)) - return SendPacket("OK"); - } - return SendPacket("E54"); -} - -// FORMAT: QSaveRegisterState;thread:TTTT; (when thread suffix is supported) -// FORMAT: QSaveRegisterState (when thread suffix is NOT -// supported) -// TTTT: thread ID in hex -// -// RESPONSE: -// SAVEID: Where SAVEID is a decimal number that represents the save ID -// that can be passed back into a "QRestoreRegisterState" packet -// EXX: error code -// -// EXAMPLES: -// QSaveRegisterState;thread:1E34; (when thread suffix is supported) -// QSaveRegisterState (when thread suffix is NOT -// supported) - -rnb_err_t RNBRemote::HandlePacket_SaveRegisterState(const char *p) { - nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); - if (tid == INVALID_NUB_THREAD) { - if (m_thread_suffix_supported) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "No thread specified in QSaveRegisterState packet"); - else - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread was is set with the Hg packet"); - } - - // Get the register context size first by calling with NULL buffer - const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid); - if (save_id != 0) { - char response[64]; - snprintf(response, sizeof(response), "%u", save_id); - return SendPacket(response); - } else { - return SendPacket("E75"); - } -} -// FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT; (when thread suffix is -// supported) -// FORMAT: QRestoreRegisterState:SAVEID (when thread suffix is NOT -// supported) -// TTTT: thread ID in hex -// SAVEID: a decimal number that represents the save ID that was -// returned from a call to "QSaveRegisterState" -// -// RESPONSE: -// OK: successfully restored registers for the specified thread -// EXX: error code -// -// EXAMPLES: -// QRestoreRegisterState:1;thread:1E34; (when thread suffix is -// supported) -// QRestoreRegisterState:1 (when thread suffix is NOT -// supported) - -rnb_err_t RNBRemote::HandlePacket_RestoreRegisterState(const char *p) { - nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); - if (tid == INVALID_NUB_THREAD) { - if (m_thread_suffix_supported) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "No thread specified in QSaveRegisterState packet"); - else - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread was is set with the Hg packet"); - } - - StdStringExtractor packet(p); - packet.SetFilePos( - strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:" - const uint32_t save_id = packet.GetU32(0); - - if (save_id != 0) { - // Get the register context size first by calling with NULL buffer - if (DNBThreadRestoreRegisterState(pid, tid, save_id)) - return SendPacket("OK"); - else - return SendPacket("E77"); - } - return SendPacket("E76"); -} - -static bool GetProcessNameFrom_vAttach(const char *&p, - std::string &attach_name) { - bool return_val = true; - while (*p != '\0') { - char smallbuf[3]; - smallbuf[0] = *p; - smallbuf[1] = *(p + 1); - smallbuf[2] = '\0'; - - errno = 0; - int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) { - return_val = false; - break; - } - - attach_name.push_back(ch); - p += 2; - } - return return_val; -} - -rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) { - uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet - // size--debugger can always use less - char buf[256]; - snprintf(buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+", - max_packet_size); - - bool enable_compression = false; - (void)enable_compression; - -#if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) \ - || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) \ - || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1) \ - || (defined (TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1) - enable_compression = true; -#endif - - if (enable_compression) { - strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;" - "DefaultCompressionMinSize="); - char numbuf[16]; - snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize); - numbuf[sizeof(numbuf) - 1] = '\0'; - strcat(buf, numbuf); - } - - return SendPacket(buf); -} - -/* - vAttach;pid - - Attach to a new process with the specified process ID. pid is a hexadecimal - integer - identifying the process. If the stub is currently controlling a process, it is - killed. The attached process is stopped.This packet is only available in - extended - mode (see extended mode). - - Reply: - "ENN" for an error - "Any Stop Reply Packet" for success - */ - -rnb_err_t RNBRemote::HandlePacket_v(const char *p) { - if (strcmp(p, "vCont;c") == 0) { - // Simple continue - return RNBRemote::HandlePacket_c("c"); - } else if (strcmp(p, "vCont;s") == 0) { - // Simple step - return RNBRemote::HandlePacket_s("s"); - } else if (strstr(p, "vCont") == p) { - DNBThreadResumeActions thread_actions; - char *c = const_cast<char *>(p += strlen("vCont")); - char *c_end = c + strlen(c); - if (*c == '?') - return SendPacket("vCont;c;C;s;S"); - - while (c < c_end && *c == ';') { - ++c; // Skip the semi-colon - DNBThreadResumeAction thread_action; - thread_action.tid = INVALID_NUB_THREAD; - thread_action.state = eStateInvalid; - thread_action.signal = 0; - thread_action.addr = INVALID_NUB_ADDRESS; - - char action = *c++; - - switch (action) { - case 'C': - errno = 0; - thread_action.signal = static_cast<int>(strtoul(c, &c, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "Could not parse signal in vCont packet"); - // Fall through to next case... - [[clang::fallthrough]]; - case 'c': - // Continue - thread_action.state = eStateRunning; - break; - - case 'S': - errno = 0; - thread_action.signal = static_cast<int>(strtoul(c, &c, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "Could not parse signal in vCont packet"); - // Fall through to next case... - [[clang::fallthrough]]; - case 's': - // Step - thread_action.state = eStateStepping; - break; - - default: - HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Unsupported action in vCont packet"); - break; - } - if (*c == ':') { - errno = 0; - thread_action.tid = strtoul(++c, &c, 16); - if (errno != 0) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "Could not parse thread number in vCont packet"); - } - - thread_actions.Append(thread_action); - } - - // If a default action for all other threads wasn't mentioned - // then we should stop the threads - thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(), - thread_actions.GetSize()); - return rnb_success; - } else if (strstr(p, "vAttach") == p) { - nub_process_t attach_pid = - INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails - nub_process_t pid_attaching_to = - INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified - char err_str[1024] = {'\0'}; - std::string attach_name; - - if (strstr(p, "vAttachWait;") == p) { - p += strlen("vAttachWait;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt"); - } - const bool ignore_existing = true; - attach_pid = DNBProcessAttachWait( - attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, - 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); - - } else if (strstr(p, "vAttachOrWait;") == p) { - p += strlen("vAttachOrWait;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "non-hex char in arg on 'vAttachOrWait' pkt"); - } - const bool ignore_existing = false; - attach_pid = DNBProcessAttachWait( - attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, - 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); - } else if (strstr(p, "vAttachName;") == p) { - p += strlen("vAttachName;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); - } - - attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str, - sizeof(err_str)); - - } else if (strstr(p, "vAttach;") == p) { - p += strlen("vAttach;"); - char *end = NULL; - pid_attaching_to = static_cast<int>( - strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode - if (p != end && *end == '\0') { - // Wait at most 30 second for attach - struct timespec attach_timeout_abstime; - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); - attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, - err_str, sizeof(err_str)); - } - } else { - return HandlePacket_UNIMPLEMENTED(p); - } - - if (attach_pid != INVALID_NUB_PROCESS) { - if (m_ctx.ProcessID() != attach_pid) - m_ctx.SetProcessID(attach_pid); - // Send a stop reply packet to indicate we successfully attached! - NotifyThatProcessStopped(); - return rnb_success; - } else { - m_ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - m_ctx.LaunchStatus().SetErrorString(err_str); - else - m_ctx.LaunchStatus().SetErrorString("attach failed"); - -#if defined(__APPLE__) && \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) - if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) { - pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str()); - } - if (pid_attaching_to != INVALID_NUB_PROCESS && - strcmp(err_str, "No such process") != 0) { - // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity - // Protection is in effect. - if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) { - bool attach_failed_due_to_sip = false; - - if (rootless_allows_task_for_pid(pid_attaching_to) == 0) { - attach_failed_due_to_sip = true; - } - - if (!attach_failed_due_to_sip) { - int csops_flags = 0; - int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags, - sizeof(csops_flags)); - if (retval != -1 && (csops_flags & CS_RESTRICT)) { - attach_failed_due_to_sip = true; - } - } - if (attach_failed_due_to_sip) { - SendPacket("E87"); // E87 is the magic value which says that we are - // not allowed to attach - DNBLogError("Attach failed because process does not allow " - "attaching: \"%s\".", - err_str); - return rnb_err; - } - } - } - -#endif - - SendPacket("E01"); // E01 is our magic error value for attach failed. - DNBLogError("Attach failed: \"%s\".", err_str); - return rnb_err; - } - } - - // All other failures come through here - return HandlePacket_UNIMPLEMENTED(p); -} - -/* 'T XX' -- status of thread - Check if the specified thread is alive. - The thread number is in hex? */ - -rnb_err_t RNBRemote::HandlePacket_T(const char *p) { - p++; - if (p == NULL || *p == '\0') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in T packet"); - } - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E15"); - } - errno = 0; - nub_thread_t tid = strtoul(p, NULL, 16); - if (errno != 0 && tid == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse thread number in T packet"); - } - - nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid); - if (state == eStateInvalid || state == eStateExited || - state == eStateCrashed) { - return SendPacket("E16"); - } - - return SendPacket("OK"); -} - -rnb_err_t RNBRemote::HandlePacket_z(const char *p) { - if (p == NULL || *p == '\0') - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in z packet"); - - if (!m_ctx.HasValidProcessID()) - return SendPacket("E15"); - - char packet_cmd = *p++; - char break_type = *p++; - - if (*p++ != ',') - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma separator missing in z packet"); - - char *c = NULL; - nub_process_t pid = m_ctx.ProcessID(); - errno = 0; - nub_addr_t addr = strtoull(p, &c, 16); - if (errno != 0 && addr == 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid address in z packet"); - p = c; - if (*p++ != ',') - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Comma separator missing in z packet"); - - errno = 0; - auto byte_size = strtoul(p, &c, 16); - if (errno != 0 && byte_size == 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Invalid length in z packet"); - - if (packet_cmd == 'Z') { - // set - switch (break_type) { - case '0': // set software breakpoint - case '1': // set hardware breakpoint - { - // gdb can send multiple Z packets for the same address and - // these calls must be ref counted. - bool hardware = (break_type == '1'); - - if (DNBBreakpointSet(pid, addr, byte_size, hardware)) { - // We successfully created a breakpoint, now lets full out - // a ref count structure with the breakID and add it to our - // map. - return SendPacket("OK"); - } else { - // We failed to set the software breakpoint - return SendPacket("E09"); - } - } break; - - case '2': // set write watchpoint - case '3': // set read watchpoint - case '4': // set access watchpoint - { - bool hardware = true; - uint32_t watch_flags = 0; - if (break_type == '2') - watch_flags = WATCH_TYPE_WRITE; - else if (break_type == '3') - watch_flags = WATCH_TYPE_READ; - else - watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; - - if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) { - return SendPacket("OK"); - } else { - // We failed to set the watchpoint - return SendPacket("E09"); - } - } break; - - default: - break; - } - } else if (packet_cmd == 'z') { - // remove - switch (break_type) { - case '0': // remove software breakpoint - case '1': // remove hardware breakpoint - if (DNBBreakpointClear(pid, addr)) { - return SendPacket("OK"); - } else { - return SendPacket("E08"); - } - break; - - case '2': // remove write watchpoint - case '3': // remove read watchpoint - case '4': // remove access watchpoint - if (DNBWatchpointClear(pid, addr)) { - return SendPacket("OK"); - } else { - return SendPacket("E08"); - } - break; - - default: - break; - } - } - return HandlePacket_UNIMPLEMENTED(p); -} - -// Extract the thread number from the thread suffix that might be appended to -// thread specific packets. This will only be enabled if -// m_thread_suffix_supported -// is true. -nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) { - if (m_thread_suffix_supported) { - nub_thread_t tid = INVALID_NUB_THREAD; - if (p) { - const char *tid_cstr = strstr(p, "thread:"); - if (tid_cstr) { - tid_cstr += strlen("thread:"); - tid = strtoul(tid_cstr, NULL, 16); - } - } - return tid; - } - return GetCurrentThread(); -} - -/* 'p XX' - print the contents of register X */ - -rnb_err_t RNBRemote::HandlePacket_p(const char *p) { - if (g_num_reg_entries == 0) - InitializeRegisters(); - - if (p == NULL || *p == '\0') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in p packet"); - } - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E15"); - } - nub_process_t pid = m_ctx.ProcessID(); - errno = 0; - char *tid_cstr = NULL; - uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16)); - if (errno != 0 && reg == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "Could not parse register number in p packet"); - } - - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in p packet"); - - const register_map_entry_t *reg_entry; - - if (reg < g_num_reg_entries) - reg_entry = &g_reg_entries[reg]; - else - reg_entry = NULL; - - std::ostringstream ostrm; - if (reg_entry == NULL) { - DNBLogError( - "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", - p, reg); - ostrm << "00000000"; - } else if (reg_entry->nub_info.reg == (uint32_t)-1) { - if (reg_entry->nub_info.size > 0) { - std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0'); - append_hex_value(ostrm, zeros.data(), zeros.size(), false); - } - } else { - register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL); - } - return SendPacket(ostrm.str()); -} - -/* 'Pnn=rrrrr' - Set register number n to value r. - n and r are hex strings. */ - -rnb_err_t RNBRemote::HandlePacket_P(const char *p) { - if (g_num_reg_entries == 0) - InitializeRegisters(); - - if (p == NULL || *p == '\0') { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet"); - } - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E28"); - } - - nub_process_t pid = m_ctx.ProcessID(); - - StdStringExtractor packet(p); - - const char cmd_char = packet.GetChar(); - // Register ID is always in big endian - const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX); - const char equal_char = packet.GetChar(); - - if (cmd_char != 'P') - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Improperly formed P packet"); - - if (reg == UINT32_MAX) - return SendPacket("E29"); - - if (equal_char != '=') - return SendPacket("E30"); - - const register_map_entry_t *reg_entry; - - if (reg >= g_num_reg_entries) - return SendPacket("E47"); - - reg_entry = &g_reg_entries[reg]; - - if (reg_entry->nub_info.set == (uint32_t)-1 && - reg_entry->nub_info.reg == (uint32_t)-1) { - DNBLogError( - "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", - p, reg); - return SendPacket("E48"); - } - - DNBRegisterValue reg_value; - reg_value.info = reg_entry->nub_info; - packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc); - - nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "No thread specified in p packet"); - - if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set, - reg_entry->nub_info.reg, ®_value)) { - return SendPacket("E32"); - } - return SendPacket("OK"); -} - -/* 'c [addr]' - Continue, optionally from a specified address. */ - -rnb_err_t RNBRemote::HandlePacket_c(const char *p) { - const nub_process_t pid = m_ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E23"); - - DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0, - INVALID_NUB_ADDRESS}; - - if (*(p + 1) != '\0') { - action.tid = GetContinueThread(); - errno = 0; - action.addr = strtoull(p + 1, NULL, 16); - if (errno != 0 && action.addr == 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse address in c packet"); - } - - DNBThreadResumeActions thread_actions; - thread_actions.Append(action); - thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); - if (!DNBProcessResume(pid, thread_actions.GetFirst(), - thread_actions.GetSize())) - return SendPacket("E25"); - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; -} - -rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) { - /* This packet will find memory attributes (e.g. readable, writable, - executable, stack, jitted code) - for the memory region containing a given address and return that - information. - - Users of this packet must be prepared for three results: - - Region information is returned - Region information is unavailable for this address because the address - is in unmapped memory - Region lookup cannot be performed on this platform or process is not - yet launched - This packet isn't implemented - - Examples of use: - qMemoryRegionInfo:3a55140 - start:3a50000,size:100000,permissions:rwx - - qMemoryRegionInfo:0 - error:address in unmapped region - - qMemoryRegionInfo:3a551140 (on a different platform) - error:region lookup cannot be performed - - qMemoryRegionInfo - OK // this packet is implemented by the remote nub - */ - - p += sizeof("qMemoryRegionInfo") - 1; - if (*p == '\0') - return SendPacket("OK"); - if (*p++ != ':') - return SendPacket("E67"); - if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) - p += 2; - - errno = 0; - uint64_t address = strtoul(p, NULL, 16); - if (errno != 0 && address == 0) { - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); - } - - DNBRegionInfo region_info = {0, 0, 0}; - DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, ®ion_info); - std::ostringstream ostrm; - - // start:3a50000,size:100000,permissions:rwx - ostrm << "start:" << std::hex << region_info.addr << ';'; - - if (region_info.size > 0) - ostrm << "size:" << std::hex << region_info.size << ';'; - - if (region_info.permissions) { - ostrm << "permissions:"; - - if (region_info.permissions & eMemoryPermissionsReadable) - ostrm << 'r'; - if (region_info.permissions & eMemoryPermissionsWritable) - ostrm << 'w'; - if (region_info.permissions & eMemoryPermissionsExecutable) - ostrm << 'x'; - ostrm << ';'; - } - return SendPacket(ostrm.str()); -} - -// qGetProfileData;scan_type:0xYYYYYYY -rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) { - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("OK"); - - StdStringExtractor packet(p += sizeof("qGetProfileData")); - DNBProfileDataScanType scan_type = eProfileAll; - std::string name; - std::string value; - while (packet.GetNameColonValue(name, value)) { - if (name == "scan_type") { - std::istringstream iss(value); - uint32_t int_value = 0; - if (iss >> std::hex >> int_value) { - scan_type = (DNBProfileDataScanType)int_value; - } - } - } - - std::string data = DNBProcessGetProfileData(pid, scan_type); - if (!data.empty()) { - return SendPacket(data.c_str()); - } else { - return SendPacket("OK"); - } -} - -// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY -rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) { - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("OK"); - - StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling")); - bool enable = false; - uint64_t interval_usec = 0; - DNBProfileDataScanType scan_type = eProfileAll; - std::string name; - std::string value; - while (packet.GetNameColonValue(name, value)) { - if (name == "enable") { - enable = strtoul(value.c_str(), NULL, 10) > 0; - } else if (name == "interval_usec") { - interval_usec = strtoul(value.c_str(), NULL, 10); - } else if (name == "scan_type") { - std::istringstream iss(value); - uint32_t int_value = 0; - if (iss >> std::hex >> int_value) { - scan_type = (DNBProfileDataScanType)int_value; - } - } - } - - if (interval_usec == 0) { - enable = 0; - } - - DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); - return SendPacket("OK"); -} - -// QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO -// COMPRESS>; -// -// type: must be a type previously reported by the qXfer:features: -// SupportedCompressions list -// -// minsize: is optional; by default the qXfer:features: -// DefaultCompressionMinSize value is used -// debugserver may have a better idea of what a good minimum packet size to -// compress is than lldb. - -rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) { - p += sizeof("QEnableCompression:") - 1; - - size_t new_compression_minsize = m_compression_minsize; - const char *new_compression_minsize_str = strstr(p, "minsize:"); - if (new_compression_minsize_str) { - new_compression_minsize_str += strlen("minsize:"); - errno = 0; - new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10); - if (errno != 0 || new_compression_minsize == ULONG_MAX) { - new_compression_minsize = m_compression_minsize; - } - } - - if (strstr(p, "type:zlib-deflate;") != nullptr) { - EnableCompressionNextSendPacket(compression_types::zlib_deflate); - m_compression_minsize = new_compression_minsize; - return SendPacket("OK"); - } else if (strstr(p, "type:lz4;") != nullptr) { - EnableCompressionNextSendPacket(compression_types::lz4); - m_compression_minsize = new_compression_minsize; - return SendPacket("OK"); - } else if (strstr(p, "type:lzma;") != nullptr) { - EnableCompressionNextSendPacket(compression_types::lzma); - m_compression_minsize = new_compression_minsize; - return SendPacket("OK"); - } else if (strstr(p, "type:lzfse;") != nullptr) { - EnableCompressionNextSendPacket(compression_types::lzfse); - m_compression_minsize = new_compression_minsize; - return SendPacket("OK"); - } - - return SendPacket("E88"); -} - -rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) { - p += strlen("qSpeedTest:response_size:"); - char *end = NULL; - errno = 0; - uint64_t response_size = ::strtoul(p, &end, 16); - if (errno != 0) - return HandlePacket_ILLFORMED( - __FILE__, __LINE__, p, - "Didn't find response_size value at right offset"); - else if (*end == ';') { - static char g_data[4 * 1024 * 1024 + 16] = "data:"; - memset(g_data + 5, 'a', response_size); - g_data[response_size + 5] = '\0'; - return SendPacket(g_data); - } else { - return SendPacket("E79"); - } -} - -rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) { - /* This packet simply returns the number of supported hardware watchpoints. - - Examples of use: - qWatchpointSupportInfo: - num:4 - - qWatchpointSupportInfo - OK // this packet is implemented by the remote nub - */ - - p += sizeof("qWatchpointSupportInfo") - 1; - if (*p == '\0') - return SendPacket("OK"); - if (*p++ != ':') - return SendPacket("E67"); - - errno = 0; - uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID()); - std::ostringstream ostrm; - - // size:4 - ostrm << "num:" << std::dec << num << ';'; - return SendPacket(ostrm.str()); -} - -/* 'C sig [;addr]' - Resume with signal sig, optionally at address addr. */ - -rnb_err_t RNBRemote::HandlePacket_C(const char *p) { - const nub_process_t pid = m_ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E36"); - - DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0, - INVALID_NUB_ADDRESS}; - int process_signo = -1; - if (*(p + 1) != '\0') { - action.tid = GetContinueThread(); - char *end = NULL; - errno = 0; - process_signo = static_cast<int>(strtoul(p + 1, &end, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse signal in C packet"); - else if (*end == ';') { - errno = 0; - action.addr = strtoull(end + 1, NULL, 16); - if (errno != 0 && action.addr == 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse address in C packet"); - } - } - - DNBThreadResumeActions thread_actions; - thread_actions.Append(action); - thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal); - if (!DNBProcessSignal(pid, process_signo)) - return SendPacket("E52"); - if (!DNBProcessResume(pid, thread_actions.GetFirst(), - thread_actions.GetSize())) - return SendPacket("E38"); - /* Don't send an "OK" packet; response is the stopped/exited message. */ - return rnb_success; -} - -//---------------------------------------------------------------------- -// 'D' packet -// Detach from gdb. -//---------------------------------------------------------------------- -rnb_err_t RNBRemote::HandlePacket_D(const char *p) { - if (m_ctx.HasValidProcessID()) { - if (DNBProcessDetach(m_ctx.ProcessID())) - SendPacket("OK"); - else - SendPacket("E"); - } else { - SendPacket("E"); - } - return rnb_success; -} - -/* 'k' - Kill the inferior process. */ - -rnb_err_t RNBRemote::HandlePacket_k(const char *p) { - DNBLog("Got a 'k' packet, killing the inferior process."); - // No response to should be sent to the kill packet - if (m_ctx.HasValidProcessID()) - DNBProcessKill(m_ctx.ProcessID()); - SendPacket("X09"); - return rnb_success; -} - -rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) { -//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test -//exiting on interrupt -#if defined(TEST_EXIT_ON_INTERRUPT) - rnb_err_t err = HandlePacket_k(p); - m_comm.Disconnect(true); - return err; -#else - if (!DNBProcessInterrupt(m_ctx.ProcessID())) { - // If we failed to interrupt the process, then send a stop - // reply packet as the process was probably already stopped - DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop " - "reply because DNBProcessInterrupt returned false"); - HandlePacket_last_signal(NULL); - } - return rnb_success; -#endif -} - -/* 's' - Step the inferior process. */ - -rnb_err_t RNBRemote::HandlePacket_s(const char *p) { - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E32"); - - // Hardware supported stepping not supported on arm - nub_thread_t tid = GetContinueThread(); - if (tid == 0 || tid == (nub_thread_t)-1) - tid = GetCurrentThread(); - - if (tid == INVALID_NUB_THREAD) - return SendPacket("E33"); - - DNBThreadResumeActions thread_actions; - thread_actions.AppendAction(tid, eStateStepping); - - // Make all other threads stop when we are stepping - thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - if (!DNBProcessResume(pid, thread_actions.GetFirst(), - thread_actions.GetSize())) - return SendPacket("E49"); - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; -} - -/* 'S sig [;addr]' - Step with signal sig, optionally at address addr. */ - -rnb_err_t RNBRemote::HandlePacket_S(const char *p) { - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E36"); - - DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0, - INVALID_NUB_ADDRESS}; - - if (*(p + 1) != '\0') { - char *end = NULL; - errno = 0; - action.signal = static_cast<int>(strtoul(p + 1, &end, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse signal in S packet"); - else if (*end == ';') { - errno = 0; - action.addr = strtoull(end + 1, NULL, 16); - if (errno != 0 && action.addr == 0) { - return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, - "Could not parse address in S packet"); - } - } - } - - action.tid = GetContinueThread(); - if (action.tid == 0 || action.tid == (nub_thread_t)-1) - return SendPacket("E40"); - - nub_state_t tstate = DNBThreadGetState(pid, action.tid); - if (tstate == eStateInvalid || tstate == eStateExited) - return SendPacket("E37"); - - DNBThreadResumeActions thread_actions; - thread_actions.Append(action); - - // Make all other threads stop when we are stepping - thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - if (!DNBProcessResume(pid, thread_actions.GetFirst(), - thread_actions.GetSize())) - return SendPacket("E39"); - - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; -} - -static const char *GetArchName(const uint32_t cputype, - const uint32_t cpusubtype) { - switch (cputype) { - case CPU_TYPE_ARM: - switch (cpusubtype) { - case 5: - return "armv4"; - case 6: - return "armv6"; - case 7: - return "armv5t"; - case 8: - return "xscale"; - case 9: - return "armv7"; - case 10: - return "armv7f"; - case 11: - return "armv7s"; - case 12: - return "armv7k"; - case 14: - return "armv6m"; - case 15: - return "armv7m"; - case 16: - return "armv7em"; - default: - return "arm"; - } - break; - case CPU_TYPE_ARM64: - return "arm64"; - case CPU_TYPE_I386: - return "i386"; - case CPU_TYPE_X86_64: - switch (cpusubtype) { - default: - return "x86_64"; - case 8: - return "x86_64h"; - } - break; - } - return NULL; -} - -static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype, - uint32_t &is_64_bit_capable, bool &promoted_to_64) { - static uint32_t g_host_cputype = 0; - static uint32_t g_host_cpusubtype = 0; - static uint32_t g_is_64_bit_capable = 0; - static bool g_promoted_to_64 = false; - - if (g_host_cputype == 0) { - g_promoted_to_64 = false; - size_t len = sizeof(uint32_t); - if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) { - len = sizeof(uint32_t); - if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, - NULL, 0) == 0) { - if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) { - g_promoted_to_64 = true; - g_host_cputype |= CPU_ARCH_ABI64; - } - } - } - - len = sizeof(uint32_t); - if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == - 0) { - if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 && - g_host_cpusubtype == CPU_SUBTYPE_486) - g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL; - } - } - - cputype = g_host_cputype; - cpusubtype = g_host_cpusubtype; - is_64_bit_capable = g_is_64_bit_capable; - promoted_to_64 = g_promoted_to_64; - return g_host_cputype != 0; -} - -rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) { - std::ostringstream strm; - - uint32_t cputype = 0; - uint32_t cpusubtype = 0; - uint32_t is_64_bit_capable = 0; - bool promoted_to_64 = false; - if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) { - strm << "cputype:" << std::dec << cputype << ';'; - strm << "cpusubtype:" << std::dec << cpusubtype << ';'; - } - - // The OS in the triple should be "ios" or "macosx" which doesn't match our - // "Darwin" which gets returned from "kern.ostype", so we need to hardcode - // this for now. - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) { -#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 - strm << "ostype:tvos;"; -#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - strm << "ostype:watchos;"; -#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 - strm << "ostype:bridgeos;"; -#else - strm << "ostype:ios;"; -#endif - - // On armv7 we use "synchronous" watchpoints which means the exception is - // delivered before the instruction executes. - strm << "watchpoint_exceptions_received:before;"; - } else { - strm << "ostype:macosx;"; - strm << "watchpoint_exceptions_received:after;"; - } - // char ostype[64]; - // len = sizeof(ostype); - // if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) - // { - // len = strlen(ostype); - // std::transform (ostype, ostype + len, ostype, tolower); - // strm << "ostype:" << std::dec << ostype << ';'; - // } - - strm << "vendor:apple;"; - - uint64_t major, minor, patch; - if (DNBGetOSVersionNumbers(&major, &minor, &patch)) { - strm << "os_version:" << major << "." << minor; - if (patch != UINT64_MAX) - strm << "." << patch; - strm << ";"; - } - -#if defined(__LITTLE_ENDIAN__) - strm << "endian:little;"; -#elif defined(__BIG_ENDIAN__) - strm << "endian:big;"; -#elif defined(__PDP_ENDIAN__) - strm << "endian:pdp;"; -#endif - - if (promoted_to_64) - strm << "ptrsize:8;"; - else - strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; - -#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - strm << "default_packet_timeout:10;"; -#endif - - return SendPacket(strm.str()); -} - -void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name, - bool has_attributes) { - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << name; - if (!has_attributes) - s << '>' << std::endl; -} - -void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) { - if (empty) - s << '/'; - s << '>' << std::endl; -} - -void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) { - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << '/' << name << '>' << std::endl; -} - -void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent, - const char *name, const char *value, - bool close = true) { - if (value) { - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << name << '>' << value; - if (close) - XMLElementEnd(s, 0, name); - } -} - -void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent, - const char *name, uint64_t value, - bool close = true) { - if (indent) - s << INDENT_WITH_SPACES(indent); - - s << '<' << name << '>' << DECIMAL << value; - if (close) - XMLElementEnd(s, 0, name); -} - -void XMLAttributeString(std::ostringstream &s, const char *name, - const char *value, const char *default_value = NULL) { - if (value) { - if (default_value && strcmp(value, default_value) == 0) - return; // No need to emit the attribute because it matches the default - // value - s << ' ' << name << "=\"" << value << "\""; - } -} - -void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name, - uint64_t value) { - s << ' ' << name << "=\"" << DECIMAL << value << "\""; -} - -void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num, - nub_size_t num_reg_sets, - const DNBRegisterSetInfo *reg_set_info, - const register_map_entry_t ®) { - const char *default_lldb_encoding = "uint"; - const char *lldb_encoding = default_lldb_encoding; - const char *gdb_group = "general"; - const char *default_gdb_type = "int"; - const char *gdb_type = default_gdb_type; - const char *default_lldb_format = "hex"; - const char *lldb_format = default_lldb_format; - const char *lldb_set = NULL; - - switch (reg.nub_info.type) { - case Uint: - lldb_encoding = "uint"; - break; - case Sint: - lldb_encoding = "sint"; - break; - case IEEE754: - lldb_encoding = "ieee754"; - if (reg.nub_info.set > 0) - gdb_group = "float"; - break; - case Vector: - lldb_encoding = "vector"; - if (reg.nub_info.set > 0) - gdb_group = "vector"; - break; - } - - switch (reg.nub_info.format) { - case Binary: - lldb_format = "binary"; - break; - case Decimal: - lldb_format = "decimal"; - break; - case Hex: - lldb_format = "hex"; - break; - case Float: - gdb_type = "float"; - lldb_format = "float"; - break; - case VectorOfSInt8: - gdb_type = "float"; - lldb_format = "vector-sint8"; - break; - case VectorOfUInt8: - gdb_type = "float"; - lldb_format = "vector-uint8"; - break; - case VectorOfSInt16: - gdb_type = "float"; - lldb_format = "vector-sint16"; - break; - case VectorOfUInt16: - gdb_type = "float"; - lldb_format = "vector-uint16"; - break; - case VectorOfSInt32: - gdb_type = "float"; - lldb_format = "vector-sint32"; - break; - case VectorOfUInt32: - gdb_type = "float"; - lldb_format = "vector-uint32"; - break; - case VectorOfFloat32: - gdb_type = "float"; - lldb_format = "vector-float32"; - break; - case VectorOfUInt128: - gdb_type = "float"; - lldb_format = "vector-uint128"; - break; - }; - if (reg_set_info && reg.nub_info.set < num_reg_sets) - lldb_set = reg_set_info[reg.nub_info.set].name; - - uint32_t indent = 2; - - XMLElementStart(s, indent, "reg", true); - XMLAttributeString(s, "name", reg.nub_info.name); - XMLAttributeUnsignedDecimal(s, "regnum", reg_num); - XMLAttributeUnsignedDecimal(s, "offset", reg.offset); - XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8); - XMLAttributeString(s, "group", gdb_group); - XMLAttributeString(s, "type", gdb_type, default_gdb_type); - XMLAttributeString(s, "altname", reg.nub_info.alt); - XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding); - XMLAttributeString(s, "format", lldb_format, default_lldb_format); - XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set); - if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM) - XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe); - if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM) - XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf); - - const char *lldb_generic = NULL; - switch (reg.nub_info.reg_generic) { - case GENERIC_REGNUM_FP: - lldb_generic = "fp"; - break; - case GENERIC_REGNUM_PC: - lldb_generic = "pc"; - break; - case GENERIC_REGNUM_SP: - lldb_generic = "sp"; - break; - case GENERIC_REGNUM_RA: - lldb_generic = "ra"; - break; - case GENERIC_REGNUM_FLAGS: - lldb_generic = "flags"; - break; - case GENERIC_REGNUM_ARG1: - lldb_generic = "arg1"; - break; - case GENERIC_REGNUM_ARG2: - lldb_generic = "arg2"; - break; - case GENERIC_REGNUM_ARG3: - lldb_generic = "arg3"; - break; - case GENERIC_REGNUM_ARG4: - lldb_generic = "arg4"; - break; - case GENERIC_REGNUM_ARG5: - lldb_generic = "arg5"; - break; - case GENERIC_REGNUM_ARG6: - lldb_generic = "arg6"; - break; - case GENERIC_REGNUM_ARG7: - lldb_generic = "arg7"; - break; - case GENERIC_REGNUM_ARG8: - lldb_generic = "arg8"; - break; - default: - break; - } - XMLAttributeString(s, "generic", lldb_generic); - - bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty(); - if (!empty) { - if (!reg.value_regnums.empty()) { - std::ostringstream regnums; - bool first = true; - regnums << DECIMAL; - for (auto regnum : reg.value_regnums) { - if (!first) - regnums << ','; - regnums << regnum; - first = false; - } - XMLAttributeString(s, "value_regnums", regnums.str().c_str()); - } - - if (!reg.invalidate_regnums.empty()) { - std::ostringstream regnums; - bool first = true; - regnums << DECIMAL; - for (auto regnum : reg.invalidate_regnums) { - if (!first) - regnums << ','; - regnums << regnum; - first = false; - } - XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str()); - } - } - XMLElementStartEndAttributes(s, true); -} - -void GenerateTargetXMLRegisters(std::ostringstream &s) { - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets); - - uint32_t cputype = DNBGetRegisterCPUType(); - if (cputype) { - XMLElementStart(s, 0, "feature", true); - std::ostringstream name_strm; - name_strm << "com.apple.debugserver." << GetArchName(cputype, 0); - XMLAttributeString(s, "name", name_strm.str().c_str()); - XMLElementStartEndAttributes(s, false); - for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num) - // for (const auto ®: g_dynamic_register_map) - { - GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, - g_reg_entries[reg_num]); - } - XMLElementEnd(s, 0, "feature"); - - if (num_reg_sets > 0) { - XMLElementStart(s, 0, "groups", false); - for (uint32_t set = 1; set < num_reg_sets; ++set) { - XMLElementStart(s, 2, "group", true); - XMLAttributeUnsignedDecimal(s, "id", set); - XMLAttributeString(s, "name", reg_sets[set].name); - XMLElementStartEndAttributes(s, true); - } - XMLElementEnd(s, 0, "groups"); - } - } -} - -static const char *g_target_xml_header = R"(<?xml version="1.0"?> -<target version="1.0">)"; - -static const char *g_target_xml_footer = "</target>"; - -static std::string g_target_xml; - -void UpdateTargetXML() { - std::ostringstream s; - s << g_target_xml_header << std::endl; - - // Set the architecture - // - // On raw targets (no OS, vendor info), I've seen replies like - // <architecture>i386:x86-64</architecture> (for x86_64 systems - from vmware) - // <architecture>arm</architecture> (for an unspecified arm device - from a Segger JLink) - // For good interop, I'm not sure what's expected here. e.g. will anyone understand - // <architecture>x86_64</architecture> ? Or is i386:x86_64 the expected phrasing? - // - // s << "<architecture>" << arch "</architecture>" << std::endl; - - // Set the OSABI - // s << "<osabi>abi-name</osabi>" - - GenerateTargetXMLRegisters(s); - - s << g_target_xml_footer << std::endl; - - // Save the XML output in case it gets retrieved in chunks - g_target_xml = s.str(); -} - -rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) { - const char *p = command; - p += strlen("qXfer:"); - const char *sep = strchr(p, ':'); - if (sep) { - std::string object(p, sep - p); // "auxv", "backtrace", "features", etc - p = sep + 1; - sep = strchr(p, ':'); - if (sep) { - std::string rw(p, sep - p); // "read" or "write" - p = sep + 1; - sep = strchr(p, ':'); - if (sep) { - std::string annex(p, sep - p); // "read" or "write" - - p = sep + 1; - sep = strchr(p, ','); - if (sep) { - std::string offset_str(p, sep - p); // read the length as a string - p = sep + 1; - std::string length_str(p); // read the offset as a string - char *end = nullptr; - const uint64_t offset = strtoul(offset_str.c_str(), &end, - 16); // convert offset_str to a offset - if (*end == '\0') { - const uint64_t length = strtoul( - length_str.c_str(), &end, 16); // convert length_str to a length - if (*end == '\0') { - if (object == "features" && rw == "read" && - annex == "target.xml") { - std::ostringstream xml_out; - - if (offset == 0) { - InitializeRegisters(true); - - UpdateTargetXML(); - if (g_target_xml.empty()) - return SendPacket("E83"); - - if (length > g_target_xml.size()) { - xml_out << 'l'; // No more data - xml_out << binary_encode_string(g_target_xml); - } else { - xml_out << 'm'; // More data needs to be read with a - // subsequent call - xml_out << binary_encode_string( - std::string(g_target_xml, offset, length)); - } - } else { - // Retrieving target XML in chunks - if (offset < g_target_xml.size()) { - std::string chunk(g_target_xml, offset, length); - if (chunk.size() < length) - xml_out << 'l'; // No more data - else - xml_out << 'm'; // More data needs to be read with a - // subsequent call - xml_out << binary_encode_string(chunk.data()); - } - } - return SendPacket(xml_out.str()); - } - // Well formed, put not supported - return HandlePacket_UNIMPLEMENTED(command); - } - } - } - } else { - SendPacket("E85"); - } - } else { - SendPacket("E86"); - } - } - return SendPacket("E82"); -} - -rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) { - std::ostringstream strm; - -#if defined(DEBUGSERVER_PROGRAM_NAME) - strm << "name:" DEBUGSERVER_PROGRAM_NAME ";"; -#else - strm << "name:debugserver;"; -#endif - strm << "version:" << DEBUGSERVER_VERSION_NUM << ";"; - - return SendPacket(strm.str()); -} - -// A helper function that retrieves a single integer value from -// a one-level-deep JSON dictionary of key-value pairs. e.g. -// jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}] -// -uint64_t get_integer_value_for_key_name_from_json(const char *key, - const char *json_string) { - uint64_t retval = INVALID_NUB_ADDRESS; - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr(json_string, key_with_quotes.c_str()); - if (c) { - c += key_with_quotes.size(); - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == ':') { - c++; - - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - errno = 0; - retval = strtoul(c, NULL, 10); - if (errno != 0) { - retval = INVALID_NUB_ADDRESS; - } - } - } - return retval; -} - -// A helper function that retrieves a boolean value from -// a one-level-deep JSON dictionary of key-value pairs. e.g. -// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}] - -// Returns true if it was able to find the key name, and sets the 'value' -// argument to the value found. - -bool get_boolean_value_for_key_name_from_json(const char *key, - const char *json_string, - bool &value) { - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr(json_string, key_with_quotes.c_str()); - if (c) { - c += key_with_quotes.size(); - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == ':') { - c++; - - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (strncmp(c, "true", 4) == 0) { - value = true; - return true; - } else if (strncmp(c, "false", 5) == 0) { - value = false; - return true; - } - } - } - return false; -} - -// A helper function that reads an array of uint64_t's from -// a one-level-deep JSON dictionary of key-value pairs. e.g. -// jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}] - -// Returns true if it was able to find the key name, false if it did not. -// "ints" will have all integers found in the array appended to it. - -bool get_array_of_ints_value_for_key_name_from_json( - const char *key, const char *json_string, std::vector<uint64_t> &ints) { - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr(json_string, key_with_quotes.c_str()); - if (c) { - c += key_with_quotes.size(); - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == ':') { - c++; - - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == '[') { - c++; - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - while (1) { - if (!isdigit(*c)) { - return true; - } - - errno = 0; - char *endptr; - uint64_t value = strtoul(c, &endptr, 10); - if (errno == 0) { - ints.push_back(value); - } else { - break; - } - if (endptr == c || endptr == nullptr || *endptr == '\0') { - break; - } - c = endptr; - - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - if (*c == ',') - c++; - while (*c != '\0' && - (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - if (*c == ']') { - return true; - } - } - } - } - } - return false; -} - -JSONGenerator::ObjectSP -RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) { - JSONGenerator::ArraySP threads_array_sp; - if (m_ctx.HasValidProcessID()) { - threads_array_sp.reset(new JSONGenerator::Array()); - - nub_process_t pid = m_ctx.ProcessID(); - - nub_size_t numthreads = DNBProcessGetNumThreads(pid); - for (nub_size_t i = 0; i < numthreads; ++i) { - nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i); - - struct DNBThreadStopInfo tid_stop_info; - - const bool stop_info_valid = - DNBThreadGetStopReason(pid, tid, &tid_stop_info); - - // If we are doing stop info only, then we only show threads that have a - // valid stop reason - if (threads_with_valid_stop_info_only) { - if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid) - continue; - } - - JSONGenerator::DictionarySP thread_dict_sp( - new JSONGenerator::Dictionary()); - thread_dict_sp->AddIntegerItem("tid", tid); - - std::string reason_value("none"); - - if (stop_info_valid) { - switch (tid_stop_info.reason) { - case eStopTypeInvalid: - break; - - case eStopTypeSignal: - if (tid_stop_info.details.signal.signo != 0) { - thread_dict_sp->AddIntegerItem("signal", - tid_stop_info.details.signal.signo); - reason_value = "signal"; - } - break; - - case eStopTypeException: - if (tid_stop_info.details.exception.type != 0) { - reason_value = "exception"; - thread_dict_sp->AddIntegerItem( - "metype", tid_stop_info.details.exception.type); - JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array()); - for (nub_size_t i = 0; - i < tid_stop_info.details.exception.data_count; ++i) { - medata_array_sp->AddItem( - JSONGenerator::IntegerSP(new JSONGenerator::Integer( - tid_stop_info.details.exception.data[i]))); - } - thread_dict_sp->AddItem("medata", medata_array_sp); - } - break; - - case eStopTypeExec: - reason_value = "exec"; - break; - } - } - - thread_dict_sp->AddStringItem("reason", reason_value); - - if (!threads_with_valid_stop_info_only) { - const char *thread_name = DNBThreadGetName(pid, tid); - if (thread_name && thread_name[0]) - thread_dict_sp->AddStringItem("name", thread_name); - - thread_identifier_info_data_t thread_ident_info; - if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) { - if (thread_ident_info.dispatch_qaddr != 0) { - thread_dict_sp->AddIntegerItem("qaddr", - thread_ident_info.dispatch_qaddr); - - const DispatchQueueOffsets *dispatch_queue_offsets = - GetDispatchQueueOffsets(); - if (dispatch_queue_offsets) { - std::string queue_name; - uint64_t queue_width = 0; - uint64_t queue_serialnum = 0; - nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS; - dispatch_queue_offsets->GetThreadQueueInfo( - pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t, - queue_name, queue_width, queue_serialnum); - if (dispatch_queue_t == 0 && queue_name.empty() && - queue_serialnum == 0) { - thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue", - false); - } else { - thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue", - true); - } - if (dispatch_queue_t != INVALID_NUB_ADDRESS && - dispatch_queue_t != 0) - thread_dict_sp->AddIntegerItem("dispatch_queue_t", - dispatch_queue_t); - if (!queue_name.empty()) - thread_dict_sp->AddStringItem("qname", queue_name); - if (queue_width == 1) - thread_dict_sp->AddStringItem("qkind", "serial"); - else if (queue_width > 1) - thread_dict_sp->AddStringItem("qkind", "concurrent"); - if (queue_serialnum > 0) - thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum); - } - } - } - - DNBRegisterValue reg_value; - - if (g_reg_entries != NULL) { - JSONGenerator::DictionarySP registers_dict_sp( - new JSONGenerator::Dictionary()); - - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) { - // Expedite all registers in the first register set that aren't - // contained in other registers - if (g_reg_entries[reg].nub_info.set == 1 && - g_reg_entries[reg].nub_info.value_regs == NULL) { - if (!DNBThreadGetRegisterValueByID( - pid, tid, g_reg_entries[reg].nub_info.set, - g_reg_entries[reg].nub_info.reg, ®_value)) - continue; - - std::ostringstream reg_num; - reg_num << std::dec << g_reg_entries[reg].debugserver_regnum; - // Encode native byte ordered bytes as hex ascii - registers_dict_sp->AddBytesAsHexASCIIString( - reg_num.str(), reg_value.value.v_uint8, - g_reg_entries[reg].nub_info.size); - } - } - thread_dict_sp->AddItem("registers", registers_dict_sp); - } - - // Add expedited stack memory so stack backtracing doesn't need to read - // anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory(pid, tid, stack_mmap); - if (!stack_mmap.empty()) { - JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array()); - - for (const auto &stack_memory : stack_mmap) { - JSONGenerator::DictionarySP stack_memory_sp( - new JSONGenerator::Dictionary()); - stack_memory_sp->AddIntegerItem("address", stack_memory.first); - stack_memory_sp->AddBytesAsHexASCIIString( - "bytes", stack_memory.second.bytes, stack_memory.second.length); - memory_array_sp->AddItem(stack_memory_sp); - } - thread_dict_sp->AddItem("memory", memory_array_sp); - } - } - - threads_array_sp->AddItem(thread_dict_sp); - } - } - return threads_array_sp; -} - -rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) { - JSONGenerator::ObjectSP threads_info_sp; - std::ostringstream json; - std::ostringstream reply_strm; - // If we haven't run the process yet, return an error. - if (m_ctx.HasValidProcessID()) { - const bool threads_with_valid_stop_info_only = false; - JSONGenerator::ObjectSP threads_info_sp = - GetJSONThreadsInfo(threads_with_valid_stop_info_only); - - if (threads_info_sp) { - std::ostringstream strm; - threads_info_sp->Dump(strm); - std::string binary_packet = binary_encode_string(strm.str()); - if (!binary_packet.empty()) - return SendPacket(binary_packet.c_str()); - } - } - return SendPacket("E85"); -} - -rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) { - nub_process_t pid; - std::ostringstream json; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E81"); - } - - pid = m_ctx.ProcessID(); - - const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"}; - if (strncmp(p, thread_extended_info_str, - sizeof(thread_extended_info_str) - 1) == 0) { - p += strlen(thread_extended_info_str); - - uint64_t tid = get_integer_value_for_key_name_from_json("thread", p); - uint64_t plo_pthread_tsd_base_address_offset = - get_integer_value_for_key_name_from_json( - "plo_pthread_tsd_base_address_offset", p); - uint64_t plo_pthread_tsd_base_offset = - get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset", - p); - uint64_t plo_pthread_tsd_entry_size = - get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size", - p); - uint64_t dti_qos_class_index = - get_integer_value_for_key_name_from_json("dti_qos_class_index", p); - - if (tid != INVALID_NUB_ADDRESS) { - nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid); - - uint64_t tsd_address = INVALID_NUB_ADDRESS; - if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS && - plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS && - plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) { - tsd_address = DNBGetTSDAddressForThread( - pid, tid, plo_pthread_tsd_base_address_offset, - plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); - } - - bool timed_out = false; - Genealogy::ThreadActivitySP thread_activity_sp; - - // If the pthread_t value is invalid, or if we were able to fetch the - // thread's TSD base - // and got an invalid value back, then we have a thread in early startup - // or shutdown and - // it's possible that gathering the genealogy information for this thread - // go badly. - // Ideally fetching this info for a thread in these odd states shouldn't - // matter - but - // we've seen some problems with these new SPI and threads in edge-casey - // states. - - double genealogy_fetch_time = 0; - if (pthread_t_value != INVALID_NUB_ADDRESS && - tsd_address != INVALID_NUB_ADDRESS) { - DNBTimer timer(false); - thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out); - genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0; - } - - std::unordered_set<uint32_t> - process_info_indexes; // an array of the process info #'s seen - - json << "{"; - - bool need_to_print_comma = false; - - if (thread_activity_sp && !timed_out) { - const Genealogy::Activity *activity = - &thread_activity_sp->current_activity; - bool need_vouchers_comma_sep = false; - json << "\"activity_query_timed_out\":false,"; - if (genealogy_fetch_time != 0) { - // If we append the floating point value with << we'll get it in - // scientific - // notation. - char floating_point_ascii_buffer[64]; - floating_point_ascii_buffer[0] = '\0'; - snprintf(floating_point_ascii_buffer, - sizeof(floating_point_ascii_buffer), "%f", - genealogy_fetch_time); - if (strlen(floating_point_ascii_buffer) > 0) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"activity_query_duration\":" - << floating_point_ascii_buffer; - } - } - if (activity->activity_id != 0) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - need_vouchers_comma_sep = true; - json << "\"activity\":{"; - json << "\"start\":" << activity->activity_start << ","; - json << "\"id\":" << activity->activity_id << ","; - json << "\"parent_id\":" << activity->parent_id << ","; - json << "\"name\":\"" - << json_string_quote_metachars(activity->activity_name) << "\","; - json << "\"reason\":\"" - << json_string_quote_metachars(activity->reason) << "\""; - json << "}"; - } - if (thread_activity_sp->messages.size() > 0) { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - json << "\"trace_messages\":["; - bool printed_one_message = false; - for (auto iter = thread_activity_sp->messages.begin(); - iter != thread_activity_sp->messages.end(); ++iter) { - if (printed_one_message) - json << ","; - else - printed_one_message = true; - json << "{"; - json << "\"timestamp\":" << iter->timestamp << ","; - json << "\"activity_id\":" << iter->activity_id << ","; - json << "\"trace_id\":" << iter->trace_id << ","; - json << "\"thread\":" << iter->thread << ","; - json << "\"type\":" << (int)iter->type << ","; - json << "\"process_info_index\":" << iter->process_info_index - << ","; - process_info_indexes.insert(iter->process_info_index); - json << "\"message\":\"" - << json_string_quote_metachars(iter->message) << "\""; - json << "}"; - } - json << "]"; - } - if (thread_activity_sp->breadcrumbs.size() == 1) { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - json << "\"breadcrumb\":{"; - for (auto iter = thread_activity_sp->breadcrumbs.begin(); - iter != thread_activity_sp->breadcrumbs.end(); ++iter) { - json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ","; - json << "\"activity_id\":" << iter->activity_id << ","; - json << "\"timestamp\":" << iter->timestamp << ","; - json << "\"name\":\"" << json_string_quote_metachars(iter->name) - << "\""; - } - json << "}"; - } - if (process_info_indexes.size() > 0) { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - bool printed_one_process_info = false; - for (auto iter = process_info_indexes.begin(); - iter != process_info_indexes.end(); ++iter) { - if (printed_one_process_info) - json << ","; - Genealogy::ProcessExecutableInfoSP image_info_sp; - uint32_t idx = *iter; - image_info_sp = DNBGetGenealogyImageInfo(pid, idx); - if (image_info_sp) { - if (!printed_one_process_info) { - json << "\"process_infos\":["; - printed_one_process_info = true; - } - - json << "{"; - char uuid_buf[37]; - uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf); - json << "\"process_info_index\":" << idx << ","; - json << "\"image_path\":\"" - << json_string_quote_metachars(image_info_sp->image_path) - << "\","; - json << "\"image_uuid\":\"" << uuid_buf << "\""; - json << "}"; - } - } - if (printed_one_process_info) - json << "]"; - } - } else { - if (timed_out) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"activity_query_timed_out\":true"; - if (genealogy_fetch_time != 0) { - // If we append the floating point value with << we'll get it in - // scientific - // notation. - char floating_point_ascii_buffer[64]; - floating_point_ascii_buffer[0] = '\0'; - snprintf(floating_point_ascii_buffer, - sizeof(floating_point_ascii_buffer), "%f", - genealogy_fetch_time); - if (strlen(floating_point_ascii_buffer) > 0) { - json << ","; - json << "\"activity_query_duration\":" - << floating_point_ascii_buffer; - } - } - } - } - - if (tsd_address != INVALID_NUB_ADDRESS) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"tsd_address\":" << tsd_address; - - if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) { - ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread( - pid, tid, tsd_address, dti_qos_class_index); - if (requested_qos.IsValid()) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"requested_qos\":{"; - json << "\"enum_value\":" << requested_qos.enum_value << ","; - json << "\"constant_name\":\"" - << json_string_quote_metachars(requested_qos.constant_name) - << "\","; - json << "\"printable_name\":\"" - << json_string_quote_metachars(requested_qos.printable_name) - << "\""; - json << "}"; - } - } - } - - if (pthread_t_value != INVALID_NUB_ADDRESS) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"pthread_t\":" << pthread_t_value; - } - - nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid); - if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"dispatch_queue_t\":" << dispatch_queue_t_value; - } - - json << "}"; - std::string json_quoted = binary_encode_string(json.str()); - return SendPacket(json_quoted); - } - } - return SendPacket("OK"); -} - -// This packet may be called in one of three ways: -// -// jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704} -// Look for an array of the old dyld_all_image_infos style of binary infos -// at the image_list_address. -// This an array of {void* load_addr, void* mod_date, void* pathname} -// -// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true} -// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to -// get a list of all the -// libraries loaded -// -// jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]} -// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to -// get the information -// about the libraries loaded at these addresses. -// -rnb_err_t -RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) { - nub_process_t pid; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E83"); - } - - pid = m_ctx.ProcessID(); - - const char get_loaded_dynamic_libraries_infos_str[] = { - "jGetLoadedDynamicLibrariesInfos:{"}; - if (strncmp(p, get_loaded_dynamic_libraries_infos_str, - sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) { - p += strlen(get_loaded_dynamic_libraries_infos_str); - - JSONGenerator::ObjectSP json_sp; - - std::vector<uint64_t> macho_addresses; - bool fetch_all_solibs = false; - if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p, - fetch_all_solibs) && - fetch_all_solibs) { - json_sp = DNBGetAllLoadedLibrariesInfos(pid); - } else if (get_array_of_ints_value_for_key_name_from_json( - "solib_addresses", p, macho_addresses)) { - json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses); - } else { - nub_addr_t image_list_address = - get_integer_value_for_key_name_from_json("image_list_address", p); - nub_addr_t image_count = - get_integer_value_for_key_name_from_json("image_count", p); - - if (image_list_address != INVALID_NUB_ADDRESS && - image_count != INVALID_NUB_ADDRESS) { - json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address, - image_count); - } - } - - if (json_sp.get()) { - std::ostringstream json_str; - json_sp->Dump(json_str); - if (json_str.str().size() > 0) { - std::string json_str_quoted = binary_encode_string(json_str.str()); - return SendPacket(json_str_quoted.c_str()); - } else { - SendPacket("E84"); - } - } - } - return SendPacket("OK"); -} - -// This packet does not currently take any arguments. So the behavior is -// jGetSharedCacheInfo:{} -// send information about the inferior's shared cache -// jGetSharedCacheInfo: -// send "OK" to indicate that this packet is supported -rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) { - nub_process_t pid; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) { - return SendPacket("E85"); - } - - pid = m_ctx.ProcessID(); - - const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"}; - if (strncmp(p, get_shared_cache_info_str, - sizeof(get_shared_cache_info_str) - 1) == 0) { - JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid); - - if (json_sp.get()) { - std::ostringstream json_str; - json_sp->Dump(json_str); - if (json_str.str().size() > 0) { - std::string json_str_quoted = binary_encode_string(json_str.str()); - return SendPacket(json_str_quoted.c_str()); - } else { - SendPacket("E86"); - } - } - } - return SendPacket("OK"); -} - -static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size, - nub_addr_t mach_header_addr, - mach_header &mh) { - DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, " - "addr_size = %u, mach_header_addr = " - "0x%16.16llx)", - pid, addr_size, mach_header_addr); - const nub_size_t bytes_read = - DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh); - if (bytes_read == sizeof(mh)) { - DNBLogThreadedIf( - LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = " - "%u, mach_header_addr = 0x%16.16llx): mh = {\n magic = " - "0x%8.8x\n cpu = 0x%8.8x\n sub = 0x%8.8x\n filetype = " - "%u\n ncmds = %u\n sizeofcmds = 0x%8.8x\n flags = " - "0x%8.8x }", - pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype, - mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags); - if ((addr_size == 4 && mh.magic == MH_MAGIC) || - (addr_size == 8 && mh.magic == MH_MAGIC_64)) { - if (mh.filetype == MH_EXECUTE) { - DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = " - "%u, addr_size = %u, mach_header_addr = " - "0x%16.16llx) -> this is the " - "executable!!!", - pid, addr_size, mach_header_addr); - return true; - } - } - } - return false; -} - -static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid, - const uint32_t addr_size, - mach_header &mh) { - struct AllImageInfos { - uint32_t version; - uint32_t dylib_info_count; - uint64_t dylib_info_addr; - }; - - uint64_t mach_header_addr = 0; - - const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid); - uint8_t bytes[256]; - nub_size_t bytes_read = 0; - DNBDataRef data(bytes, sizeof(bytes), false); - DNBDataRef::offset_t offset = 0; - data.SetPointerSize(addr_size); - - //---------------------------------------------------------------------- - // When we are sitting at __dyld_start, the kernel has placed the - // address of the mach header of the main executable on the stack. If we - // read the SP and dereference a pointer, we might find the mach header - // for the executable. We also just make sure there is only 1 thread - // since if we are at __dyld_start we shouldn't have multiple threads. - //---------------------------------------------------------------------- - if (DNBProcessGetNumThreads(pid) == 1) { - nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0); - if (tid != INVALID_NUB_THREAD) { - DNBRegisterValue sp_value; - if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, - GENERIC_REGNUM_SP, &sp_value)) { - uint64_t sp = - addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32; - bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes); - if (bytes_read == addr_size) { - offset = 0; - mach_header_addr = data.GetPointer(&offset); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) - return mach_header_addr; - } - } - } - } - - //---------------------------------------------------------------------- - // Check the dyld_all_image_info structure for a list of mach header - // since it is a very easy thing to check - //---------------------------------------------------------------------- - if (shlib_addr != INVALID_NUB_ADDRESS) { - bytes_read = - DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes); - if (bytes_read > 0) { - AllImageInfos aii; - offset = 0; - aii.version = data.Get32(&offset); - aii.dylib_info_count = data.Get32(&offset); - if (aii.dylib_info_count > 0) { - aii.dylib_info_addr = data.GetPointer(&offset); - if (aii.dylib_info_addr != 0) { - const size_t image_info_byte_size = 3 * addr_size; - for (uint32_t i = 0; i < aii.dylib_info_count; ++i) { - bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + - i * image_info_byte_size, - image_info_byte_size, bytes); - if (bytes_read != image_info_byte_size) - break; - offset = 0; - mach_header_addr = data.GetPointer(&offset); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, - mh)) - return mach_header_addr; - } - } - } - } - } - - //---------------------------------------------------------------------- - // We failed to find the executable's mach header from the all image - // infos and by dereferencing the stack pointer. Now we fall back to - // enumerating the memory regions and looking for regions that are - // executable. - //---------------------------------------------------------------------- - DNBRegionInfo region_info; - mach_header_addr = 0; - while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, ®ion_info)) { - if (region_info.size == 0) - break; - - if (region_info.permissions & eMemoryPermissionsExecutable) { - DNBLogThreadedIf( - LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: " - "checking region for executable mach header", - region_info.addr, region_info.addr + region_info.size, - (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', - (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', - (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) - return mach_header_addr; - } else { - DNBLogThreadedIf( - LOG_RNB_PROC, - "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region", - region_info.addr, region_info.addr + region_info.size, - (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', - (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', - (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); - } - // Set the address to the next mapped region - mach_header_addr = region_info.addr + region_info.size; - } - bzero(&mh, sizeof(mh)); - return INVALID_NUB_ADDRESS; -} - -rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) { - const char *p = command; - p += strlen("qSymbol:"); - const char *sep = strchr(p, ':'); - - std::string symbol_name; - std::string symbol_value_str; - // Extract the symbol value if there is one - if (sep > p) - symbol_value_str.assign(p, sep - p); - p = sep + 1; - - if (*p) { - // We have a symbol name - symbol_name = decode_hex_ascii_string(p); - if (!symbol_value_str.empty()) { - nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16); - if (symbol_name == "dispatch_queue_offsets") - m_dispatch_queue_offsets_addr = symbol_value; - } - ++m_qSymbol_index; - } else { - // No symbol name, set our symbol index to zero so we can - // read any symbols that we need - m_qSymbol_index = 0; - } - - symbol_name.clear(); - - if (m_qSymbol_index == 0) { - if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS) - symbol_name = "dispatch_queue_offsets"; - else - ++m_qSymbol_index; - } - - // // Lookup next symbol when we have one... - // if (m_qSymbol_index == 1) - // { - // } - - if (symbol_name.empty()) { - // Done with symbol lookups - return SendPacket("OK"); - } else { - std::ostringstream reply; - reply << "qSymbol:"; - for (size_t i = 0; i < symbol_name.size(); ++i) - reply << RAWHEX8(symbol_name[i]); - return SendPacket(reply.str().c_str()); - } -} - -// Note that all numeric values returned by qProcessInfo are hex encoded, -// including the pid and the cpu type. - -rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) { - nub_process_t pid; - std::ostringstream rep; - - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) - return SendPacket("E68"); - - pid = m_ctx.ProcessID(); - - rep << "pid:" << std::hex << pid << ';'; - - int procpid_mib[4]; - procpid_mib[0] = CTL_KERN; - procpid_mib[1] = KERN_PROC; - procpid_mib[2] = KERN_PROC_PID; - procpid_mib[3] = pid; - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size = sizeof(struct kinfo_proc); - - if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { - if (proc_kinfo_size > 0) { - rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';'; - rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid - << ';'; - rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid - << ';'; - rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid - << ';'; - if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) - rep << "effective-gid:" << std::hex - << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';'; - } - } - - cpu_type_t cputype = DNBProcessGetCPUType(pid); - if (cputype == 0) { - DNBLog("Unable to get the process cpu_type, making a best guess."); - cputype = best_guess_cpu_type(); - } - - uint32_t addr_size = 0; - if (cputype != 0) { - rep << "cputype:" << std::hex << cputype << ";"; - if (cputype & CPU_ARCH_ABI64) - addr_size = 8; - else - addr_size = 4; - } - - bool host_cpu_is_64bit = false; - uint32_t is64bit_capable; - size_t is64bit_capable_len = sizeof(is64bit_capable); - if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, - &is64bit_capable_len, NULL, 0) == 0) - host_cpu_is_64bit = is64bit_capable != 0; - - uint32_t cpusubtype; - size_t cpusubtype_len = sizeof(cpusubtype); - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == - 0) { - // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected - // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the - // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu - // subtype - // for i386... - if (host_cpu_is_64bit) { - if (cputype == CPU_TYPE_X86) { - cpusubtype = 3; // CPU_SUBTYPE_I386_ALL - } else if (cputype == CPU_TYPE_ARM) { - // We can query a process' cputype but we cannot query a process' - // cpusubtype. - // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit - // process) and we - // need to override the host cpusubtype (which is in the - // CPU_SUBTYPE_ARM64 subtype namespace) - // with a reasonable CPU_SUBTYPE_ARMV7 subtype. - cpusubtype = 12; // CPU_SUBTYPE_ARM_V7K - } - } - rep << "cpusubtype:" << std::hex << cpusubtype << ';'; - } - - bool os_handled = false; - if (addr_size > 0) { - rep << "ptrsize:" << std::dec << addr_size << ';'; - -#if (defined(__x86_64__) || defined(__i386__)) - // Try and get the OS type by looking at the load commands in the main - // executable and looking for a LC_VERSION_MIN load command. This is the - // most reliable way to determine the "ostype" value when on desktop. - - mach_header mh; - nub_addr_t exe_mach_header_addr = - GetMachHeaderForMainExecutable(pid, addr_size, mh); - if (exe_mach_header_addr != INVALID_NUB_ADDRESS) { - uint64_t load_command_addr = - exe_mach_header_addr + - ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header)); - load_command lc; - for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) { - const nub_size_t bytes_read = - DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc); - (void)bytes_read; - - uint32_t major_version, minor_version, patch_version; - auto *platform = DNBGetDeploymentInfo(pid, lc, load_command_addr, - major_version, minor_version, - patch_version); - if (platform) { - os_handled = true; - rep << "ostype:" << platform << ";"; - break; - } - load_command_addr = load_command_addr + lc.cmdsize; - } - } -#endif // when compiling this on x86 targets - } - - // If we weren't able to find the OS in a LC_VERSION_MIN load command, try - // to set it correctly by using the cpu type and other tricks - if (!os_handled) { - // The OS in the triple should be "ios" or "macosx" which doesn't match our - // "Darwin" which gets returned from "kern.ostype", so we need to hardcode - // this for now. - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) { -#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 - rep << "ostype:tvos;"; -#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - rep << "ostype:watchos;"; -#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 - rep << "ostype:bridgeos;"; -#else - rep << "ostype:ios;"; -#endif - } else { - bool is_ios_simulator = false; - if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) { - // Check for iOS simulator binaries by getting the process argument - // and environment and checking for SIMULATOR_UDID in the environment - int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid}; - - uint8_t arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) == - 0) { - DNBDataRef data(arg_data, arg_data_size, false); - DNBDataRef::offset_t offset = 0; - uint32_t argc = data.Get32(&offset); - const char *cstr; - - cstr = data.GetCStr(&offset); - if (cstr) { - // Skip NULLs - while (1) { - const char *p = data.PeekCStr(offset); - if ((p == NULL) || (*p != '\0')) - break; - ++offset; - } - // Now skip all arguments - for (uint32_t i = 0; i < argc; ++i) { - data.GetCStr(&offset); - } - - // Now iterate across all environment variables - while ((cstr = data.GetCStr(&offset))) { - if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == - 0) { - is_ios_simulator = true; - break; - } - if (cstr[0] == '\0') - break; - } - } - } - } - if (is_ios_simulator) { -#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 - rep << "ostype:tvos;"; -#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - rep << "ostype:watchos;"; -#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 - rep << "ostype:bridgeos;"; -#else - rep << "ostype:ios;"; -#endif - } else { - rep << "ostype:macosx;"; - } - } - } - - rep << "vendor:apple;"; - -#if defined(__LITTLE_ENDIAN__) - rep << "endian:little;"; -#elif defined(__BIG_ENDIAN__) - rep << "endian:big;"; -#elif defined(__PDP_ENDIAN__) - rep << "endian:pdp;"; -#endif - - if (addr_size == 0) { -#if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE) - nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid); - kern_return_t kr; - x86_thread_state_t gp_regs; - mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; - kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE, - (thread_state_t)&gp_regs, &gp_count); - if (kr == KERN_SUCCESS) { - if (gp_regs.tsh.flavor == x86_THREAD_STATE64) - rep << "ptrsize:8;"; - else - rep << "ptrsize:4;"; - } -#elif defined(__arm__) - rep << "ptrsize:4;"; -#elif (defined(__arm64__) || defined(__aarch64__)) && \ - defined(ARM_UNIFIED_THREAD_STATE) - nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid); - kern_return_t kr; - arm_unified_thread_state_t gp_regs; - mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT; - kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE, - (thread_state_t)&gp_regs, &gp_count); - if (kr == KERN_SUCCESS) { - if (gp_regs.ash.flavor == ARM_THREAD_STATE64) - rep << "ptrsize:8;"; - else - rep << "ptrsize:4;"; - } -#endif - } - - return SendPacket(rep.str()); -} - -const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() { - if (!m_dispatch_queue_offsets.IsValid() && - m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS && - m_ctx.HasValidProcessID()) { - nub_process_t pid = m_ctx.ProcessID(); - nub_size_t bytes_read = DNBProcessMemoryRead( - pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets), - &m_dispatch_queue_offsets); - if (bytes_read != sizeof(m_dispatch_queue_offsets)) - m_dispatch_queue_offsets.Clear(); - } - - if (m_dispatch_queue_offsets.IsValid()) - return &m_dispatch_queue_offsets; - else - return nullptr; -} - -void RNBRemote::EnableCompressionNextSendPacket(compression_types type) { - m_compression_mode = type; - m_enable_compression_next_send_packet = true; -} - -compression_types RNBRemote::GetCompressionType() { - // The first packet we send back to the debugger after a QEnableCompression - // request - // should be uncompressed -- so we can indicate whether the compression was - // enabled - // or not via OK / Enn returns. After that, all packets sent will be using - // the - // compression protocol. - - if (m_enable_compression_next_send_packet) { - // One time, we send back "None" as our compression type - m_enable_compression_next_send_packet = false; - return compression_types::none; - } - return m_compression_mode; -} diff --git a/tools/debugserver/source/RNBRemote.h b/tools/debugserver/source/RNBRemote.h deleted file mode 100644 index 0c9c9856308a..000000000000 --- a/tools/debugserver/source/RNBRemote.h +++ /dev/null @@ -1,433 +0,0 @@ - -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __RNBRemote_h__ -#define __RNBRemote_h__ - -#include "DNB.h" -#include "PThreadMutex.h" -#include "RNBContext.h" -#include "RNBDefs.h" -#include "RNBSocket.h" -#include <deque> -#include <map> -#include <string> -#include <vector> - -class RNBSocket; -class RNBContext; -class PThreadEvents; - -enum event_loop_mode { debug_nub, gdb_remote_protocol, done }; - -enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none }; - -class RNBRemote { -public: - typedef enum { - invalid_packet = 0, - ack, // '+' - nack, // '-' - halt, // ^C (async halt) - use_extended_mode, // '!' - why_halted, // '?' - set_argv, // 'A' - set_bp, // 'B' - cont, // 'c' - continue_with_sig, // 'C' - detach, // 'D' - read_general_regs, // 'g' - write_general_regs, // 'G' - set_thread, // 'H' - step_inferior_one_cycle, // 'i' - signal_and_step_inf_one_cycle, // 'I' - kill, // 'k' - read_memory, // 'm' - write_memory, // 'M' - read_register, // 'p' - write_register, // 'P' - restart, // 'R' - single_step, // 's' - single_step_with_sig, // 'S' - search_mem_backwards, // 't' - thread_alive_p, // 'T' - vattach, // 'vAttach;pid' - vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded - // process name ASCII bytes - vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded - // process name ASCII bytes - vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded - // process name ASCII bytes - vcont, // 'vCont' - vcont_list_actions, // 'vCont?' - read_data_from_memory, // 'x' - write_data_to_memory, // 'X' - insert_mem_bp, // 'Z0' - remove_mem_bp, // 'z0' - insert_hardware_bp, // 'Z1' - remove_hardware_bp, // 'z1' - insert_write_watch_bp, // 'Z2' - remove_write_watch_bp, // 'z2' - insert_read_watch_bp, // 'Z3' - remove_read_watch_bp, // 'z3' - insert_access_watch_bp, // 'Z4' - remove_access_watch_bp, // 'z4' - - query_monitor, // 'qRcmd' - query_current_thread_id, // 'qC' - query_get_pid, // 'qGetPid' - query_echo, // 'qEcho' - query_thread_ids_first, // 'qfThreadInfo' - query_thread_ids_subsequent, // 'qsThreadInfo' - query_thread_extra_info, // 'qThreadExtraInfo' - query_thread_stop_info, // 'qThreadStopInfo' - query_image_offsets, // 'qOffsets' - query_symbol_lookup, // 'qSymbol' - query_launch_success, // 'qLaunchSuccess' - query_register_info, // 'qRegisterInfo' - query_shlib_notify_info_addr, // 'qShlibInfoAddr' - query_step_packet_supported, // 'qStepPacketSupported' - query_supported_features, // 'qSupported' - query_vattachorwait_supported, // 'qVAttachOrWaitSupported' - query_sync_thread_state_supported, // 'QSyncThreadState' - query_host_info, // 'qHostInfo' - query_gdb_server_version, // 'qGDBServerVersion' - query_process_info, // 'qProcessInfo' - json_query_thread_extended_info, // 'jThreadExtendedInfo' - json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos' - json_query_threads_info, // 'jThreadsInfo' - json_query_get_shared_cache_info, // 'jGetSharedCacheInfo' - pass_signals_to_inferior, // 'QPassSignals' - start_noack_mode, // 'QStartNoAckMode' - prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID - set_logging_mode, // 'QSetLogging:' - set_max_packet_size, // 'QSetMaxPacketSize:' - set_max_payload_size, // 'QSetMaxPayloadSize:' - set_environment_variable, // 'QEnvironment:' - set_environment_variable_hex, // 'QEnvironmentHexEncoded:' - set_launch_arch, // 'QLaunchArch:' - set_disable_aslr, // 'QSetDisableASLR:' - set_stdin, // 'QSetSTDIN:' - set_stdout, // 'QSetSTDOUT:' - set_stderr, // 'QSetSTDERR:' - set_working_dir, // 'QSetWorkingDir:' - set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:' - sync_thread_state, // 'QSyncThreadState:' - memory_region_info, // 'qMemoryRegionInfo:' - get_profile_data, // 'qGetProfileData' - set_enable_profiling, // 'QSetEnableAsyncProfiling' - enable_compression, // 'QEnableCompression:' - watchpoint_support_info, // 'qWatchpointSupportInfo:' - allocate_memory, // '_M' - deallocate_memory, // '_m' - set_process_event, // 'QSetProcessEvent:' - save_register_state, // '_g' - restore_register_state, // '_G' - speed_test, // 'qSpeedTest:' - set_detach_on_error, // 'QSetDetachOnError:' - query_transfer, // 'qXfer:' - query_supported_async_json_packets, // 'QSupportedAsyncJSONPackets' - configure_darwin_log, // 'ConfigureDarwinLog:' - unknown_type - } PacketEnum; - - typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p); - - RNBRemote(); - ~RNBRemote(); - - void Initialize(); - - bool InitializeRegisters(bool force = false); - - rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL); - rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL); - - nub_thread_t GetContinueThread() const { return m_continue_thread; } - - void SetContinueThread(nub_thread_t tid) { m_continue_thread = tid; } - - nub_thread_t GetCurrentThread() const { - if (m_thread == 0 || m_thread == (nub_thread_t)-1) - return DNBProcessGetCurrentThread(m_ctx.ProcessID()); - return m_thread; - } - - void SetCurrentThread(nub_thread_t tid) { - DNBProcessSetCurrentThread(m_ctx.ProcessID(), tid); - m_thread = tid; - } - - static void *ThreadFunctionReadRemoteData(void *arg); - void StartReadRemoteDataThread(); - void StopReadRemoteDataThread(); - - void NotifyThatProcessStopped(void); - - rnb_err_t HandlePacket_A(const char *p); - rnb_err_t HandlePacket_H(const char *p); - rnb_err_t HandlePacket_qC(const char *p); - rnb_err_t HandlePacket_qRcmd(const char *p); - rnb_err_t HandlePacket_qGetPid(const char *p); - rnb_err_t HandlePacket_qEcho(const char *p); - rnb_err_t HandlePacket_qLaunchSuccess(const char *p); - rnb_err_t HandlePacket_qRegisterInfo(const char *p); - rnb_err_t HandlePacket_qShlibInfoAddr(const char *p); - rnb_err_t HandlePacket_qStepPacketSupported(const char *p); - rnb_err_t HandlePacket_qVAttachOrWaitSupported(const char *p); - rnb_err_t HandlePacket_qSyncThreadStateSupported(const char *p); - rnb_err_t HandlePacket_qThreadInfo(const char *p); - rnb_err_t HandlePacket_jThreadExtendedInfo(const char *p); - rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p); - rnb_err_t HandlePacket_jThreadsInfo(const char *p); - rnb_err_t HandlePacket_jGetSharedCacheInfo(const char *p); - rnb_err_t HandlePacket_qThreadExtraInfo(const char *p); - rnb_err_t HandlePacket_qThreadStopInfo(const char *p); - rnb_err_t HandlePacket_qHostInfo(const char *p); - rnb_err_t HandlePacket_qGDBServerVersion(const char *p); - rnb_err_t HandlePacket_qProcessInfo(const char *p); - rnb_err_t HandlePacket_qSymbol(const char *p); - rnb_err_t HandlePacket_QStartNoAckMode(const char *p); - rnb_err_t HandlePacket_QThreadSuffixSupported(const char *p); - rnb_err_t HandlePacket_QSetLogging(const char *p); - rnb_err_t HandlePacket_QSetDisableASLR(const char *p); - rnb_err_t HandlePacket_QSetSTDIO(const char *p); - rnb_err_t HandlePacket_QSetWorkingDir(const char *p); - rnb_err_t HandlePacket_QSetMaxPayloadSize(const char *p); - rnb_err_t HandlePacket_QSetMaxPacketSize(const char *p); - rnb_err_t HandlePacket_QEnvironment(const char *p); - rnb_err_t HandlePacket_QEnvironmentHexEncoded(const char *p); - rnb_err_t HandlePacket_QLaunchArch(const char *p); - rnb_err_t HandlePacket_QListThreadsInStopReply(const char *p); - rnb_err_t HandlePacket_QSyncThreadState(const char *p); - rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID(const char *p); - rnb_err_t HandlePacket_QSetProcessEvent(const char *p); - rnb_err_t HandlePacket_last_signal(const char *p); - rnb_err_t HandlePacket_m(const char *p); - rnb_err_t HandlePacket_M(const char *p); - rnb_err_t HandlePacket_x(const char *p); - rnb_err_t HandlePacket_X(const char *p); - rnb_err_t HandlePacket_g(const char *p); - rnb_err_t HandlePacket_G(const char *p); - rnb_err_t HandlePacket_z(const char *p); - rnb_err_t HandlePacket_T(const char *p); - rnb_err_t HandlePacket_p(const char *p); - rnb_err_t HandlePacket_P(const char *p); - rnb_err_t HandlePacket_c(const char *p); - rnb_err_t HandlePacket_C(const char *p); - rnb_err_t HandlePacket_D(const char *p); - rnb_err_t HandlePacket_k(const char *p); - rnb_err_t HandlePacket_s(const char *p); - rnb_err_t HandlePacket_S(const char *p); - rnb_err_t HandlePacket_qSupported(const char *p); - rnb_err_t HandlePacket_v(const char *p); - rnb_err_t HandlePacket_UNIMPLEMENTED(const char *p); - rnb_err_t HandlePacket_ILLFORMED(const char *file, int line, const char *p, - const char *description); - rnb_err_t HandlePacket_AllocateMemory(const char *p); - rnb_err_t HandlePacket_DeallocateMemory(const char *p); - rnb_err_t HandlePacket_SaveRegisterState(const char *p); - rnb_err_t HandlePacket_RestoreRegisterState(const char *p); - rnb_err_t HandlePacket_MemoryRegionInfo(const char *p); - rnb_err_t HandlePacket_GetProfileData(const char *p); - rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p); - rnb_err_t HandlePacket_QEnableCompression(const char *p); - rnb_err_t HandlePacket_WatchpointSupportInfo(const char *p); - rnb_err_t HandlePacket_qSpeedTest(const char *p); - rnb_err_t HandlePacket_qXfer(const char *p); - rnb_err_t HandlePacket_stop_process(const char *p); - rnb_err_t HandlePacket_QSetDetachOnError(const char *p); - rnb_err_t HandlePacket_qStructuredDataPlugins(const char *p); - rnb_err_t HandlePacket_QConfigureDarwinLog(const char *p); - - rnb_err_t SendStopReplyPacketForThread(nub_thread_t tid); - rnb_err_t SendHexEncodedBytePacket(const char *header, const void *buf, - size_t buf_len, const char *footer); - rnb_err_t SendSTDOUTPacket(char *buf, nub_size_t buf_size); - rnb_err_t SendSTDERRPacket(char *buf, nub_size_t buf_size); - void FlushSTDIO(); - void SendAsyncProfileData(); - rnb_err_t SendAsyncProfileDataPacket(char *buf, nub_size_t buf_size); - void SendAsyncDarwinLogData(); - rnb_err_t SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary); - - RNBContext &Context() { return m_ctx; } - RNBSocket &Comm() { return m_comm; } - -private: - // Outlaw some constructors - RNBRemote(const RNBRemote &); - -protected: - rnb_err_t GetCommData(); - void CommDataReceived(const std::string &data); - struct Packet { - typedef std::vector<Packet> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - PacketEnum type; - HandlePacketCallback normal; // Function to call when inferior is halted - HandlePacketCallback async; // Function to call when inferior is running - std::string abbrev; - std::string printable_name; - - bool IsPlatformPacket() const { - switch (type) { - case set_logging_mode: - case query_host_info: - return true; - default: - break; - } - return false; - } - Packet() - : type(invalid_packet), normal(NULL), async(NULL), abbrev(), - printable_name() {} - - Packet(PacketEnum in_type, HandlePacketCallback in_normal, - HandlePacketCallback in_async, const char *in_abbrev, - const char *in_printable_name) - : type(in_type), normal(in_normal), async(in_async), abbrev(in_abbrev), - printable_name(in_printable_name) {} - }; - - struct DispatchQueueOffsets { - uint16_t dqo_version; - uint16_t dqo_label; - uint16_t dqo_label_size; - uint16_t dqo_flags; - uint16_t dqo_flags_size; - uint16_t dqo_serialnum; - uint16_t dqo_serialnum_size; - uint16_t dqo_width; - uint16_t dqo_width_size; - uint16_t dqo_running; - uint16_t dqo_running_size; - uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t - dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - - DispatchQueueOffsets() { Clear(); } - - void Clear() { - dqo_version = UINT16_MAX; - dqo_label = UINT16_MAX; - dqo_label_size = UINT16_MAX; - dqo_flags = UINT16_MAX; - dqo_flags_size = UINT16_MAX; - dqo_serialnum = UINT16_MAX; - dqo_serialnum_size = UINT16_MAX; - dqo_width = UINT16_MAX; - dqo_width_size = UINT16_MAX; - dqo_running = UINT16_MAX; - dqo_running_size = UINT16_MAX; - dqo_suspend_cnt = UINT16_MAX; - dqo_suspend_cnt_size = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_target_queue_size = UINT16_MAX; - dqo_priority = UINT16_MAX; - dqo_priority_size = UINT16_MAX; - } - - bool IsValid() const { return dqo_version != UINT16_MAX; } - - void GetThreadQueueInfo(nub_process_t pid, nub_addr_t dispatch_qaddr, - nub_addr_t &dispatch_queue_t, - std::string &queue_name, uint64_t &queue_width, - uint64_t &queue_serialnum) const; - }; - - rnb_err_t GetPacket(std::string &packet_data, RNBRemote::Packet &packet_info, - bool wait); - rnb_err_t SendPacket(const std::string &); - std::string CompressString(const std::string &); - - void CreatePacketTable(); - rnb_err_t GetPacketPayload(std::string &); - - nub_thread_t ExtractThreadIDFromThreadSuffix(const char *p); - - void EnableCompressionNextSendPacket(compression_types); - - compression_types GetCompressionType(); - - const DispatchQueueOffsets *GetDispatchQueueOffsets(); - - JSONGenerator::ObjectSP - GetJSONThreadsInfo(bool threads_with_valid_stop_info_only); - - RNBContext m_ctx; // process context - RNBSocket m_comm; // communication port - std::string m_arch; - nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all - nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all - PThreadMutex m_mutex; // Mutex that protects - DispatchQueueOffsets m_dispatch_queue_offsets; - nub_addr_t m_dispatch_queue_offsets_addr; - uint32_t m_qSymbol_index; - uint32_t m_packets_recvd; - Packet::collection m_packets; - std::deque<std::string> m_rx_packets; - std::string m_rx_partial_data; // For packets that may come in more than one - // batch, anything left over can be left here - pthread_t m_rx_pthread; - uint32_t - m_max_payload_size; // the maximum sized payload we should send to gdb - bool m_extended_mode; // are we in extended mode? - bool m_noack_mode; // are we in no-ack mode? - bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' - // packets should be prefixed with the thread - // ID and colon: - // "$pRR;thread:TTTT;" instead of "$pRR" - // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV" - // "$g;thread:TTTT" instead of "$g" - // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV" - bool m_list_threads_in_stop_reply; - - size_t m_compression_minsize; // only packets larger than this size will be - // compressed - bool m_enable_compression_next_send_packet; - - compression_types m_compression_mode; -}; - -/* We translate the /usr/include/mach/exception_types.h exception types - (e.g. EXC_BAD_ACCESS) to the fake BSD signal numbers that gdb uses - in include/gdb/signals.h (e.g. TARGET_EXC_BAD_ACCESS). These hard - coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb - values in its include/gdb/signals.h. */ - -#define TARGET_EXC_BAD_ACCESS 0x91 -#define TARGET_EXC_BAD_INSTRUCTION 0x92 -#define TARGET_EXC_ARITHMETIC 0x93 -#define TARGET_EXC_EMULATION 0x94 -#define TARGET_EXC_SOFTWARE 0x95 -#define TARGET_EXC_BREAKPOINT 0x96 - -/* Generally speaking, you can't assume gdb can receive more than 399 bytes - at a time with a random gdb. This bufsize constant is only specifying - how many bytes gdb can *receive* from debugserver -- it tells us nothing - about how many bytes gdb might try to send in a single packet. */ -#define DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE 399 - -#endif // #ifndef __RNBRemote_h__ diff --git a/tools/debugserver/source/RNBServices.cpp b/tools/debugserver/source/RNBServices.cpp deleted file mode 100644 index 89c4c27da1dd..000000000000 --- a/tools/debugserver/source/RNBServices.cpp +++ /dev/null @@ -1,235 +0,0 @@ -//===-- RNBServices.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Christopher Friesen on 3/21/08. -// -//===----------------------------------------------------------------------===// - -#include "RNBServices.h" - -#include "CFString.h" -#include "DNBLog.h" -#include "MacOSX/CFUtils.h" -#include <CoreFoundation/CoreFoundation.h> -#include <libproc.h> -#include <sys/sysctl.h> -#include <unistd.h> -#include <vector> - -// For now only SpringBoard has a notion of "Applications" that it can list for -// us. -// So we have to use the SpringBoard API's here. -#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) -#include <SpringBoardServices/SpringBoardServices.h> -#endif - -// From DNB.cpp -size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos); - -int GetProcesses(CFMutableArrayRef plistMutableArray, bool all_users) { - if (plistMutableArray == NULL) - return -1; - - // Running as root, get all processes - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = GetAllInfos(proc_infos); - if (num_proc_infos > 0) { - const pid_t our_pid = getpid(); - const uid_t our_uid = getuid(); - uint32_t i; - CFAllocatorRef alloc = kCFAllocatorDefault; - - for (i = 0; i < num_proc_infos; i++) { - struct kinfo_proc &proc_info = proc_infos[i]; - - bool kinfo_user_matches; - // Special case, if lldb is being run as root we can attach to anything. - if (all_users) - kinfo_user_matches = true; - else - kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid; - - const pid_t pid = proc_info.kp_proc.p_pid; - // Skip zombie processes and processes with unset status - if (!kinfo_user_matches || // User is acceptable - pid == our_pid || // Skip this process - pid == 0 || // Skip kernel (kernel pid is zero) - proc_info.kp_proc.p_stat == - SZOMB || // Zombies are bad, they like brains... - proc_info.kp_proc.p_flag & P_TRACED || // Being debugged? - proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting? - proc_info.kp_proc.p_flag & - P_TRANSLATED) // Skip translated ppc (Rosetta) - continue; - - // Create a new mutable dictionary for each application - CFReleaser<CFMutableDictionaryRef> appInfoDict( - ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - // Get the process id for the app (if there is one) - const int32_t pid_int32 = pid; - CFReleaser<CFNumberRef> pidCFNumber( - ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid_int32)); - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY, - pidCFNumber.get()); - - // Set a boolean to indicate if this is the front most - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, - kCFBooleanFalse); - - const char *pid_basename = proc_info.kp_proc.p_comm; - char proc_path_buf[PATH_MAX]; - - int return_val = proc_pidpath(pid, proc_path_buf, PATH_MAX); - if (return_val > 0) { - // Okay, now search backwards from that to see if there is a - // slash in the name. Note, even though we got all the args we don't - // care - // because the list data is just a bunch of concatenated null terminated - // strings - // so strrchr will start from the end of argv0. - - pid_basename = strrchr(proc_path_buf, '/'); - if (pid_basename) { - // Skip the '/' - ++pid_basename; - } else { - // We didn't find a directory delimiter in the process argv[0], just - // use what was in there - pid_basename = proc_path_buf; - } - CFString cf_pid_path(proc_path_buf); - if (cf_pid_path.get()) - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY, - cf_pid_path.get()); - } - - if (pid_basename && pid_basename[0]) { - CFString pid_name(pid_basename); - ::CFDictionarySetValue(appInfoDict.get(), - DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get()); - } - - // Append the application info to the plist array - ::CFArrayAppendValue(plistMutableArray, appInfoDict.get()); - } - } - return 0; -} -int ListApplications(std::string &plist, bool opt_runningApps, - bool opt_debuggable) { - int result = -1; - - CFAllocatorRef alloc = kCFAllocatorDefault; - - // Create a mutable array that we can populate. Specify zero so it can be of - // any size. - CFReleaser<CFMutableArrayRef> plistMutableArray( - ::CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks)); - - const uid_t our_uid = getuid(); - -#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) - - if (our_uid == 0) { - bool all_users = true; - result = GetProcesses(plistMutableArray.get(), all_users); - } else { - CFReleaser<CFStringRef> sbsFrontAppID( - ::SBSCopyFrontmostApplicationDisplayIdentifier()); - CFReleaser<CFArrayRef> sbsAppIDs(::SBSCopyApplicationDisplayIdentifiers( - opt_runningApps, opt_debuggable)); - - // Need to check the return value from SBSCopyApplicationDisplayIdentifiers. - CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount(sbsAppIDs.get()) : 0; - CFIndex i = 0; - for (i = 0; i < count; i++) { - CFStringRef displayIdentifier = - (CFStringRef)::CFArrayGetValueAtIndex(sbsAppIDs.get(), i); - - // Create a new mutable dictionary for each application - CFReleaser<CFMutableDictionaryRef> appInfoDict( - ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - // Get the process id for the app (if there is one) - pid_t pid = INVALID_NUB_PROCESS; - if (::SBSProcessIDForDisplayIdentifier((CFStringRef)displayIdentifier, - &pid) == true) { - CFReleaser<CFNumberRef> pidCFNumber( - ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid)); - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY, - pidCFNumber.get()); - } - - // Set a boolean to indicate if this is the front most - if (sbsFrontAppID.get() && displayIdentifier && - (::CFStringCompare(sbsFrontAppID.get(), displayIdentifier, 0) == - kCFCompareEqualTo)) - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, - kCFBooleanTrue); - else - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, - kCFBooleanFalse); - - CFReleaser<CFStringRef> executablePath( - ::SBSCopyExecutablePathForDisplayIdentifier(displayIdentifier)); - if (executablePath.get() != NULL) { - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY, - executablePath.get()); - } - - CFReleaser<CFStringRef> iconImagePath( - ::SBSCopyIconImagePathForDisplayIdentifier(displayIdentifier)); - if (iconImagePath.get() != NULL) { - ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, - iconImagePath.get()); - } - - CFReleaser<CFStringRef> localizedDisplayName( - ::SBSCopyLocalizedApplicationNameForDisplayIdentifier( - displayIdentifier)); - if (localizedDisplayName.get() != NULL) { - ::CFDictionarySetValue(appInfoDict.get(), - DTSERVICES_APP_DISPLAY_NAME_KEY, - localizedDisplayName.get()); - } - - // Append the application info to the plist array - ::CFArrayAppendValue(plistMutableArray.get(), appInfoDict.get()); - } - } -#else // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) - // When root, show all processes - bool all_users = (our_uid == 0); - GetProcesses(plistMutableArray.get(), all_users); -#endif - - CFReleaser<CFDataRef> plistData( - ::CFPropertyListCreateXMLData(alloc, plistMutableArray.get())); - - // write plist to service port - if (plistData.get() != NULL) { - CFIndex size = ::CFDataGetLength(plistData.get()); - const UInt8 *bytes = ::CFDataGetBytePtr(plistData.get()); - if (bytes != NULL && size > 0) { - plist.assign((const char *)bytes, size); - return 0; // Success - } else { - DNBLogError("empty application property list."); - result = -2; - } - } else { - DNBLogError("serializing task list."); - result = -3; - } - - return result; -} diff --git a/tools/debugserver/source/RNBServices.h b/tools/debugserver/source/RNBServices.h deleted file mode 100644 index caa2b0fd199e..000000000000 --- a/tools/debugserver/source/RNBServices.h +++ /dev/null @@ -1,29 +0,0 @@ -//===-- RNBServices.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Christopher Friesen on 3/21/08. -// -//===----------------------------------------------------------------------===// - -#ifndef __RNBServices_h__ -#define __RNBServices_h__ - -#include "RNBDefs.h" -#include <string> - -#define DTSERVICES_APP_FRONTMOST_KEY CFSTR("isFrontApp") -#define DTSERVICES_APP_PATH_KEY CFSTR("executablePath") -#define DTSERVICES_APP_ICON_PATH_KEY CFSTR("iconPath") -#define DTSERVICES_APP_DISPLAY_NAME_KEY CFSTR("displayName") -#define DTSERVICES_APP_PID_KEY CFSTR("pid") - -int ListApplications(std::string &plist, bool opt_runningApps, - bool opt_debuggable); - -#endif // __RNBServices_h__ diff --git a/tools/debugserver/source/RNBSocket.cpp b/tools/debugserver/source/RNBSocket.cpp deleted file mode 100644 index 88136c210acc..000000000000 --- a/tools/debugserver/source/RNBSocket.cpp +++ /dev/null @@ -1,392 +0,0 @@ -//===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#include "RNBSocket.h" -#include "DNBError.h" -#include "DNBLog.h" -#include <arpa/inet.h> -#include <errno.h> -#include <fcntl.h> -#include <map> -#include <netdb.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/event.h> -#include <termios.h> -#include <vector> - -#include "lldb/Host/SocketAddress.h" - -#ifdef WITH_LOCKDOWN -#include "lockdown.h" -#endif - -/* Once we have a RNBSocket object with a port # specified, - this function is called to wait for an incoming connection. - This function blocks while waiting for that connection. */ - -bool ResolveIPV4HostName(const char *hostname, in_addr_t &addr) { - if (hostname == NULL || hostname[0] == '\0' || - strcmp(hostname, "localhost") == 0 || - strcmp(hostname, "127.0.0.1") == 0) { - addr = htonl(INADDR_LOOPBACK); - return true; - } else if (strcmp(hostname, "*") == 0) { - addr = htonl(INADDR_ANY); - return true; - } else { - // See if an IP address was specified as numbers - int inet_pton_result = ::inet_pton(AF_INET, hostname, &addr); - - if (inet_pton_result == 1) - return true; - - struct hostent *host_entry = gethostbyname(hostname); - if (host_entry) { - std::string ip_str( - ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list)); - inet_pton_result = ::inet_pton(AF_INET, ip_str.c_str(), &addr); - if (inet_pton_result == 1) - return true; - } - } - return false; -} - -rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, - PortBoundCallback callback, - const void *callback_baton) { - // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", - // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); - // Disconnect without saving errno - Disconnect(false); - - DNBError err; - int queue_id = kqueue(); - if (queue_id < 0) { - err.SetError(errno, DNBError::MachKernel); - err.LogThreaded("error: failed to create kqueue."); - return rnb_err; - } - - bool any_addr = (strcmp(listen_host, "*") == 0); - - // If the user wants to allow connections from any address we should create - // sockets on all families that can resolve localhost. This will allow us to - // listen for IPv6 and IPv4 connections from all addresses if those interfaces - // are available. - const char *local_addr = any_addr ? "localhost" : listen_host; - - std::map<int, lldb_private::SocketAddress> sockets; - auto addresses = lldb_private::SocketAddress::GetAddressInfo( - local_addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); - - for (auto address : addresses) { - int sock_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); - if (sock_fd == -1) - continue; - - SetSocketOption(sock_fd, SOL_SOCKET, SO_REUSEADDR, 1); - - lldb_private::SocketAddress bind_address = address; - - if(any_addr || !bind_address.IsLocalhost()) - bind_address.SetToAnyAddress(bind_address.GetFamily(), port); - else - bind_address.SetPort(port); - - int error = - ::bind(sock_fd, &bind_address.sockaddr(), bind_address.GetLength()); - if (error == -1) { - ClosePort(sock_fd, false); - continue; - } - - error = ::listen(sock_fd, 5); - if (error == -1) { - ClosePort(sock_fd, false); - continue; - } - - // We were asked to listen on port zero which means we must now read the - // actual port that was given to us as port zero is a special code for "find - // an open port for me". This will only execute on the first socket created, - // subesquent sockets will reuse this port number. - if (port == 0) { - socklen_t sa_len = address.GetLength(); - if (getsockname(sock_fd, &address.sockaddr(), &sa_len) == 0) - port = address.GetPort(); - } - - sockets[sock_fd] = address; - } - - if (sockets.size() == 0) { - err.SetError(errno, DNBError::POSIX); - err.LogThreaded("::listen or ::bind failed"); - return rnb_err; - } - - if (callback) - callback(callback_baton, port); - - std::vector<struct kevent> events; - events.resize(sockets.size()); - int i = 0; - for (auto socket : sockets) { - EV_SET(&events[i++], socket.first, EVFILT_READ, EV_ADD, 0, 0, 0); - } - - bool accept_connection = false; - - // Loop until we are happy with our connection - while (!accept_connection) { - - struct kevent event_list[4]; - int num_events = - kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); - - if (num_events < 0) { - err.SetError(errno, DNBError::MachKernel); - err.LogThreaded("error: kevent() failed."); - } - - for (int i = 0; i < num_events; ++i) { - auto sock_fd = event_list[i].ident; - auto socket_pair = sockets.find(sock_fd); - if (socket_pair == sockets.end()) - continue; - - lldb_private::SocketAddress &addr_in = socket_pair->second; - lldb_private::SocketAddress accept_addr; - socklen_t sa_len = accept_addr.GetMaxLength(); - m_fd = ::accept(sock_fd, &accept_addr.sockaddr(), &sa_len); - - if (m_fd == -1) { - err.SetError(errno, DNBError::POSIX); - err.LogThreaded("error: Socket accept failed."); - } - - if (addr_in.IsAnyAddr()) - accept_connection = true; - else { - if (accept_addr == addr_in) - accept_connection = true; - else { - ::close(m_fd); - m_fd = -1; - ::fprintf( - stderr, - "error: rejecting incoming connection from %s (expecting %s)\n", - accept_addr.GetIPAddress().c_str(), - addr_in.GetIPAddress().c_str()); - DNBLogThreaded("error: rejecting connection from %s (expecting %s)\n", - accept_addr.GetIPAddress().c_str(), - addr_in.GetIPAddress().c_str()); - err.Clear(); - } - } - } - if (err.Fail()) - break; - } - for (auto socket : sockets) { - int ListenFd = socket.first; - ClosePort(ListenFd, false); - } - - if (err.Fail()) - return rnb_err; - - // Keep our TCP packets coming without any delays. - SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - - return rnb_success; -} - -rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) { - auto result = rnb_err; - Disconnect(false); - - auto addresses = lldb_private::SocketAddress::GetAddressInfo( - host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); - - for (auto address : addresses) { - m_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); - if (m_fd == -1) - continue; - - // Enable local address reuse - SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1); - - address.SetPort(port); - - if (-1 == ::connect(m_fd, &address.sockaddr(), address.GetLength())) { - Disconnect(false); - continue; - } - SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - - result = rnb_success; - break; - } - return result; -} - -rnb_err_t RNBSocket::useFD(int fd) { - if (fd < 0) { - DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); - return rnb_err; - } - - m_fd = fd; - return rnb_success; -} - -#ifdef WITH_LOCKDOWN -rnb_err_t RNBSocket::ConnectToService() { - DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); - // Disconnect from any previous connections - Disconnect(false); - if (::secure_lockdown_checkin(&m_ld_conn, NULL, NULL) != kLDESuccess) { - DNBLogThreadedIf(LOG_RNB_COMM, - "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); - m_fd = -1; - return rnb_not_connected; - } - m_fd = ::lockdown_get_socket(m_ld_conn); - if (m_fd == -1) { - DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); - return rnb_not_connected; - } - m_fd_from_lockdown = true; - return rnb_success; -} -#endif - -rnb_err_t RNBSocket::OpenFile(const char *path) { - DNBError err; - m_fd = open(path, O_RDWR); - if (m_fd == -1) { - err.SetError(errno, DNBError::POSIX); - err.LogThreaded("can't open file '%s'", path); - return rnb_not_connected; - } else { - struct termios stdin_termios; - - if (::tcgetattr(m_fd, &stdin_termios) == 0) { - stdin_termios.c_lflag &= ~ECHO; // Turn off echoing - stdin_termios.c_lflag &= ~ICANON; // Get one char at a time - ::tcsetattr(m_fd, TCSANOW, &stdin_termios); - } - } - return rnb_success; -} - -int RNBSocket::SetSocketOption(int fd, int level, int option_name, - int option_value) { - return ::setsockopt(fd, level, option_name, &option_value, - sizeof(option_value)); -} - -rnb_err_t RNBSocket::Disconnect(bool save_errno) { -#ifdef WITH_LOCKDOWN - if (m_fd_from_lockdown) { - m_fd_from_lockdown = false; - m_fd = -1; - lockdown_disconnect(m_ld_conn); - return rnb_success; - } -#endif - return ClosePort(m_fd, save_errno); -} - -rnb_err_t RNBSocket::Read(std::string &p) { - char buf[1024]; - p.clear(); - - // Note that BUF is on the stack so we must be careful to keep any - // writes to BUF from overflowing or we'll have security issues. - - if (m_fd == -1) - return rnb_err; - - // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", - // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); - DNBError err; - ssize_t bytesread = read(m_fd, buf, sizeof(buf)); - if (bytesread <= 0) - err.SetError(errno, DNBError::POSIX); - else - p.append(buf, bytesread); - - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof(buf), - (uint64_t)bytesread); - - // Our port went away - we have to mark this so IsConnected will return the - // truth. - if (bytesread == 0) { - m_fd = -1; - return rnb_not_connected; - } else if (bytesread == -1) { - m_fd = -1; - return rnb_err; - } - // Strip spaces from the end of the buffer - while (!p.empty() && isspace(p[p.size() - 1])) - p.erase(p.size() - 1); - - // Most data in the debugserver packets valid printable characters... - DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); - return rnb_success; -} - -rnb_err_t RNBSocket::Write(const void *buffer, size_t length) { - if (m_fd == -1) - return rnb_err; - - DNBError err; - ssize_t bytessent = write(m_fd, buffer, length); - if (bytessent < 0) - err.SetError(errno, DNBError::POSIX); - - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", - m_fd, buffer, length, (uint64_t)bytessent); - - if (bytessent < 0) - return rnb_err; - - if ((size_t)bytessent != length) - return rnb_err; - - DNBLogThreadedIf( - LOG_RNB_PACKETS, "putpkt: %*s", (int)length, - (const char *) - buffer); // All data is string based in debugserver, so this is safe - DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, - (const char *)buffer); - - return rnb_success; -} - -rnb_err_t RNBSocket::ClosePort(int &fd, bool save_errno) { - int close_err = 0; - if (fd > 0) { - errno = 0; - close_err = close(fd); - fd = -1; - } - return close_err != 0 ? rnb_err : rnb_success; -} diff --git a/tools/debugserver/source/RNBSocket.h b/tools/debugserver/source/RNBSocket.h deleted file mode 100644 index 9f636d855621..000000000000 --- a/tools/debugserver/source/RNBSocket.h +++ /dev/null @@ -1,79 +0,0 @@ -//===-- RNBSocket.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 12/12/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __RNBSocket_h__ -#define __RNBSocket_h__ - -#include "DNBTimer.h" -#include "RNBDefs.h" -#include <string> -#include <sys/socket.h> -#include <sys/types.h> - -#ifdef WITH_LOCKDOWN -#include "lockdown.h" -#endif - -class RNBSocket { -public: - typedef void (*PortBoundCallback)(const void *baton, uint16_t port); - - RNBSocket() - : m_fd(-1), -#ifdef WITH_LOCKDOWN - m_fd_from_lockdown(false), m_ld_conn(), -#endif - m_timer(true) // Make a thread safe timer - { - } - ~RNBSocket(void) { Disconnect(false); } - - rnb_err_t Listen(const char *listen_host, uint16_t port, - PortBoundCallback callback, const void *callback_baton); - rnb_err_t Connect(const char *host, uint16_t port); - - rnb_err_t useFD(int fd); - -#ifdef WITH_LOCKDOWN - rnb_err_t ConnectToService(); -#endif - rnb_err_t OpenFile(const char *path); - rnb_err_t Disconnect(bool save_errno); - rnb_err_t Read(std::string &p); - rnb_err_t Write(const void *buffer, size_t length); - - bool IsConnected() const { return m_fd != -1; } - void SaveErrno(int curr_errno); - DNBTimer &Timer() { return m_timer; } - - static int SetSocketOption(int fd, int level, int option_name, - int option_value); - -private: - // Outlaw some constructors - RNBSocket(const RNBSocket &); - -protected: - rnb_err_t ClosePort(int &fd, bool save_errno); - - int m_fd; // Socket we use to communicate once conn established - -#ifdef WITH_LOCKDOWN - bool m_fd_from_lockdown; - lockdown_connection m_ld_conn; -#endif - - DNBTimer m_timer; -}; - -#endif // #ifndef __RNBSocket_h__ diff --git a/tools/debugserver/source/StdStringExtractor.cpp b/tools/debugserver/source/StdStringExtractor.cpp deleted file mode 100644 index 3b400b2a89d2..000000000000 --- a/tools/debugserver/source/StdStringExtractor.cpp +++ /dev/null @@ -1,401 +0,0 @@ -//===-- StdStringExtractor.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "StdStringExtractor.h" - -#include <stdlib.h> - - -static inline int xdigit_to_sint(char ch) { - if (ch >= 'a' && ch <= 'f') - return 10 + ch - 'a'; - if (ch >= 'A' && ch <= 'F') - return 10 + ch - 'A'; - if (ch >= '0' && ch <= '9') - return ch - '0'; - return -1; -} - -//---------------------------------------------------------------------- -// StdStringExtractor constructor -//---------------------------------------------------------------------- -StdStringExtractor::StdStringExtractor() : m_packet(), m_index(0) {} - -StdStringExtractor::StdStringExtractor(const char *packet_cstr) - : m_packet(), m_index(0) { - if (packet_cstr) - m_packet.assign(packet_cstr); -} - -//---------------------------------------------------------------------- -// StdStringExtractor copy constructor -//---------------------------------------------------------------------- -StdStringExtractor::StdStringExtractor(const StdStringExtractor &rhs) - : m_packet(rhs.m_packet), m_index(rhs.m_index) {} - -//---------------------------------------------------------------------- -// StdStringExtractor assignment operator -//---------------------------------------------------------------------- -const StdStringExtractor &StdStringExtractor:: -operator=(const StdStringExtractor &rhs) { - if (this != &rhs) { - m_packet = rhs.m_packet; - m_index = rhs.m_index; - } - return *this; -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -StdStringExtractor::~StdStringExtractor() {} - -char StdStringExtractor::GetChar(char fail_value) { - if (m_index < m_packet.size()) { - char ch = m_packet[m_index]; - ++m_index; - return ch; - } - m_index = UINT64_MAX; - return fail_value; -} - -//---------------------------------------------------------------------- -// If a pair of valid hex digits exist at the head of the -// StdStringExtractor they are decoded into an unsigned byte and returned -// by this function -// -// If there is not a pair of valid hex digits at the head of the -// StdStringExtractor, it is left unchanged and -1 is returned -//---------------------------------------------------------------------- -int StdStringExtractor::DecodeHexU8() { - SkipSpaces(); - if (GetBytesLeft() < 2) { - return -1; - } - const int hi_nibble = xdigit_to_sint(m_packet[m_index]); - const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]); - if (hi_nibble == -1 || lo_nibble == -1) { - return -1; - } - m_index += 2; - return (uint8_t)((hi_nibble << 4) + lo_nibble); -} - -//---------------------------------------------------------------------- -// Extract an unsigned character from two hex ASCII chars in the packet -// string, or return fail_value on failure -//---------------------------------------------------------------------- -uint8_t StdStringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) { - // On success, fail_value will be overwritten with the next - // character in the stream - GetHexU8Ex(fail_value, set_eof_on_fail); - return fail_value; -} - -bool StdStringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) { - int byte = DecodeHexU8(); - if (byte == -1) { - if (set_eof_on_fail || m_index >= m_packet.size()) - m_index = UINT64_MAX; - // ch should not be changed in case of failure - return false; - } - ch = (uint8_t)byte; - return true; -} - -uint32_t StdStringExtractor::GetU32(uint32_t fail_value, int base) { - if (m_index < m_packet.size()) { - char *end = nullptr; - const char *start = m_packet.c_str(); - const char *cstr = start + m_index; - uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base)); - - if (end && end != cstr) { - m_index = end - start; - return result; - } - } - return fail_value; -} - -int32_t StdStringExtractor::GetS32(int32_t fail_value, int base) { - if (m_index < m_packet.size()) { - char *end = nullptr; - const char *start = m_packet.c_str(); - const char *cstr = start + m_index; - int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base)); - - if (end && end != cstr) { - m_index = end - start; - return result; - } - } - return fail_value; -} - -uint64_t StdStringExtractor::GetU64(uint64_t fail_value, int base) { - if (m_index < m_packet.size()) { - char *end = nullptr; - const char *start = m_packet.c_str(); - const char *cstr = start + m_index; - uint64_t result = ::strtoull(cstr, &end, base); - - if (end && end != cstr) { - m_index = end - start; - return result; - } - } - return fail_value; -} - -int64_t StdStringExtractor::GetS64(int64_t fail_value, int base) { - if (m_index < m_packet.size()) { - char *end = nullptr; - const char *start = m_packet.c_str(); - const char *cstr = start + m_index; - int64_t result = ::strtoll(cstr, &end, base); - - if (end && end != cstr) { - m_index = end - start; - return result; - } - } - return fail_value; -} - -uint32_t StdStringExtractor::GetHexMaxU32(bool little_endian, - uint32_t fail_value) { - uint32_t result = 0; - uint32_t nibble_count = 0; - - SkipSpaces(); - if (little_endian) { - uint32_t shift_amount = 0; - while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - // Make sure we don't exceed the size of a uint32_t... - if (nibble_count >= (sizeof(uint32_t) * 2)) { - m_index = UINT64_MAX; - return fail_value; - } - - uint8_t nibble_lo; - uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); - ++m_index; - if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - nibble_lo = xdigit_to_sint(m_packet[m_index]); - ++m_index; - result |= ((uint32_t)nibble_hi << (shift_amount + 4)); - result |= ((uint32_t)nibble_lo << shift_amount); - nibble_count += 2; - shift_amount += 8; - } else { - result |= ((uint32_t)nibble_hi << shift_amount); - nibble_count += 1; - shift_amount += 4; - } - } - } else { - while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - // Make sure we don't exceed the size of a uint32_t... - if (nibble_count >= (sizeof(uint32_t) * 2)) { - m_index = UINT64_MAX; - return fail_value; - } - - uint8_t nibble = xdigit_to_sint(m_packet[m_index]); - // Big Endian - result <<= 4; - result |= nibble; - - ++m_index; - ++nibble_count; - } - } - return result; -} - -uint64_t StdStringExtractor::GetHexMaxU64(bool little_endian, - uint64_t fail_value) { - uint64_t result = 0; - uint32_t nibble_count = 0; - - SkipSpaces(); - if (little_endian) { - uint32_t shift_amount = 0; - while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - // Make sure we don't exceed the size of a uint64_t... - if (nibble_count >= (sizeof(uint64_t) * 2)) { - m_index = UINT64_MAX; - return fail_value; - } - - uint8_t nibble_lo; - uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]); - ++m_index; - if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - nibble_lo = xdigit_to_sint(m_packet[m_index]); - ++m_index; - result |= ((uint64_t)nibble_hi << (shift_amount + 4)); - result |= ((uint64_t)nibble_lo << shift_amount); - nibble_count += 2; - shift_amount += 8; - } else { - result |= ((uint64_t)nibble_hi << shift_amount); - nibble_count += 1; - shift_amount += 4; - } - } - } else { - while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) { - // Make sure we don't exceed the size of a uint64_t... - if (nibble_count >= (sizeof(uint64_t) * 2)) { - m_index = UINT64_MAX; - return fail_value; - } - - uint8_t nibble = xdigit_to_sint(m_packet[m_index]); - // Big Endian - result <<= 4; - result |= nibble; - - ++m_index; - ++nibble_count; - } - } - return result; -} - -size_t StdStringExtractor::GetHexBytes(void *dst_void, size_t dst_len, - uint8_t fail_fill_value) { - uint8_t *dst = (uint8_t *)dst_void; - size_t bytes_extracted = 0; - while (bytes_extracted < dst_len && GetBytesLeft()) { - dst[bytes_extracted] = GetHexU8(fail_fill_value); - if (IsGood()) - ++bytes_extracted; - else - break; - } - - for (size_t i = bytes_extracted; i < dst_len; ++i) - dst[i] = fail_fill_value; - - return bytes_extracted; -} - -//---------------------------------------------------------------------- -// Decodes all valid hex encoded bytes at the head of the -// StdStringExtractor, limited by dst_len. -// -// Returns the number of bytes successfully decoded -//---------------------------------------------------------------------- -size_t StdStringExtractor::GetHexBytesAvail(void *dst_void, size_t dst_len) { - uint8_t *dst = (uint8_t *)dst_void; - size_t bytes_extracted = 0; - while (bytes_extracted < dst_len) { - int decode = DecodeHexU8(); - if (decode == -1) { - break; - } - dst[bytes_extracted++] = (uint8_t)decode; - } - return bytes_extracted; -} - -// Consume ASCII hex nibble character pairs until we have decoded byte_size -// bytes of data. - -uint64_t StdStringExtractor::GetHexWithFixedSize(uint32_t byte_size, - bool little_endian, - uint64_t fail_value) { - if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { - uint64_t result = 0; - uint32_t i; - if (little_endian) { - // Little Endian - uint32_t shift_amount; - for (i = 0, shift_amount = 0; i < byte_size && IsGood(); - ++i, shift_amount += 8) { - result |= ((uint64_t)GetHexU8() << shift_amount); - } - } else { - // Big Endian - for (i = 0; i < byte_size && IsGood(); ++i) { - result <<= 8; - result |= GetHexU8(); - } - } - } - m_index = UINT64_MAX; - return fail_value; -} - -size_t StdStringExtractor::GetHexByteString(std::string &str) { - str.clear(); - str.reserve(GetBytesLeft() / 2); - char ch; - while ((ch = GetHexU8()) != '\0') - str.append(1, ch); - return str.size(); -} - -size_t StdStringExtractor::GetHexByteStringFixedLength(std::string &str, - uint32_t nibble_length) { - str.clear(); - - uint32_t nibble_count = 0; - for (const char *pch = Peek(); - (nibble_count < nibble_length) && (pch != nullptr); - str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) { - } - - return str.size(); -} - -size_t StdStringExtractor::GetHexByteStringTerminatedBy(std::string &str, - char terminator) { - str.clear(); - char ch; - while ((ch = GetHexU8(0, false)) != '\0') - str.append(1, ch); - if (Peek() && *Peek() == terminator) - return str.size(); - - str.clear(); - return str.size(); -} - -bool StdStringExtractor::GetNameColonValue(std::string &name, - std::string &value) { - // Read something in the form of NNNN:VVVV; where NNNN is any character - // that is not a colon, followed by a ':' character, then a value (one or - // more ';' chars), followed by a ';' - if (m_index < m_packet.size()) { - const size_t colon_idx = m_packet.find(':', m_index); - if (colon_idx != std::string::npos) { - const size_t semicolon_idx = m_packet.find(';', colon_idx); - if (semicolon_idx != std::string::npos) { - name.assign(m_packet, m_index, colon_idx - m_index); - value.assign(m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1)); - m_index = semicolon_idx + 1; - return true; - } - } - } - m_index = UINT64_MAX; - return false; -} - -void StdStringExtractor::SkipSpaces() { - const size_t n = m_packet.size(); - while (m_index < n && isspace(m_packet[m_index])) - ++m_index; -} diff --git a/tools/debugserver/source/StdStringExtractor.h b/tools/debugserver/source/StdStringExtractor.h deleted file mode 100644 index 40b57cb08fb5..000000000000 --- a/tools/debugserver/source/StdStringExtractor.h +++ /dev/null @@ -1,121 +0,0 @@ -//===-- StdStringExtractor.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef utility_StdStringExtractor_h_ -#define utility_StdStringExtractor_h_ - -#include <stdint.h> -#include <string> - - -// Based on StringExtractor, with the added limitation that this file should not -// take a dependency on LLVM, as it is used from debugserver. -class StdStringExtractor { -public: - enum { BigEndian = 0, LittleEndian = 1 }; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - StdStringExtractor(); - StdStringExtractor(const char *packet_cstr); - StdStringExtractor(const StdStringExtractor &rhs); - virtual ~StdStringExtractor(); - - //------------------------------------------------------------------ - // Operators - //------------------------------------------------------------------ - const StdStringExtractor &operator=(const StdStringExtractor &rhs); - - // Returns true if the file position is still valid for the data - // contained in this string extractor object. - bool IsGood() const { return m_index != UINT64_MAX; } - - uint64_t GetFilePos() const { return m_index; } - - void SetFilePos(uint32_t idx) { m_index = idx; } - - void Clear() { - m_packet.clear(); - m_index = 0; - } - - void SkipSpaces(); - - std::string &GetStringRef() { return m_packet; } - - const std::string &GetStringRef() const { return m_packet; } - - bool Empty() { return m_packet.empty(); } - - size_t GetBytesLeft() { - if (m_index < m_packet.size()) - return m_packet.size() - m_index; - return 0; - } - - char GetChar(char fail_value = '\0'); - - char PeekChar(char fail_value = '\0') { - const char *cstr = Peek(); - if (cstr) - return cstr[0]; - return fail_value; - } - - int DecodeHexU8(); - - uint8_t GetHexU8(uint8_t fail_value = 0, bool set_eof_on_fail = true); - - bool GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail = true); - - bool GetNameColonValue(std::string &name, std::string &value); - - int32_t GetS32(int32_t fail_value, int base = 0); - - uint32_t GetU32(uint32_t fail_value, int base = 0); - - int64_t GetS64(int64_t fail_value, int base = 0); - - uint64_t GetU64(uint64_t fail_value, int base = 0); - - uint32_t GetHexMaxU32(bool little_endian, uint32_t fail_value); - - uint64_t GetHexMaxU64(bool little_endian, uint64_t fail_value); - - size_t GetHexBytes(void *dst, size_t dst_len, uint8_t fail_fill_value); - - size_t GetHexBytesAvail(void *dst, size_t dst_len); - - uint64_t GetHexWithFixedSize(uint32_t byte_size, bool little_endian, - uint64_t fail_value); - - size_t GetHexByteString(std::string &str); - - size_t GetHexByteStringFixedLength(std::string &str, uint32_t nibble_length); - - size_t GetHexByteStringTerminatedBy(std::string &str, char terminator); - - const char *Peek() { - if (m_index < m_packet.size()) - return m_packet.c_str() + m_index; - return nullptr; - } - -protected: - //------------------------------------------------------------------ - // For StdStringExtractor only - //------------------------------------------------------------------ - std::string m_packet; // The string in which to extract data. - uint64_t m_index; // When extracting data from a packet, this index - // will march along as things get extracted. If set - // to UINT64_MAX the end of the packet data was - // reached when decoding information -}; - -#endif // utility_StringExtractor_h_ diff --git a/tools/debugserver/source/SysSignal.cpp b/tools/debugserver/source/SysSignal.cpp deleted file mode 100644 index c2995f362c03..000000000000 --- a/tools/debugserver/source/SysSignal.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//===-- SysSignal.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#include "SysSignal.h" -#include <signal.h> -#include <stddef.h> - -const char *SysSignal::Name(int signal) { - switch (signal) { - case SIGHUP: - return "SIGHUP"; // 1 hangup - case SIGINT: - return "SIGINT"; // 2 interrupt - case SIGQUIT: - return "SIGQUIT"; // 3 quit - case SIGILL: - return "SIGILL"; // 4 illegal instruction (not reset when caught) - case SIGTRAP: - return "SIGTRAP"; // 5 trace trap (not reset when caught) - case SIGABRT: - return "SIGABRT"; // 6 abort() -#if defined(_POSIX_C_SOURCE) - case SIGPOLL: - return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) -#else // !_POSIX_C_SOURCE - case SIGEMT: - return "SIGEMT"; // 7 EMT instruction -#endif // !_POSIX_C_SOURCE - case SIGFPE: - return "SIGFPE"; // 8 floating point exception - case SIGKILL: - return "SIGKILL"; // 9 kill (cannot be caught or ignored) - case SIGBUS: - return "SIGBUS"; // 10 bus error - case SIGSEGV: - return "SIGSEGV"; // 11 segmentation violation - case SIGSYS: - return "SIGSYS"; // 12 bad argument to system call - case SIGPIPE: - return "SIGPIPE"; // 13 write on a pipe with no one to read it - case SIGALRM: - return "SIGALRM"; // 14 alarm clock - case SIGTERM: - return "SIGTERM"; // 15 software termination signal from kill - case SIGURG: - return "SIGURG"; // 16 urgent condition on IO channel - case SIGSTOP: - return "SIGSTOP"; // 17 sendable stop signal not from tty - case SIGTSTP: - return "SIGTSTP"; // 18 stop signal from tty - case SIGCONT: - return "SIGCONT"; // 19 continue a stopped process - case SIGCHLD: - return "SIGCHLD"; // 20 to parent on child stop or exit - case SIGTTIN: - return "SIGTTIN"; // 21 to readers pgrp upon background tty read - case SIGTTOU: - return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) -#if !defined(_POSIX_C_SOURCE) - case SIGIO: - return "SIGIO"; // 23 input/output possible signal -#endif - case SIGXCPU: - return "SIGXCPU"; // 24 exceeded CPU time limit - case SIGXFSZ: - return "SIGXFSZ"; // 25 exceeded file size limit - case SIGVTALRM: - return "SIGVTALRM"; // 26 virtual time alarm - case SIGPROF: - return "SIGPROF"; // 27 profiling time alarm -#if !defined(_POSIX_C_SOURCE) - case SIGWINCH: - return "SIGWINCH"; // 28 window size changes - case SIGINFO: - return "SIGINFO"; // 29 information request -#endif - case SIGUSR1: - return "SIGUSR1"; // 30 user defined signal 1 - case SIGUSR2: - return "SIGUSR2"; // 31 user defined signal 2 - default: - break; - } - return NULL; -} diff --git a/tools/debugserver/source/SysSignal.h b/tools/debugserver/source/SysSignal.h deleted file mode 100644 index c9827126c18b..000000000000 --- a/tools/debugserver/source/SysSignal.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- SysSignal.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/18/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __SysSignal_h__ -#define __SysSignal_h__ - -class SysSignal { -public: - static const char *Name(int signal); -}; - -#endif diff --git a/tools/debugserver/source/TTYState.cpp b/tools/debugserver/source/TTYState.cpp deleted file mode 100644 index 5f10050fcdde..000000000000 --- a/tools/debugserver/source/TTYState.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===-- TTYState.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/26/07. -// -//===----------------------------------------------------------------------===// - -#include "TTYState.h" -#include <fcntl.h> -#include <sys/signal.h> -#include <unistd.h> - -TTYState::TTYState() - : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {} - -TTYState::~TTYState() {} - -bool TTYState::GetTTYState(int fd, bool saveProcessGroup) { - if (fd >= 0 && ::isatty(fd)) { - m_fd = fd; - m_tflags = fcntl(fd, F_GETFL, 0); - m_ttystateErr = tcgetattr(fd, &m_ttystate); - if (saveProcessGroup) - m_processGroup = tcgetpgrp(0); - else - m_processGroup = -1; - } else { - m_fd = -1; - m_tflags = -1; - m_ttystateErr = -1; - m_processGroup = -1; - } - return m_ttystateErr == 0; -} - -bool TTYState::SetTTYState() const { - int result = 0; - if (IsValid()) { - if (TFlagsValid()) - result = fcntl(m_fd, F_SETFL, m_tflags); - - if (TTYStateValid()) - result = tcsetattr(m_fd, TCSANOW, &m_ttystate); - - if (ProcessGroupValid()) { - // Save the original signal handler. - void (*saved_sigttou_callback)(int) = NULL; - saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); - // Set the process group - result = tcsetpgrp(m_fd, m_processGroup); - // Restore the original signal handler. - signal(SIGTTOU, saved_sigttou_callback); - } - return true; - } - return false; -} - -TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {} - -TTYStateSwitcher::~TTYStateSwitcher() {} - -bool TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) { - if (ValidStateIndex(idx)) - return m_ttystates[idx].GetTTYState(fd, saveProcessGroup); - return false; -} - -bool TTYStateSwitcher::SetState(uint32_t idx) const { - if (!ValidStateIndex(idx)) - return false; - - // See if we already are in this state? - if (ValidStateIndex(m_currentState) && (idx == m_currentState) && - m_ttystates[idx].IsValid()) - return true; - - // Set the state to match the index passed in and only update the - // current state if there are no errors. - if (m_ttystates[idx].SetTTYState()) { - m_currentState = idx; - return true; - } - - // We failed to set the state. The tty state was invalid or not - // initialized. - return false; -} diff --git a/tools/debugserver/source/TTYState.h b/tools/debugserver/source/TTYState.h deleted file mode 100644 index 88b6d3c2462e..000000000000 --- a/tools/debugserver/source/TTYState.h +++ /dev/null @@ -1,59 +0,0 @@ -//===-- TTYState.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 3/26/07. -// -//===----------------------------------------------------------------------===// - -#ifndef __TTYState_h__ -#define __TTYState_h__ - -#include <stdint.h> -#include <termios.h> - -class TTYState { -public: - TTYState(); - ~TTYState(); - - bool GetTTYState(int fd, bool saveProcessGroup); - bool SetTTYState() const; - - bool IsValid() const { - return FileDescriptorValid() && TFlagsValid() && TTYStateValid(); - } - bool FileDescriptorValid() const { return m_fd >= 0; } - bool TFlagsValid() const { return m_tflags != -1; } - bool TTYStateValid() const { return m_ttystateErr == 0; } - bool ProcessGroupValid() const { return m_processGroup != -1; } - -protected: - int m_fd; // File descriptor - int m_tflags; - int m_ttystateErr; - struct termios m_ttystate; - pid_t m_processGroup; -}; - -class TTYStateSwitcher { -public: - TTYStateSwitcher(); - ~TTYStateSwitcher(); - - bool GetState(uint32_t idx, int fd, bool saveProcessGroup); - bool SetState(uint32_t idx) const; - uint32_t NumStates() const { return sizeof(m_ttystates) / sizeof(TTYState); } - bool ValidStateIndex(uint32_t idx) const { return idx < NumStates(); } - -protected: - mutable uint32_t m_currentState; - TTYState m_ttystates[2]; -}; - -#endif diff --git a/tools/debugserver/source/com.apple.debugserver.applist.internal.plist b/tools/debugserver/source/com.apple.debugserver.applist.internal.plist deleted file mode 100644 index e9a74bd0bf79..000000000000 --- a/tools/debugserver/source/com.apple.debugserver.applist.internal.plist +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.debugserver.applist.internal</string> - <key>ProgramArguments</key> - <array> - <string>/Developer/usr/bin/debugserver</string> - <string>--lockdown</string> - <string>--applist</string> - </array> - <key>AllowByProxy</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/com.apple.debugserver.applist.plist b/tools/debugserver/source/com.apple.debugserver.applist.plist deleted file mode 100644 index 002e90d98d13..000000000000 --- a/tools/debugserver/source/com.apple.debugserver.applist.plist +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.debugserver.applist</string> - <key>UserName</key> - <string>mobile</string> - <key>ProgramArguments</key> - <array> - <string>/Developer/usr/bin/debugserver</string> - <string>--lockdown</string> - <string>--applist</string> - <string>--launch=frontboard</string> - </array> - <key>AllowByProxy</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/com.apple.debugserver.internal.plist b/tools/debugserver/source/com.apple.debugserver.internal.plist deleted file mode 100644 index b9f57f731232..000000000000 --- a/tools/debugserver/source/com.apple.debugserver.internal.plist +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.debugserver.internal</string> - <key>ProgramArguments</key> - <array> - <string>/Developer/usr/bin/debugserver</string> - <string>--lockdown</string> - </array> - <key>AllowByProxy</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/com.apple.debugserver.plist b/tools/debugserver/source/com.apple.debugserver.plist deleted file mode 100644 index c07466e27cd2..000000000000 --- a/tools/debugserver/source/com.apple.debugserver.plist +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.debugserver</string> - <key>UserName</key> - <string>mobile</string> - <key>ProgramArguments</key> - <array> - <string>/Developer/usr/bin/debugserver</string> - <string>--lockdown</string> - <string>--launch=frontboard</string> - </array> - <key>AllowByProxy</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/com.apple.debugserver.posix.plist b/tools/debugserver/source/com.apple.debugserver.posix.plist deleted file mode 100644 index 4083f8a75c67..000000000000 --- a/tools/debugserver/source/com.apple.debugserver.posix.plist +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.debugserver.posix</string> - <key>UserName</key> - <string>mobile</string> - <key>ProgramArguments</key> - <array> - <string>/Developer/usr/bin/debugserver</string> - <string>--lockdown</string> - <string>--launch=posix</string> - </array> - <key>AllowByProxy</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/com.apple.internal.xpc.remote.debugserver.plist b/tools/debugserver/source/com.apple.internal.xpc.remote.debugserver.plist deleted file mode 100644 index 837ebe7b59ad..000000000000 --- a/tools/debugserver/source/com.apple.internal.xpc.remote.debugserver.plist +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>com.apple.internal.xpc.remote.debugserver</string> - <key>RemoteServices</key> - <dict> - <key>com.apple.internal.debugserver</key> - <dict> - <key>RequireEntitlement</key> - <string>AppleInternal</string> - <key>ExposedToUntrustedDevices</key> - <true/> - </dict> - </dict> - <key>ProgramArguments</key> - <array> - <string>/usr/libexec/remotectl</string> - <string>trampoline</string> - <string>-2</string> - <string>42</string> - <string>com.apple.internal.debugserver</string> - <string>/usr/local/bin/debugserver-nonui</string> - <string>--fd</string> - <string>42</string> - </array> - <key>POSIXSpawnType</key> - <string>Interactive</string> - <key>EnableTransactions</key> - <true/> - <key>EnablePressuredExit</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/debugserver-entitlements.plist b/tools/debugserver/source/debugserver-entitlements.plist deleted file mode 100644 index 6d9f44536f94..000000000000 --- a/tools/debugserver/source/debugserver-entitlements.plist +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>com.apple.springboard.debugapplications</key> - <true/> - <key>com.apple.backboardd.launchapplications</key> - <true/> - <key>com.apple.backboardd.debugapplications</key> - <true/> - <key>com.apple.frontboard.launchapplications</key> - <true/> - <key>com.apple.frontboard.debugapplications</key> - <true/> - <key>seatbelt-profiles</key> - <array> - <string>debugserver</string> - </array> - <key>com.apple.diagnosticd.diagnostic</key> - <true/> - <key>com.apple.security.network.server</key> - <true/> - <key>com.apple.security.network.client</key> - <true/> - <key>com.apple.private.memorystatus</key> - <true/> - <key>com.apple.private.cs.debugger</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/debugserver-macosx-entitlements.plist b/tools/debugserver/source/debugserver-macosx-entitlements.plist deleted file mode 100644 index 92a0d13fc781..000000000000 --- a/tools/debugserver/source/debugserver-macosx-entitlements.plist +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>com.apple.diagnosticd.diagnostic</key> - <true/> - <key>com.apple.private.cs.debugger</key> - <true/> -</dict> -</plist> diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp deleted file mode 100644 index 8afe17bce37d..000000000000 --- a/tools/debugserver/source/debugserver.cpp +++ /dev/null @@ -1,1684 +0,0 @@ -//===-- debugserver.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <arpa/inet.h> -#include <asl.h> -#include <crt_externs.h> -#include <errno.h> -#include <getopt.h> -#include <netdb.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <string> -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/types.h> -#include <sys/un.h> -#include <vector> - -#if defined(__APPLE__) -#include <sched.h> -extern "C" int proc_set_wakemon_params(pid_t, int, - int); // <libproc_internal.h> SPI -#endif - -#include "CFString.h" -#include "DNB.h" -#include "DNBLog.h" -#include "DNBTimer.h" -#include "OsLogger.h" -#include "PseudoTerminal.h" -#include "RNBContext.h" -#include "RNBRemote.h" -#include "RNBServices.h" -#include "RNBSocket.h" -#include "SysSignal.h" - -// Global PID in case we get a signal and need to stop the process... -nub_process_t g_pid = INVALID_NUB_PROCESS; - -//---------------------------------------------------------------------- -// Run loop modes which determine which run loop function will be called -//---------------------------------------------------------------------- -typedef enum { - eRNBRunLoopModeInvalid = 0, - eRNBRunLoopModeGetStartModeFromRemoteProtocol, - eRNBRunLoopModeInferiorAttaching, - eRNBRunLoopModeInferiorLaunching, - eRNBRunLoopModeInferiorExecuting, - eRNBRunLoopModePlatformMode, - eRNBRunLoopModeExit -} RNBRunLoopMode; - -//---------------------------------------------------------------------- -// Global Variables -//---------------------------------------------------------------------- -RNBRemoteSP g_remoteSP; -static int g_lockdown_opt = 0; -static int g_applist_opt = 0; -static nub_launch_flavor_t g_launch_flavor = eLaunchFlavorDefault; -int g_disable_aslr = 0; - -int g_isatty = 0; -bool g_detach_on_error = true; - -#define RNBLogSTDOUT(fmt, ...) \ - do { \ - if (g_isatty) { \ - fprintf(stdout, fmt, ##__VA_ARGS__); \ - } else { \ - _DNBLog(0, fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define RNBLogSTDERR(fmt, ...) \ - do { \ - if (g_isatty) { \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - } else { \ - _DNBLog(0, fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -//---------------------------------------------------------------------- -// Get our program path and arguments from the remote connection. -// We will need to start up the remote connection without a PID, get the -// arguments, wait for the new process to finish launching and hit its -// entry point, and then return the run loop mode that should come next. -//---------------------------------------------------------------------- -RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemote *remote) { - std::string packet; - - if (remote) { - RNBContext &ctx = remote->Context(); - uint32_t event_mask = RNBContext::event_read_packet_available | - RNBContext::event_read_thread_exiting; - - // Spin waiting to get the A packet. - while (1) { - DNBLogThreadedIf(LOG_RNB_MAX, - "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", - __FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf(LOG_RNB_MAX, - "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", - __FUNCTION__, event_mask, set_events); - - if (set_events & RNBContext::event_read_thread_exiting) { - RNBLogSTDERR("error: packet read thread exited.\n"); - return eRNBRunLoopModeExit; - } - - if (set_events & RNBContext::event_read_packet_available) { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket(&type); - - // check if we tried to attach to a process - if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || - type == RNBRemote::vattachorwait) { - if (err == rnb_success) { - RNBLogSTDOUT("Attach succeeded, ready to debug.\n"); - return eRNBRunLoopModeInferiorExecuting; - } else { - RNBLogSTDERR("error: attach failed.\n"); - return eRNBRunLoopModeExit; - } - } - - if (err == rnb_success) { - // If we got our arguments we are ready to launch using the arguments - // and any environment variables we received. - if (type == RNBRemote::set_argv) { - return eRNBRunLoopModeInferiorLaunching; - } - } else if (err == rnb_not_connected) { - RNBLogSTDERR("error: connection lost.\n"); - return eRNBRunLoopModeExit; - } else { - // a catch all for any other gdb remote packets that failed - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", - __FUNCTION__); - continue; - } - - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - } else { - DNBLogThreadedIf(LOG_RNB_MINIMAL, - "%s Connection closed before getting \"A\" packet.", - __FUNCTION__); - return eRNBRunLoopModeExit; - } - } - } - return eRNBRunLoopModeExit; -} - -//---------------------------------------------------------------------- -// This run loop mode will wait for the process to launch and hit its -// entry point. It will currently ignore all events except for the -// process state changed event, where it watches for the process stopped -// or crash process state. -//---------------------------------------------------------------------- -RNBRunLoopMode RNBRunLoopLaunchInferior(RNBRemote *remote, - const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - bool no_stdio) { - RNBContext &ctx = remote->Context(); - - // The Process stuff takes a c array, the RNBContext has a vector... - // So make up a c array. - - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, - ctx.ArgumentAtIndex(0)); - - size_t inferior_argc = ctx.ArgumentCount(); - // Initialize inferior_argv with inferior_argc + 1 NULLs - std::vector<const char *> inferior_argv(inferior_argc + 1, NULL); - - size_t i; - for (i = 0; i < inferior_argc; i++) - inferior_argv[i] = ctx.ArgumentAtIndex(i); - - // Pass the environment array the same way: - - size_t inferior_envc = ctx.EnvironmentCount(); - // Initialize inferior_argv with inferior_argc + 1 NULLs - std::vector<const char *> inferior_envp(inferior_envc + 1, NULL); - - for (i = 0; i < inferior_envc; i++) - inferior_envp[i] = ctx.EnvironmentAtIndex(i); - - // Our launch type hasn't been set to anything concrete, so we need to - // figure our how we are going to launch automatically. - - nub_launch_flavor_t launch_flavor = g_launch_flavor; - if (launch_flavor == eLaunchFlavorDefault) { - // Our default launch method is posix spawn - launch_flavor = eLaunchFlavorPosixSpawn; - -#if defined WITH_FBS - // Check if we have an app bundle, if so launch using BackBoard Services. - if (strstr(inferior_argv[0], ".app")) { - launch_flavor = eLaunchFlavorFBS; - } -#elif defined WITH_BKS - // Check if we have an app bundle, if so launch using BackBoard Services. - if (strstr(inferior_argv[0], ".app")) { - launch_flavor = eLaunchFlavorBKS; - } -#elif defined WITH_SPRINGBOARD - // Check if we have an app bundle, if so launch using SpringBoard. - if (strstr(inferior_argv[0], ".app")) { - launch_flavor = eLaunchFlavorSpringBoard; - } -#endif - } - - ctx.SetLaunchFlavor(launch_flavor); - char resolved_path[PATH_MAX]; - - // If we fail to resolve the path to our executable, then just use what we - // were given and hope for the best - if (!DNBResolveExecutablePath(inferior_argv[0], resolved_path, - sizeof(resolved_path))) - ::strlcpy(resolved_path, inferior_argv[0], sizeof(resolved_path)); - - char launch_err_str[PATH_MAX]; - launch_err_str[0] = '\0'; - const char *cwd = - (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath() - : ctx.GetWorkingDirectory()); - const char *process_event = ctx.GetProcessEvent(); - nub_process_t pid = DNBProcessLaunch( - resolved_path, &inferior_argv[0], &inferior_envp[0], cwd, stdin_path, - stdout_path, stderr_path, no_stdio, launch_flavor, g_disable_aslr, - process_event, launch_err_str, sizeof(launch_err_str)); - - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS && strlen(launch_err_str) > 0) { - DNBLogThreaded("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, - launch_err_str); - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - ctx.LaunchStatus().SetErrorString(launch_err_str); - } else if (pid == INVALID_NUB_PROCESS) { - DNBLogThreaded( - "%s DNBProcessLaunch() failed to launch process, unknown failure", - __FUNCTION__); - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - ctx.LaunchStatus().SetErrorString("<unknown failure>"); - } else { - ctx.LaunchStatus().Clear(); - } - - if (remote->Comm().IsConnected()) { - // It we are connected already, the next thing gdb will do is ask - // whether the launch succeeded, and if not, whether there is an - // error code. So we need to fetch one packet from gdb before we wait - // on the stop from the target. - - uint32_t event_mask = RNBContext::event_read_packet_available; - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - - if (set_events & RNBContext::event_read_packet_available) { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket(&type); - - if (err != rnb_success) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", - __FUNCTION__); - return eRNBRunLoopModeExit; - } - if (type != RNBRemote::query_launch_success) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, - "%s Didn't get the expected qLaunchSuccess packet.", - __FUNCTION__); - } - } - } - - while (pid != INVALID_NUB_PROCESS) { - // Wait for process to start up and hit entry point - DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged, true, " - "INFINITE)...", - __FUNCTION__, pid); - nub_event_t set_events = - DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged, - true, NULL); - DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " - "eEventProcessRunningStateChanged | " - "eEventProcessStoppedStateChanged, true, " - "INFINITE) => 0x%8.8x", - __FUNCTION__, pid, set_events); - - if (set_events == 0) { - pid = INVALID_NUB_PROCESS; - g_pid = pid; - } else { - if (set_events & (eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged)) { - nub_state_t pid_state = DNBProcessGetState(pid); - DNBLogThreadedIf( - LOG_RNB_EVENTS, - "%s process %4.4x state changed (eEventProcessStateChanged): %s", - __FUNCTION__, pid, DNBStateAsString(pid_state)); - - switch (pid_state) { - case eStateInvalid: - case eStateUnloaded: - case eStateAttaching: - case eStateLaunching: - case eStateSuspended: - break; // Ignore - - case eStateRunning: - case eStateStepping: - // Still waiting to stop at entry point... - break; - - case eStateStopped: - case eStateCrashed: - ctx.SetProcessID(pid); - return eRNBRunLoopModeInferiorExecuting; - - case eStateDetached: - case eStateExited: - pid = INVALID_NUB_PROCESS; - g_pid = pid; - return eRNBRunLoopModeExit; - } - } - - DNBProcessResetEvents(pid, set_events); - } - } - - return eRNBRunLoopModeExit; -} - -//---------------------------------------------------------------------- -// This run loop mode will wait for the process to launch and hit its -// entry point. It will currently ignore all events except for the -// process state changed event, where it watches for the process stopped -// or crash process state. -//---------------------------------------------------------------------- -RNBRunLoopMode RNBRunLoopLaunchAttaching(RNBRemote *remote, - nub_process_t attach_pid, - nub_process_t &pid) { - RNBContext &ctx = remote->Context(); - - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, - attach_pid); - char err_str[1024]; - pid = DNBProcessAttach(attach_pid, NULL, err_str, sizeof(err_str)); - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS) { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - return eRNBRunLoopModeExit; - } else { - ctx.SetProcessID(pid); - return eRNBRunLoopModeInferiorExecuting; - } -} - -//---------------------------------------------------------------------- -// Watch for signals: -// SIGINT: so we can halt our inferior. (disabled for now) -// SIGPIPE: in case our child process dies -//---------------------------------------------------------------------- -int g_sigint_received = 0; -int g_sigpipe_received = 0; -void signal_handler(int signo) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, - SysSignal::Name(signo)); - - switch (signo) { - case SIGINT: - g_sigint_received++; - if (g_pid != INVALID_NUB_PROCESS) { - // Only send a SIGINT once... - if (g_sigint_received == 1) { - switch (DNBProcessGetState(g_pid)) { - case eStateRunning: - case eStateStepping: - DNBProcessSignal(g_pid, SIGSTOP); - return; - default: - break; - } - } - } - exit(SIGINT); - break; - - case SIGPIPE: - g_sigpipe_received = 1; - break; - } -} - -// Return the new run loop mode based off of the current process state -RNBRunLoopMode HandleProcessStateChange(RNBRemote *remote, bool initialize) { - RNBContext &ctx = remote->Context(); - nub_process_t pid = ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", - __FUNCTION__); - return eRNBRunLoopModeExit; - } - nub_state_t pid_state = DNBProcessGetState(pid); - - DNBLogThreadedIf(LOG_RNB_MINIMAL, - "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, - (int)initialize, DNBStateAsString(pid_state)); - - switch (pid_state) { - case eStateInvalid: - case eStateUnloaded: - // Something bad happened - return eRNBRunLoopModeExit; - break; - - case eStateAttaching: - case eStateLaunching: - return eRNBRunLoopModeInferiorExecuting; - - case eStateSuspended: - case eStateCrashed: - case eStateStopped: - // If we stop due to a signal, so clear the fact that we got a SIGINT - // so we can stop ourselves again (but only while our inferior - // process is running..) - g_sigint_received = 0; - if (initialize == false) { - // Compare the last stop count to our current notion of a stop count - // to make sure we don't notify more than once for a given stop. - nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); - bool pid_stop_count_changed = - ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); - if (pid_stop_count_changed) { - remote->FlushSTDIO(); - - if (ctx.GetProcessStopCount() == 1) { - DNBLogThreadedIf( - LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " - "pid_stop_count %llu (old %llu)) Notify??? no, " - "first stop...", - __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), - (uint64_t)ctx.GetProcessStopCount(), - (uint64_t)prev_pid_stop_count); - } else { - - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) " - "pid_state = %s pid_stop_count " - "%llu (old %llu)) Notify??? YES!!!", - __FUNCTION__, (int)initialize, - DNBStateAsString(pid_state), - (uint64_t)ctx.GetProcessStopCount(), - (uint64_t)prev_pid_stop_count); - remote->NotifyThatProcessStopped(); - } - } else { - DNBLogThreadedIf( - LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " - "pid_stop_count %llu (old %llu)) Notify??? " - "skipping...", - __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), - (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count); - } - } - return eRNBRunLoopModeInferiorExecuting; - - case eStateStepping: - case eStateRunning: - return eRNBRunLoopModeInferiorExecuting; - - case eStateExited: - remote->HandlePacket_last_signal(NULL); - case eStateDetached: - return eRNBRunLoopModeExit; - } - - // Catch all... - return eRNBRunLoopModeExit; -} -// This function handles the case where our inferior program is stopped and -// we are waiting for gdb remote protocol packets. When a packet occurs that -// makes the inferior run, we need to leave this function with a new state -// as the return code. -RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemote *remote) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - RNBContext &ctx = remote->Context(); - - // Init our mode and set 'is_running' based on the current process state - RNBRunLoopMode mode = HandleProcessStateChange(remote, true); - - while (ctx.ProcessID() != INVALID_NUB_PROCESS) { - - std::string set_events_str; - uint32_t event_mask = ctx.NormalEventBits(); - - if (!ctx.ProcessStateRunning()) { - // Clear some bits if we are not running so we don't send any async - // packets - event_mask &= ~RNBContext::event_proc_stdio_available; - event_mask &= ~RNBContext::event_proc_profile_data; - // When we enable async structured data packets over another logical - // channel, - // this can be relaxed. - event_mask &= ~RNBContext::event_darwin_log_data_available; - } - - // We want to make sure we consume all process state changes and have - // whomever is notifying us to wait for us to reset the event bit before - // continuing. - // ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); - - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) ...", - __FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", - __FUNCTION__, event_mask, set_events, - ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) { - if ((set_events & RNBContext::event_proc_thread_exiting) || - (set_events & RNBContext::event_proc_stdio_available)) { - remote->FlushSTDIO(); - } - - if (set_events & RNBContext::event_proc_profile_data) { - remote->SendAsyncProfileData(); - } - - if (set_events & RNBContext::event_darwin_log_data_available) { - remote->SendAsyncDarwinLogData(); - } - - if (set_events & RNBContext::event_read_packet_available) { - // handleReceivedPacket will take care of resetting the - // event_read_packet_available events when there are no more... - set_events ^= RNBContext::event_read_packet_available; - - if (ctx.ProcessStateRunning()) { - if (remote->HandleAsyncPacket() == rnb_not_connected) { - // TODO: connect again? Exit? - } - } else { - if (remote->HandleReceivedPacket() == rnb_not_connected) { - // TODO: connect again? Exit? - } - } - } - - if (set_events & RNBContext::event_proc_state_changed) { - mode = HandleProcessStateChange(remote, false); - ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); - set_events ^= RNBContext::event_proc_state_changed; - } - - if (set_events & RNBContext::event_proc_thread_exiting) { - mode = eRNBRunLoopModeExit; - } - - if (set_events & RNBContext::event_read_thread_exiting) { - // Out remote packet receiving thread exited, exit for now. - if (ctx.HasValidProcessID()) { - // TODO: We should add code that will leave the current process - // in its current state and listen for another connection... - if (ctx.ProcessStateRunning()) { - if (ctx.GetDetachOnError()) { - DNBLog("debugserver's event read thread is exiting, detaching " - "from the inferior process."); - DNBProcessDetach(ctx.ProcessID()); - } else { - DNBLog("debugserver's event read thread is exiting, killing the " - "inferior process."); - DNBProcessKill(ctx.ProcessID()); - } - } else { - if (ctx.GetDetachOnError()) { - DNBLog("debugserver's event read thread is exiting, detaching " - "from the inferior process."); - DNBProcessDetach(ctx.ProcessID()); - } - } - } - mode = eRNBRunLoopModeExit; - } - } - - // Reset all event bits that weren't reset for now... - if (set_events != 0) - ctx.Events().ResetEvents(set_events); - - if (mode != eRNBRunLoopModeInferiorExecuting) - break; - } - - return mode; -} - -RNBRunLoopMode RNBRunLoopPlatform(RNBRemote *remote) { - RNBRunLoopMode mode = eRNBRunLoopModePlatformMode; - RNBContext &ctx = remote->Context(); - - while (mode == eRNBRunLoopModePlatformMode) { - std::string set_events_str; - const uint32_t event_mask = RNBContext::event_read_packet_available | - RNBContext::event_read_thread_exiting; - - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) ...", - __FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", - __FUNCTION__, event_mask, set_events, - ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) { - if (set_events & RNBContext::event_read_packet_available) { - if (remote->HandleReceivedPacket() == rnb_not_connected) - mode = eRNBRunLoopModeExit; - } - - if (set_events & RNBContext::event_read_thread_exiting) { - mode = eRNBRunLoopModeExit; - } - ctx.Events().ResetEvents(set_events); - } - } - return eRNBRunLoopModeExit; -} - -//---------------------------------------------------------------------- -// Convenience function to set up the remote listening port -// Returns 1 for success 0 for failure. -//---------------------------------------------------------------------- - -static void PortWasBoundCallbackUnixSocket(const void *baton, in_port_t port) { - //::printf ("PortWasBoundCallbackUnixSocket (baton = %p, port = %u)\n", baton, - //port); - - const char *unix_socket_name = (const char *)baton; - - if (unix_socket_name && unix_socket_name[0]) { - // We were given a unix socket name to use to communicate the port - // that we ended up binding to back to our parent process - struct sockaddr_un saddr_un; - int s = ::socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) { - perror("error: socket (AF_UNIX, SOCK_STREAM, 0)"); - exit(1); - } - - saddr_un.sun_family = AF_UNIX; - ::strlcpy(saddr_un.sun_path, unix_socket_name, - sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; - saddr_un.sun_len = SUN_LEN(&saddr_un); - - if (::connect(s, (struct sockaddr *)&saddr_un, - static_cast<socklen_t>(SUN_LEN(&saddr_un))) < 0) { - perror("error: connect (socket, &saddr_un, saddr_un_len)"); - exit(1); - } - - //::printf ("connect () sucess!!\n"); - - // We were able to connect to the socket, now write our PID so whomever - // launched us will know this process's ID - RNBLogSTDOUT("Listening to port %i...\n", port); - - char pid_str[64]; - const int pid_str_len = ::snprintf(pid_str, sizeof(pid_str), "%u", port); - const ssize_t bytes_sent = ::send(s, pid_str, pid_str_len, 0); - - if (pid_str_len != bytes_sent) { - perror("error: send (s, pid_str, pid_str_len, 0)"); - exit(1); - } - - //::printf ("send () sucess!!\n"); - - // We are done with the socket - close(s); - } -} - -static void PortWasBoundCallbackNamedPipe(const void *baton, uint16_t port) { - const char *named_pipe = (const char *)baton; - if (named_pipe && named_pipe[0]) { - int fd = ::open(named_pipe, O_WRONLY); - if (fd > -1) { - char port_str[64]; - const ssize_t port_str_len = - ::snprintf(port_str, sizeof(port_str), "%u", port); - // Write the port number as a C string with the NULL terminator - ::write(fd, port_str, port_str_len + 1); - close(fd); - } - } -} - -static int ConnectRemote(RNBRemote *remote, const char *host, int port, - bool reverse_connect, const char *named_pipe_path, - const char *unix_socket_name) { - if (!remote->Comm().IsConnected()) { - if (reverse_connect) { - if (port == 0) { - DNBLogThreaded( - "error: invalid port supplied for reverse connection: %i.\n", port); - return 0; - } - if (remote->Comm().Connect(host, port) != rnb_success) { - DNBLogThreaded("Failed to reverse connect to %s:%i.\n", host, port); - return 0; - } - } else { - if (port != 0) - RNBLogSTDOUT("Listening to port %i for a connection from %s...\n", port, - host ? host : "127.0.0.1"); - if (unix_socket_name && unix_socket_name[0]) { - if (remote->Comm().Listen(host, port, PortWasBoundCallbackUnixSocket, - unix_socket_name) != rnb_success) { - RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); - return 0; - } - } else { - if (remote->Comm().Listen(host, port, PortWasBoundCallbackNamedPipe, - named_pipe_path) != rnb_success) { - RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); - return 0; - } - } - } - remote->StartReadRemoteDataThread(); - } - return 1; -} - -//---------------------------------------------------------------------- -// ASL Logging callback that can be registered with DNBLogSetLogCallback -//---------------------------------------------------------------------- -void ASLLogCallback(void *baton, uint32_t flags, const char *format, - va_list args) { - if (format == NULL) - return; - static aslmsg g_aslmsg = NULL; - if (g_aslmsg == NULL) { - g_aslmsg = ::asl_new(ASL_TYPE_MSG); - char asl_key_sender[PATH_MAX]; - snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%s", - DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_STR); - ::asl_set(g_aslmsg, ASL_KEY_SENDER, asl_key_sender); - } - - int asl_level; - if (flags & DNBLOG_FLAG_FATAL) - asl_level = ASL_LEVEL_CRIT; - else if (flags & DNBLOG_FLAG_ERROR) - asl_level = ASL_LEVEL_ERR; - else if (flags & DNBLOG_FLAG_WARNING) - asl_level = ASL_LEVEL_WARNING; - else if (flags & DNBLOG_FLAG_VERBOSE) - asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_INFO; - else - asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_DEBUG; - - ::asl_vlog(NULL, g_aslmsg, asl_level, format, args); -} - -//---------------------------------------------------------------------- -// FILE based Logging callback that can be registered with -// DNBLogSetLogCallback -//---------------------------------------------------------------------- -void FileLogCallback(void *baton, uint32_t flags, const char *format, - va_list args) { - if (baton == NULL || format == NULL) - return; - - ::vfprintf((FILE *)baton, format, args); - ::fprintf((FILE *)baton, "\n"); - ::fflush((FILE *)baton); -} - -void show_usage_and_exit(int exit_code) { - RNBLogSTDERR( - "Usage:\n %s host:port [program-name program-arg1 program-arg2 ...]\n", - DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR(" %s /path/file [program-name program-arg1 program-arg2 ...]\n", - DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR(" %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR(" %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR(" %s host:port --attach=<process_name>\n", - DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR(" %s /path/file --attach=<process_name>\n", - DEBUGSERVER_PROGRAM_NAME); - exit(exit_code); -} - -//---------------------------------------------------------------------- -// option descriptors for getopt_long_only() -//---------------------------------------------------------------------- -static struct option g_long_options[] = { - {"attach", required_argument, NULL, 'a'}, - {"arch", required_argument, NULL, 'A'}, - {"debug", no_argument, NULL, 'g'}, - {"kill-on-error", no_argument, NULL, 'K'}, - {"verbose", no_argument, NULL, 'v'}, - {"lockdown", no_argument, &g_lockdown_opt, 1}, // short option "-k" - {"applist", no_argument, &g_applist_opt, 1}, // short option "-t" - {"log-file", required_argument, NULL, 'l'}, - {"log-flags", required_argument, NULL, 'f'}, - {"launch", required_argument, NULL, 'x'}, // Valid values are "auto", - // "posix-spawn", "fork-exec", - // "springboard" (arm only) - {"waitfor", required_argument, NULL, - 'w'}, // Wait for a process whose name starts with ARG - {"waitfor-interval", required_argument, NULL, - 'i'}, // Time in usecs to wait between sampling the pid list when waiting - // for a process by name - {"waitfor-duration", required_argument, NULL, - 'd'}, // The time in seconds to wait for a process to show up by name - {"native-regs", no_argument, NULL, 'r'}, // Specify to use the native - // registers instead of the gdb - // defaults for the architecture. - {"stdio-path", required_argument, NULL, - 's'}, // Set the STDIO path to be used when launching applications (STDIN, - // STDOUT and STDERR) (only if debugserver launches the process) - {"stdin-path", required_argument, NULL, - 'I'}, // Set the STDIN path to be used when launching applications (only if - // debugserver launches the process) - {"stdout-path", required_argument, NULL, - 'O'}, // Set the STDOUT path to be used when launching applications (only - // if debugserver launches the process) - {"stderr-path", required_argument, NULL, - 'E'}, // Set the STDERR path to be used when launching applications (only - // if debugserver launches the process) - {"no-stdio", no_argument, NULL, - 'n'}, // Do not set up any stdio (perhaps the program is a GUI program) - // (only if debugserver launches the process) - {"setsid", no_argument, NULL, - 'S'}, // call setsid() to make debugserver run in its own session - {"disable-aslr", no_argument, NULL, 'D'}, // Use _POSIX_SPAWN_DISABLE_ASLR - // to avoid shared library - // randomization - {"working-dir", required_argument, NULL, - 'W'}, // The working directory that the inferior process should have (only - // if debugserver launches the process) - {"platform", required_argument, NULL, - 'p'}, // Put this executable into a remote platform mode - {"unix-socket", required_argument, NULL, - 'u'}, // If we need to handshake with our parent process, an option will be - // passed down that specifies a unix socket name to use - {"fd", required_argument, NULL, - '2'}, // A file descriptor was passed to this process when spawned that - // is already open and ready for communication - {"named-pipe", required_argument, NULL, 'P'}, - {"reverse-connect", no_argument, NULL, 'R'}, - {"env", required_argument, NULL, - 'e'}, // When debugserver launches the process, set a single environment - // entry as specified by the option value ("./debugserver -e FOO=1 -e - // BAR=2 localhost:1234 -- /bin/ls") - {"forward-env", no_argument, NULL, - 'F'}, // When debugserver launches the process, forward debugserver's - // current environment variables to the child process ("./debugserver - // -F localhost:1234 -- /bin/ls" - {NULL, 0, NULL, 0}}; - -//---------------------------------------------------------------------- -// main -//---------------------------------------------------------------------- -int main(int argc, char *argv[]) { - // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we - // don't spawn child processes with this enabled. - unsetenv("DYLD_INSERT_LIBRARIES"); - - const char *argv_sub_zero = - argv[0]; // save a copy of argv[0] for error reporting post-launch - -#if defined(__APPLE__) - pthread_setname_np("main thread"); -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, - &thread_param) == 0) { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } - - ::proc_set_wakemon_params( - getpid(), 500, - 0); // Allow up to 500 wakeups/sec to avoid EXC_RESOURCE for normal use. -#endif -#endif - - g_isatty = ::isatty(STDIN_FILENO); - - // ::printf ("uid=%u euid=%u gid=%u egid=%u\n", - // getuid(), - // geteuid(), - // getgid(), - // getegid()); - - // signal (SIGINT, signal_handler); - signal(SIGPIPE, signal_handler); - signal(SIGHUP, signal_handler); - - // We're always sitting in waitpid or kevent waiting on our target process' - // death, - // we don't need no stinking SIGCHLD's... - - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGCHLD); - sigprocmask(SIG_BLOCK, &sigset, NULL); - - g_remoteSP.reset(new RNBRemote()); - - RNBRemote *remote = g_remoteSP.get(); - if (remote == NULL) { - RNBLogSTDERR("error: failed to create a remote connection class\n"); - return -1; - } - - RNBContext &ctx = remote->Context(); - - int i; - int attach_pid = INVALID_NUB_PROCESS; - - FILE *log_file = NULL; - uint32_t log_flags = 0; - // Parse our options - int ch; - int long_option_index = 0; - int debug = 0; - int communication_fd = -1; - std::string compile_options; - std::string waitfor_pid_name; // Wait for a process that starts with this name - std::string attach_pid_name; - std::string arch_name; - std::string working_dir; // The new working directory to use for the inferior - std::string unix_socket_name; // If we need to handshake with our parent - // process, an option will be passed down that - // specifies a unix socket name to use - std::string named_pipe_path; // If we need to handshake with our parent - // process, an option will be passed down that - // specifies a named pipe to use - useconds_t waitfor_interval = 1000; // Time in usecs between process lists - // polls when waiting for a process by - // name, default 1 msec. - useconds_t waitfor_duration = - 0; // Time in seconds to wait for a process by name, 0 means wait forever. - bool no_stdio = false; - bool reverse_connect = false; // Set to true by an option to indicate we - // should reverse connect to the host:port - // supplied as the first debugserver argument - -#if !defined(DNBLOG_ENABLED) - compile_options += "(no-logging) "; -#endif - - RNBRunLoopMode start_mode = eRNBRunLoopModeExit; - - char short_options[512]; - uint32_t short_options_idx = 0; - - // Handle the two case that don't have short options in g_long_options - short_options[short_options_idx++] = 'k'; - short_options[short_options_idx++] = 't'; - - for (i = 0; g_long_options[i].name != NULL; ++i) { - if (isalpha(g_long_options[i].val)) { - short_options[short_options_idx++] = g_long_options[i].val; - switch (g_long_options[i].has_arg) { - default: - case no_argument: - break; - - case optional_argument: - short_options[short_options_idx++] = ':'; - // Fall through to required_argument case below... - case required_argument: - short_options[short_options_idx++] = ':'; - break; - } - } - } - // NULL terminate the short option string. - short_options[short_options_idx++] = '\0'; - -#if __GLIBC__ - optind = 0; -#else - optreset = 1; - optind = 1; -#endif - - bool forward_env = false; - while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, - &long_option_index)) != -1) { - DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", ch, (uint8_t)ch, - g_long_options[long_option_index].name, - g_long_options[long_option_index].has_arg ? '=' : ' ', - optarg ? optarg : ""); - switch (ch) { - case 0: // Any optional that auto set themselves will return 0 - break; - - case 'A': - if (optarg && optarg[0]) - arch_name.assign(optarg); - break; - - case 'a': - if (optarg && optarg[0]) { - if (isdigit(optarg[0])) { - char *end = NULL; - attach_pid = static_cast<int>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') { - RNBLogSTDERR("error: invalid pid option '%s'\n", optarg); - exit(4); - } - } else { - attach_pid_name = optarg; - } - start_mode = eRNBRunLoopModeInferiorAttaching; - } - break; - - // --waitfor=NAME - case 'w': - if (optarg && optarg[0]) { - waitfor_pid_name = optarg; - start_mode = eRNBRunLoopModeInferiorAttaching; - } - break; - - // --waitfor-interval=USEC - case 'i': - if (optarg && optarg[0]) { - char *end = NULL; - waitfor_interval = static_cast<useconds_t>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') { - RNBLogSTDERR("error: invalid waitfor-interval option value '%s'.\n", - optarg); - exit(6); - } - } - break; - - // --waitfor-duration=SEC - case 'd': - if (optarg && optarg[0]) { - char *end = NULL; - waitfor_duration = static_cast<useconds_t>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') { - RNBLogSTDERR("error: invalid waitfor-duration option value '%s'.\n", - optarg); - exit(7); - } - } - break; - - case 'K': - g_detach_on_error = false; - break; - case 'W': - if (optarg && optarg[0]) - working_dir.assign(optarg); - break; - - case 'x': - if (optarg && optarg[0]) { - if (strcasecmp(optarg, "auto") == 0) - g_launch_flavor = eLaunchFlavorDefault; - else if (strcasestr(optarg, "posix") == optarg) - g_launch_flavor = eLaunchFlavorPosixSpawn; - else if (strcasestr(optarg, "fork") == optarg) - g_launch_flavor = eLaunchFlavorForkExec; -#ifdef WITH_SPRINGBOARD - else if (strcasestr(optarg, "spring") == optarg) - g_launch_flavor = eLaunchFlavorSpringBoard; -#endif -#ifdef WITH_BKS - else if (strcasestr(optarg, "backboard") == optarg) - g_launch_flavor = eLaunchFlavorBKS; -#endif -#ifdef WITH_FBS - else if (strcasestr(optarg, "frontboard") == optarg) - g_launch_flavor = eLaunchFlavorFBS; -#endif - - else { - RNBLogSTDERR("error: invalid TYPE for the --launch=TYPE (-x TYPE) " - "option: '%s'\n", - optarg); - RNBLogSTDERR("Valid values TYPE are:\n"); - RNBLogSTDERR( - " auto Auto-detect the best launch method to use.\n"); - RNBLogSTDERR( - " posix Launch the executable using posix_spawn.\n"); - RNBLogSTDERR( - " fork Launch the executable using fork and exec.\n"); -#ifdef WITH_SPRINGBOARD - RNBLogSTDERR( - " spring Launch the executable through Springboard.\n"); -#endif -#ifdef WITH_BKS - RNBLogSTDERR(" backboard Launch the executable through BackBoard " - "Services.\n"); -#endif -#ifdef WITH_FBS - RNBLogSTDERR(" frontboard Launch the executable through FrontBoard " - "Services.\n"); -#endif - exit(5); - } - } - break; - - case 'l': // Set Log File - if (optarg && optarg[0]) { - if (strcasecmp(optarg, "stdout") == 0) - log_file = stdout; - else if (strcasecmp(optarg, "stderr") == 0) - log_file = stderr; - else { - log_file = fopen(optarg, "w"); - if (log_file != NULL) - setlinebuf(log_file); - } - - if (log_file == NULL) { - const char *errno_str = strerror(errno); - RNBLogSTDERR( - "Failed to open log file '%s' for writing: errno = %i (%s)", - optarg, errno, errno_str ? errno_str : "unknown error"); - } - } - break; - - case 'f': // Log Flags - if (optarg && optarg[0]) - log_flags = static_cast<uint32_t>(strtoul(optarg, NULL, 0)); - break; - - case 'g': - debug = 1; - DNBLogSetDebug(debug); - break; - - case 't': - g_applist_opt = 1; - break; - - case 'k': - g_lockdown_opt = 1; - break; - - case 'r': - // Do nothing, native regs is the default these days - break; - - case 'R': - reverse_connect = true; - break; - case 'v': - DNBLogSetVerbose(1); - break; - - case 's': - ctx.GetSTDIN().assign(optarg); - ctx.GetSTDOUT().assign(optarg); - ctx.GetSTDERR().assign(optarg); - break; - - case 'I': - ctx.GetSTDIN().assign(optarg); - break; - - case 'O': - ctx.GetSTDOUT().assign(optarg); - break; - - case 'E': - ctx.GetSTDERR().assign(optarg); - break; - - case 'n': - no_stdio = true; - break; - - case 'S': - // Put debugserver into a new session. Terminals group processes - // into sessions and when a special terminal key sequences - // (like control+c) are typed they can cause signals to go out to - // all processes in a session. Using this --setsid (-S) option - // will cause debugserver to run in its own sessions and be free - // from such issues. - // - // This is useful when debugserver is spawned from a command - // line application that uses debugserver to do the debugging, - // yet that application doesn't want debugserver receiving the - // signals sent to the session (i.e. dying when anyone hits ^C). - setsid(); - break; - case 'D': - g_disable_aslr = 1; - break; - - case 'p': - start_mode = eRNBRunLoopModePlatformMode; - break; - - case 'u': - unix_socket_name.assign(optarg); - break; - - case 'P': - named_pipe_path.assign(optarg); - break; - - case 'e': - // Pass a single specified environment variable down to the process that - // gets launched - remote->Context().PushEnvironment(optarg); - break; - - case 'F': - forward_env = true; - break; - - case '2': - // File descriptor passed to this process during fork/exec and is already - // open and ready for communication. - communication_fd = atoi(optarg); - break; - } - } - - if (arch_name.empty()) { -#if defined(__arm__) - arch_name.assign("arm"); -#endif - } else { - DNBSetArchitecture(arch_name.c_str()); - } - - // if (arch_name.empty()) - // { - // fprintf(stderr, "error: no architecture was specified\n"); - // exit (8); - // } - // Skip any options we consumed with getopt_long_only - argc -= optind; - argv += optind; - - if (!working_dir.empty()) { - if (remote->Context().SetWorkingDirectory(working_dir.c_str()) == false) { - RNBLogSTDERR("error: working directory doesn't exist '%s'.\n", - working_dir.c_str()); - exit(8); - } - } - - remote->Context().SetDetachOnError(g_detach_on_error); - - remote->Initialize(); - - // It is ok for us to set NULL as the logfile (this will disable any logging) - - if (log_file != NULL) { - DNBLogSetLogCallback(FileLogCallback, log_file); - // If our log file was set, yet we have no log flags, log everything! - if (log_flags == 0) - log_flags = LOG_ALL | LOG_RNB_ALL; - - DNBLogSetLogMask(log_flags); - } else { - // Enable DNB logging - - // if os_log() support is available, log through that. - auto log_callback = OsLogger::GetLogFunction(); - if (log_callback) { - DNBLogSetLogCallback(log_callback, nullptr); - DNBLog("debugserver will use os_log for internal logging."); - } else { - // Fall back to ASL support. - DNBLogSetLogCallback(ASLLogCallback, NULL); - DNBLog("debugserver will use ASL for internal logging."); - } - DNBLogSetLogMask(log_flags); - } - - if (DNBLogEnabled()) { - for (i = 0; i < argc; i++) - DNBLogDebug("argv[%i] = %s", i, argv[i]); - } - - // as long as we're dropping remotenub in as a replacement for gdbserver, - // explicitly note that this is not gdbserver. - - RNBLogSTDOUT("%s-%s %sfor %s.\n", DEBUGSERVER_PROGRAM_NAME, - DEBUGSERVER_VERSION_STR, compile_options.c_str(), RNB_ARCH); - - std::string host; - int port = INT32_MAX; - char str[PATH_MAX]; - str[0] = '\0'; - - if (g_lockdown_opt == 0 && g_applist_opt == 0 && communication_fd == -1) { - // Make sure we at least have port - if (argc < 1) { - show_usage_and_exit(1); - } - // accept 'localhost:' prefix on port number - std::string host_specifier = argv[0]; - auto colon_location = host_specifier.rfind(':'); - if (colon_location != std::string::npos) { - host = host_specifier.substr(0, colon_location); - std::string port_str = - host_specifier.substr(colon_location + 1, std::string::npos); - char *end_ptr; - port = strtoul(port_str.c_str(), &end_ptr, 0); - if (end_ptr < port_str.c_str() + port_str.size()) - show_usage_and_exit(2); - if (host.front() == '[' && host.back() == ']') - host = host.substr(1, host.size() - 2); - DNBLogDebug("host = '%s' port = %i", host.c_str(), port); - } else { - // No hostname means "localhost" - int items_scanned = ::sscanf(argv[0], "%i", &port); - if (items_scanned == 1) { - host = "127.0.0.1"; - DNBLogDebug("host = '%s' port = %i", host.c_str(), port); - } else if (argv[0][0] == '/') { - port = INT32_MAX; - strlcpy(str, argv[0], sizeof(str)); - } else { - show_usage_and_exit(2); - } - } - - // We just used the 'host:port' or the '/path/file' arg... - argc--; - argv++; - } - - // If we know we're waiting to attach, we don't need any of this other info. - if (start_mode != eRNBRunLoopModeInferiorAttaching && - start_mode != eRNBRunLoopModePlatformMode) { - if (argc == 0 || g_lockdown_opt) { - if (g_lockdown_opt != 0) { - // Work around for SIGPIPE crashes due to posix_spawn issue. - // We have to close STDOUT and STDERR, else the first time we - // try and do any, we get SIGPIPE and die as posix_spawn is - // doing bad things with our file descriptors at the moment. - int null = open("/dev/null", O_RDWR); - dup2(null, STDOUT_FILENO); - dup2(null, STDERR_FILENO); - } else if (g_applist_opt != 0) { - // List all applications we are able to see - std::string applist_plist; - int err = ListApplications(applist_plist, false, false); - if (err == 0) { - fputs(applist_plist.c_str(), stdout); - } else { - RNBLogSTDERR("error: ListApplications returned error %i\n", err); - } - // Exit with appropriate error if we were asked to list the applications - // with no other args were given (and we weren't trying to do this over - // lockdown) - return err; - } - - DNBLogDebug("Get args from remote protocol..."); - start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; - } else { - start_mode = eRNBRunLoopModeInferiorLaunching; - // Fill in the argv array in the context from the rest of our args. - // Skip the name of this executable and the port number - for (int i = 0; i < argc; i++) { - DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]); - ctx.PushArgument(argv[i]); - } - } - } - - if (start_mode == eRNBRunLoopModeExit) - return -1; - - if (forward_env || start_mode == eRNBRunLoopModeInferiorLaunching) { - // Pass the current environment down to the process that gets launched - // This happens automatically in the "launching" mode. For the rest, we - // only do that if the user explicitly requested this via --forward-env - // argument. - char **host_env = *_NSGetEnviron(); - char *env_entry; - size_t i; - for (i = 0; (env_entry = host_env[i]) != NULL; ++i) - remote->Context().PushEnvironmentIfNeeded(env_entry); - } - - RNBRunLoopMode mode = start_mode; - char err_str[1024] = {'\0'}; - - while (mode != eRNBRunLoopModeExit) { - switch (mode) { - case eRNBRunLoopModeGetStartModeFromRemoteProtocol: -#ifdef WITH_LOCKDOWN - if (g_lockdown_opt) { - if (!remote->Comm().IsConnected()) { - if (remote->Comm().ConnectToService() != rnb_success) { - RNBLogSTDERR( - "Failed to get connection from a remote gdb process.\n"); - mode = eRNBRunLoopModeExit; - } else if (g_applist_opt != 0) { - // List all applications we are able to see - std::string applist_plist; - if (ListApplications(applist_plist, false, false) == 0) { - DNBLogDebug("Task list: %s", applist_plist.c_str()); - - remote->Comm().Write(applist_plist.c_str(), applist_plist.size()); - // Issue a read that will never yield any data until the other - // side - // closes the socket so this process doesn't just exit and cause - // the - // socket to close prematurely on the other end and cause data - // loss. - std::string buf; - remote->Comm().Read(buf); - } - remote->Comm().Disconnect(false); - mode = eRNBRunLoopModeExit; - break; - } else { - // Start watching for remote packets - remote->StartReadRemoteDataThread(); - } - } - } else -#endif - if (port != INT32_MAX) { - if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, - named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } else if (str[0] == '/') { - if (remote->Comm().OpenFile(str)) - mode = eRNBRunLoopModeExit; - } else if (communication_fd >= 0) { - // We were passed a file descriptor to use during fork/exec that is - // already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) { - RNBLogSTDOUT("Got a connection, waiting for process information for " - "launching or attaching.\n"); - - mode = RNBRunLoopGetStartModeFromRemote(remote); - } - break; - - case eRNBRunLoopModeInferiorAttaching: - if (!waitfor_pid_name.empty()) { - // Set our end wait time if we are using a waitfor-duration - // option that may have been specified - struct timespec attach_timeout_abstime, *timeout_ptr = NULL; - if (waitfor_duration != 0) { - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, - 0); - timeout_ptr = &attach_timeout_abstime; - } - nub_launch_flavor_t launch_flavor = g_launch_flavor; - if (launch_flavor == eLaunchFlavorDefault) { - // Our default launch method is posix spawn - launch_flavor = eLaunchFlavorPosixSpawn; - -#if defined WITH_FBS - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find(".app") != std::string::npos) { - launch_flavor = eLaunchFlavorFBS; - } -#elif defined WITH_BKS - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find(".app") != std::string::npos) { - launch_flavor = eLaunchFlavorBKS; - } -#elif defined WITH_SPRINGBOARD - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find(".app") != std::string::npos) { - launch_flavor = eLaunchFlavorSpringBoard; - } -#endif - } - - ctx.SetLaunchFlavor(launch_flavor); - bool ignore_existing = false; - RNBLogSTDOUT("Waiting to attach to process %s...\n", - waitfor_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachWait( - waitfor_pid_name.c_str(), launch_flavor, ignore_existing, - timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS) { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", - waitfor_pid_name.c_str(), err_str); - mode = eRNBRunLoopModeExit; - } else { - ctx.SetProcessID(pid); - mode = eRNBRunLoopModeInferiorExecuting; - } - } else if (attach_pid != INVALID_NUB_PROCESS) { - - RNBLogSTDOUT("Attaching to process %i...\n", attach_pid); - nub_process_t attached_pid; - mode = RNBRunLoopLaunchAttaching(remote, attach_pid, attached_pid); - if (mode != eRNBRunLoopModeInferiorExecuting) { - const char *error_str = remote->Context().LaunchStatus().AsString(); - RNBLogSTDERR("error: failed to attach process %i: %s\n", attach_pid, - error_str ? error_str : "unknown error."); - mode = eRNBRunLoopModeExit; - } - } else if (!attach_pid_name.empty()) { - struct timespec attach_timeout_abstime, *timeout_ptr = NULL; - if (waitfor_duration != 0) { - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, - 0); - timeout_ptr = &attach_timeout_abstime; - } - - RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachByName( - attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); - g_pid = pid; - if (pid == INVALID_NUB_PROCESS) { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", - waitfor_pid_name.c_str(), err_str); - mode = eRNBRunLoopModeExit; - } else { - ctx.SetProcessID(pid); - mode = eRNBRunLoopModeInferiorExecuting; - } - - } else { - RNBLogSTDERR( - "error: asked to attach with empty name and invalid PID.\n"); - mode = eRNBRunLoopModeExit; - } - - if (mode != eRNBRunLoopModeExit) { - if (port != INT32_MAX) { - if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, - named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } else if (str[0] == '/') { - if (remote->Comm().OpenFile(str)) - mode = eRNBRunLoopModeExit; - } else if (communication_fd >= 0) { - // We were passed a file descriptor to use during fork/exec that is - // already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - RNBLogSTDOUT("Waiting for debugger instructions for process %d.\n", - attach_pid); - } - break; - - case eRNBRunLoopModeInferiorLaunching: { - mode = RNBRunLoopLaunchInferior(remote, ctx.GetSTDINPath(), - ctx.GetSTDOUTPath(), ctx.GetSTDERRPath(), - no_stdio); - - if (mode == eRNBRunLoopModeInferiorExecuting) { - if (port != INT32_MAX) { - if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, - named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } else if (str[0] == '/') { - if (remote->Comm().OpenFile(str)) - mode = eRNBRunLoopModeExit; - } else if (communication_fd >= 0) { - // We were passed a file descriptor to use during fork/exec that is - // already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) { - const char *proc_name = "<unknown>"; - if (ctx.ArgumentCount() > 0) - proc_name = ctx.ArgumentAtIndex(0); - RNBLogSTDOUT("Got a connection, launched process %s (pid = %d).\n", - proc_name, ctx.ProcessID()); - } - } else { - const char *error_str = remote->Context().LaunchStatus().AsString(); - RNBLogSTDERR("error: failed to launch process %s: %s\n", argv_sub_zero, - error_str ? error_str : "unknown error."); - } - } break; - - case eRNBRunLoopModeInferiorExecuting: - mode = RNBRunLoopInferiorExecuting(remote); - break; - - case eRNBRunLoopModePlatformMode: - if (port != INT32_MAX) { - if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, - named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } else if (str[0] == '/') { - if (remote->Comm().OpenFile(str)) - mode = eRNBRunLoopModeExit; - } else if (communication_fd >= 0) { - // We were passed a file descriptor to use during fork/exec that is - // already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - mode = RNBRunLoopPlatform(remote); - break; - - default: - mode = eRNBRunLoopModeExit; - case eRNBRunLoopModeExit: - break; - } - } - - remote->StopReadRemoteDataThread(); - remote->Context().SetProcessID(INVALID_NUB_PROCESS); - RNBLogSTDOUT("Exiting.\n"); - - return 0; -} diff --git a/tools/debugserver/source/libdebugserver.cpp b/tools/debugserver/source/libdebugserver.cpp deleted file mode 100644 index 34df67521a7c..000000000000 --- a/tools/debugserver/source/libdebugserver.cpp +++ /dev/null @@ -1,383 +0,0 @@ -//===-- libdebugserver.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <errno.h> -#include <getopt.h> -#include <netinet/in.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -#include "DNB.h" -#include "DNBLog.h" -#include "DNBTimer.h" -#include "PseudoTerminal.h" -#include "RNBContext.h" -#include "RNBRemote.h" -#include "RNBServices.h" -#include "RNBSocket.h" -#include "SysSignal.h" - -//---------------------------------------------------------------------- -// Run loop modes which determine which run loop function will be called -//---------------------------------------------------------------------- -typedef enum { - eRNBRunLoopModeInvalid = 0, - eRNBRunLoopModeGetStartModeFromRemoteProtocol, - eRNBRunLoopModeInferiorExecuting, - eRNBRunLoopModeExit -} RNBRunLoopMode; - -//---------------------------------------------------------------------- -// Global Variables -//---------------------------------------------------------------------- -RNBRemoteSP g_remoteSP; -int g_disable_aslr = 0; -int g_isatty = 0; - -#define RNBLogSTDOUT(fmt, ...) \ - do { \ - if (g_isatty) { \ - fprintf(stdout, fmt, ##__VA_ARGS__); \ - } else { \ - _DNBLog(0, fmt, ##__VA_ARGS__); \ - } \ - } while (0) -#define RNBLogSTDERR(fmt, ...) \ - do { \ - if (g_isatty) { \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - } else { \ - _DNBLog(0, fmt, ##__VA_ARGS__); \ - } \ - } while (0) - -//---------------------------------------------------------------------- -// Get our program path and arguments from the remote connection. -// We will need to start up the remote connection without a PID, get the -// arguments, wait for the new process to finish launching and hit its -// entry point, and then return the run loop mode that should come next. -//---------------------------------------------------------------------- -RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemoteSP &remoteSP) { - std::string packet; - - if (remoteSP.get() != NULL) { - RNBRemote *remote = remoteSP.get(); - RNBContext &ctx = remote->Context(); - uint32_t event_mask = RNBContext::event_read_packet_available; - - // Spin waiting to get the A packet. - while (1) { - DNBLogThreadedIf(LOG_RNB_MAX, - "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", - __FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf(LOG_RNB_MAX, - "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", - __FUNCTION__, event_mask, set_events); - - if (set_events & RNBContext::event_read_packet_available) { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket(&type); - - // check if we tried to attach to a process - if (type == RNBRemote::vattach || type == RNBRemote::vattachwait) { - if (err == rnb_success) - return eRNBRunLoopModeInferiorExecuting; - else { - RNBLogSTDERR("error: attach failed."); - return eRNBRunLoopModeExit; - } - } - - if (err == rnb_success) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Got success...", __FUNCTION__); - continue; - } else if (err == rnb_not_connected) { - RNBLogSTDERR("error: connection lost."); - return eRNBRunLoopModeExit; - } else { - // a catch all for any other gdb remote packets that failed - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", - __FUNCTION__); - continue; - } - - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - } else { - DNBLogThreadedIf(LOG_RNB_MINIMAL, - "%s Connection closed before getting \"A\" packet.", - __FUNCTION__); - return eRNBRunLoopModeExit; - } - } - } - return eRNBRunLoopModeExit; -} - -//---------------------------------------------------------------------- -// Watch for signals: -// SIGINT: so we can halt our inferior. (disabled for now) -// SIGPIPE: in case our child process dies -//---------------------------------------------------------------------- -nub_process_t g_pid; -int g_sigpipe_received = 0; -void signal_handler(int signo) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, - SysSignal::Name(signo)); - - switch (signo) { - // case SIGINT: - // DNBProcessKill (g_pid, signo); - // break; - - case SIGPIPE: - g_sigpipe_received = 1; - break; - } -} - -// Return the new run loop mode based off of the current process state -RNBRunLoopMode HandleProcessStateChange(RNBRemoteSP &remote, bool initialize) { - RNBContext &ctx = remote->Context(); - nub_process_t pid = ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", - __FUNCTION__); - return eRNBRunLoopModeExit; - } - nub_state_t pid_state = DNBProcessGetState(pid); - - DNBLogThreadedIf(LOG_RNB_MINIMAL, - "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, - (int)initialize, DNBStateAsString(pid_state)); - - switch (pid_state) { - case eStateInvalid: - case eStateUnloaded: - // Something bad happened - return eRNBRunLoopModeExit; - break; - - case eStateAttaching: - case eStateLaunching: - return eRNBRunLoopModeInferiorExecuting; - - case eStateSuspended: - case eStateCrashed: - case eStateStopped: - if (!initialize) { - // Compare the last stop count to our current notion of a stop count - // to make sure we don't notify more than once for a given stop. - nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); - bool pid_stop_count_changed = - ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); - if (pid_stop_count_changed) { - remote->FlushSTDIO(); - - if (ctx.GetProcessStopCount() == 1) { - DNBLogThreadedIf( - LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " - "pid_stop_count %zu (old %zu)) Notify??? no, " - "first stop...", - __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), - ctx.GetProcessStopCount(), prev_pid_stop_count); - } else { - - DNBLogThreadedIf( - LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " - "pid_stop_count %zu (old %zu)) Notify??? YES!!!", - __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), - ctx.GetProcessStopCount(), prev_pid_stop_count); - remote->NotifyThatProcessStopped(); - } - } else { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) " - "pid_state = %s pid_stop_count %zu " - "(old %zu)) Notify??? skipping...", - __FUNCTION__, (int)initialize, - DNBStateAsString(pid_state), ctx.GetProcessStopCount(), - prev_pid_stop_count); - } - } - return eRNBRunLoopModeInferiorExecuting; - - case eStateStepping: - case eStateRunning: - return eRNBRunLoopModeInferiorExecuting; - - case eStateExited: - remote->HandlePacket_last_signal(NULL); - return eRNBRunLoopModeExit; - case eStateDetached: - return eRNBRunLoopModeExit; - } - - // Catch all... - return eRNBRunLoopModeExit; -} -// This function handles the case where our inferior program is stopped and -// we are waiting for gdb remote protocol packets. When a packet occurs that -// makes the inferior run, we need to leave this function with a new state -// as the return code. -RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemoteSP &remote) { - DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - RNBContext &ctx = remote->Context(); - - // Init our mode and set 'is_running' based on the current process state - RNBRunLoopMode mode = HandleProcessStateChange(remote, true); - - while (ctx.ProcessID() != INVALID_NUB_PROCESS) { - - std::string set_events_str; - uint32_t event_mask = ctx.NormalEventBits(); - - if (!ctx.ProcessStateRunning()) { - // Clear the stdio bits if we are not running so we don't send any async - // packets - event_mask &= ~RNBContext::event_proc_stdio_available; - } - - // We want to make sure we consume all process state changes and have - // whomever is notifying us to wait for us to reset the event bit before - // continuing. - // ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); - - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) ...", - __FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf(LOG_RNB_EVENTS, - "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", - __FUNCTION__, event_mask, set_events, - ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) { - if ((set_events & RNBContext::event_proc_thread_exiting) || - (set_events & RNBContext::event_proc_stdio_available)) { - remote->FlushSTDIO(); - } - - if (set_events & RNBContext::event_read_packet_available) { - // handleReceivedPacket will take care of resetting the - // event_read_packet_available events when there are no more... - set_events ^= RNBContext::event_read_packet_available; - - if (ctx.ProcessStateRunning()) { - if (remote->HandleAsyncPacket() == rnb_not_connected) { - // TODO: connect again? Exit? - } - } else { - if (remote->HandleReceivedPacket() == rnb_not_connected) { - // TODO: connect again? Exit? - } - } - } - - if (set_events & RNBContext::event_proc_state_changed) { - mode = HandleProcessStateChange(remote, false); - ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); - set_events ^= RNBContext::event_proc_state_changed; - } - - if (set_events & RNBContext::event_proc_thread_exiting) { - mode = eRNBRunLoopModeExit; - } - - if (set_events & RNBContext::event_read_thread_exiting) { - // Out remote packet receiving thread exited, exit for now. - if (ctx.HasValidProcessID()) { - // TODO: We should add code that will leave the current process - // in its current state and listen for another connection... - if (ctx.ProcessStateRunning()) { - DNBProcessKill(ctx.ProcessID()); - } - } - mode = eRNBRunLoopModeExit; - } - } - - // Reset all event bits that weren't reset for now... - if (set_events != 0) - ctx.Events().ResetEvents(set_events); - - if (mode != eRNBRunLoopModeInferiorExecuting) - break; - } - - return mode; -} - -void ASLLogCallback(void *baton, uint32_t flags, const char *format, - va_list args) { -#if 0 - vprintf(format, args); -#endif -} - -extern "C" int debug_server_main(int fd) { -#if 1 - g_isatty = 0; -#else - g_isatty = ::isatty(STDIN_FILENO); - - DNBLogSetDebug(1); - DNBLogSetVerbose(1); - DNBLogSetLogMask(-1); - DNBLogSetLogCallback(ASLLogCallback, NULL); -#endif - - signal(SIGPIPE, signal_handler); - - g_remoteSP.reset(new RNBRemote); - - RNBRemote *remote = g_remoteSP.get(); - if (remote == NULL) { - RNBLogSTDERR("error: failed to create a remote connection class\n"); - return -1; - } - - RNBRunLoopMode mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; - - while (mode != eRNBRunLoopModeExit) { - switch (mode) { - case eRNBRunLoopModeGetStartModeFromRemoteProtocol: - if (g_remoteSP->Comm().useFD(fd) == rnb_success) { - RNBLogSTDOUT("Starting remote data thread.\n"); - g_remoteSP->StartReadRemoteDataThread(); - - RNBLogSTDOUT("Waiting for start mode from remote.\n"); - mode = RNBRunLoopGetStartModeFromRemote(g_remoteSP); - } else { - mode = eRNBRunLoopModeExit; - } - break; - - case eRNBRunLoopModeInferiorExecuting: - mode = RNBRunLoopInferiorExecuting(g_remoteSP); - break; - - default: - mode = eRNBRunLoopModeExit; - break; - - case eRNBRunLoopModeExit: - break; - } - } - - g_remoteSP->StopReadRemoteDataThread(); - g_remoteSP->Context().SetProcessID(INVALID_NUB_PROCESS); - - return 0; -} diff --git a/tools/debugserver/source/libdebugserver.h b/tools/debugserver/source/libdebugserver.h deleted file mode 100644 index 2576e269ee60..000000000000 --- a/tools/debugserver/source/libdebugserver.h +++ /dev/null @@ -1,15 +0,0 @@ -//===-- libdebugserver.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef debugserver_libdebugserver_h -#define debugserver_libdebugserver_h - -int debug_server_main(int fd); - -#endif |