2017-02-18 22:57:01 +00:00
$ NetBSD $
2017-02-19 05:48:54 +00:00
- - - plugins / DebuggerCore / unix / netbsd / DebuggerCore . cpp . orig 2017 - 02 - 19 02 : 09 : 05.311209498 + 0000
2017-02-18 22:57:01 +00:00
+ + + plugins / DebuggerCore / unix / netbsd / DebuggerCore . cpp
2017-02-19 05:48:54 +00:00
@ @ - 0 , 0 + 1 , 593 @ @
2017-02-18 22:57:01 +00:00
+ /*
+ Copyright ( C ) 2006 - 2015 Evan Teran
+ evan . teran @ gmail . com
+
+ This program is free software : you can redistribute it and / or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation , either version 2 of the License , or
+ ( at your option ) any later version .
+
+ This program is distributed in the hope that it will be useful ,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
+ GNU General Public License for more details .
+
+ You should have received a copy of the GNU General Public License
+ along with this program . If not , see < http : //www.gnu.org/licenses/>.
+ */
+
2017-02-19 02:05:29 +00:00
+
+ // TODO(eteran): research usage of process_vm_readv, process_vm_writev
+
2017-02-18 22:57:01 +00:00
+ # include " DebuggerCore.h "
2017-02-19 02:05:29 +00:00
+ # include " Configuration.h "
+ # include " FeatureDetect.h "
+ # include " MemoryRegions.h "
+ # include " PlatformCommon.h "
2017-02-18 22:57:01 +00:00
+ # include " PlatformEvent.h "
2017-02-19 02:05:29 +00:00
+ # include " PlatformProcess.h "
2017-02-18 22:57:01 +00:00
+ # include " PlatformRegion.h "
+ # include " PlatformState.h "
2017-02-19 02:05:29 +00:00
+ # include " DialogMemoryAccess.h "
2017-02-18 22:57:01 +00:00
+ # include " State.h "
2017-02-19 02:05:29 +00:00
+ # include " edb.h "
2017-02-18 22:57:01 +00:00
+ # include " string_hash.h "
+
+ # include < QDebug >
2017-02-19 02:05:29 +00:00
+ # include < QDir >
+ # include < QSettings >
2017-02-18 22:57:01 +00:00
+
+ # include < cerrno >
+ # include < cstring >
+
2017-02-19 05:48:54 +00:00
+ # include < sys / param . h >
+ # include < sys / types . h >
+ # include < sys / sysctl . h >
2017-02-18 22:57:01 +00:00
+ # include < sys / ptrace . h >
2017-02-19 02:05:29 +00:00
+ # include < sys / mman . h >
2017-02-18 22:57:01 +00:00
+ # include < sys / wait . h >
2017-02-19 05:48:54 +00:00
+ # include < cpuid . h >
+
2017-02-18 22:57:01 +00:00
+ # include < unistd . h >
+
2017-02-19 02:05:29 +00:00
+ namespace DebuggerCorePlugin {
2017-02-18 22:57:01 +00:00
+
+ namespace {
+
2017-02-19 02:05:29 +00:00
+ const edb : : address_t PageSize = getpagesize ( ) ;
+
+ //------------------------------------------------------------------------------
+ // Name: is_numeric
+ // Desc: returns true if the string only contains decimal digits
+ //------------------------------------------------------------------------------
+ bool is_numeric ( const QString & s ) {
+ for ( QChar ch : s ) {
+ if ( ! ch . isDigit ( ) ) {
+ return false ;
+ }
+ }
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ return true ;
+ }
+
+ bool in64BitSegment ( ) {
+ bool edbIsIn64BitSegment ;
+ // Check that we're running in 64 bit segment: this can be in cases
+ // of LP64 and ILP32 programming models, so we can't rely on sizeof(void*)
+ asm ( R " (
+ . byte 0x33 , 0xc0 # XOR EAX , EAX
+ . byte 0x48 # DEC EAX for 32 bit , REX prefix for 64 bit
+ . byte 0xff , 0xc0 # INC EAX for 32 bit , INC RAX due to REX . W in 64 bit
+ ) " : " = a " (edbIsIn64BitSegment));
+ return edbIsIn64BitSegment ;
+ }
+
+ bool os64Bit ( bool edbIsIn64BitSegment ) {
+ bool osIs64Bit ;
+ if ( edbIsIn64BitSegment )
+ osIs64Bit = true ;
+ else {
+ // We want to be really sure the OS is 32 bit, so we can't rely on such easy
+ // to (even unintentionally) fake mechanisms as uname(2) (e.g. see setarch(8))
+ asm ( R " (.intel_syntax noprefix
+ mov eax , cs
+ cmp ax , 0x23 # this value is set for 32 - bit processes on 64 - bit kernel
+ mov ah , 0 # not sure this is really needed : usually the compiler will do
+ # MOVZX EAX , AL , but we have to be certain the result is correct
+ sete al
+ . att_syntax # restore default syntax
+ ) " : " = a " (osIs64Bit));
2017-02-18 22:57:01 +00:00
+ }
2017-02-19 02:05:29 +00:00
+ return osIs64Bit ;
2017-02-18 22:57:01 +00:00
+ }
2017-02-19 02:05:29 +00:00
+
+
+
+
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name: DebuggerCore
+ // Desc: constructor
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ DebuggerCore : : DebuggerCore ( ) :
+ binary_info_ ( nullptr ) ,
+ process_ ( 0 ) ,
+ pointer_size_ ( sizeof ( void * ) ) ,
+ edbIsIn64BitSegment ( in64BitSegment ( ) ) ,
+ osIs64Bit ( os64Bit ( edbIsIn64BitSegment ) ) ,
+ USER_CS_32 ( osIs64Bit ? 0x23 : 0x73 ) ,
+ USER_CS_64 ( osIs64Bit ? 0x33 : 0xfff8 ) , // RPL 0 can't appear in user segment registers, so 0xfff8 is safe
+ USER_SS ( osIs64Bit ? 0x2b : 0x7b )
+ {
+ qDebug ( ) < < " EDB is in " < < ( edbIsIn64BitSegment ? " 64 " : " 32 " ) < < " bit segment " ;
+ qDebug ( ) < < " OS is " < < ( osIs64Bit ? " 64 " : " 32 " ) < < " bit " ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: has_extension
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
+ bool DebuggerCore : : has_extension ( quint64 ext ) const {
2017-02-19 02:05:29 +00:00
+
+ const auto mmxHash = edb : : string_hash ( " MMX " ) ;
+ const auto xmmHash = edb : : string_hash ( " XMM " ) ;
+ const auto ymmHash = edb : : string_hash ( " YMM " ) ;
+ if ( EDB_IS_64_BIT & & ( ext = = xmmHash | | ext = = mmxHash ) )
+ return true ;
+
+ quint32 eax ;
+ quint32 ebx ;
+ quint32 ecx ;
+ quint32 edx ;
+ __cpuid ( 1 , eax , ebx , ecx , edx ) ;
+
+ switch ( ext ) {
+ case mmxHash :
+ return ( edx & bit_MMX ) ;
+ case xmmHash :
+ return ( edx & bit_SSE ) ;
+ case ymmHash :
+ {
+ // Check OSXSAVE and AVX feature flags
+ if ( ( ecx & 0x18000000 ) ! = 0x18000000 )
+ return false ;
+ // Get XCR0, must be exactly after OSXSAVE feature check, otherwise #UD
+ asm volatile ( " xgetbv " : " =a " ( eax ) , " =d " ( edx ) : " c " ( 0 ) ) ;
+ // Check that the OS has enabled XMM and YMM state support
+ if ( ( eax & 0x6 ) ! = 0x6 )
+ return false ;
+ return true ;
+ }
+ default :
+ return false ;
+ }
+
2017-02-18 22:57:01 +00:00
+ return false ;
+ }
+
+ //------------------------------------------------------------------------------
+ // Name: page_size
+ // Desc: returns the size of a page on this system
+ //------------------------------------------------------------------------------
+ edb : : address_t DebuggerCore : : page_size ( ) const {
2017-02-19 02:05:29 +00:00
+ return PageSize ;
+ }
+
+ std : : size_t DebuggerCore : : pointer_size ( ) const {
+ return pointer_size_ ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name: ~DebuggerCore
2017-02-19 02:05:29 +00:00
+ // Desc: destructor
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
+ DebuggerCore : : ~ DebuggerCore ( ) {
2017-02-19 02:05:29 +00:00
+ end_debug_session ( ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: ptrace_getsiginfo
+ // Desc:
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ long DebuggerCore : : ptrace_getsiginfo ( edb : : pid_t pid , ptrace_siginfo_t * siginfo ) {
+ Q_ASSERT ( siginfo ! = 0 ) ;
+ return ptrace ( PT_GET_SIGINFO , pid , siginfo , sizeof ( struct ptrace_siginfo ) ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: ptrace_traceme
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ long DebuggerCore : : ptrace_traceme ( ) {
+ return ptrace ( PT_TRACE_ME , 0 , NULL , 0 ) ;
+ }
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ //------------------------------------------------------------------------------
+ // Name: ptrace_continue
+ // Desc:
+ //------------------------------------------------------------------------------
+ long DebuggerCore : : ptrace_continue ( edb : : pid_t pid , long status ) {
+ Q_ASSERT ( pid ! = 0 ) ;
+ return ptrace ( PT_CONTINUE , pid , ( void * ) 1 , status ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: ptrace_step
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ long DebuggerCore : : ptrace_step ( edb : : pid_t pid , long status ) {
+ Q_ASSERT ( pid ! = 0 ) ;
+ return ptrace ( PT_STEP , pid , ( void * ) 1 , status ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: handle_event
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ IDebugEvent : : const_pointer DebuggerCore : : handle_event ( edb : : pid_t pid , int status ) {
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ // was it a thread exit event?
+ if ( WIFEXITED ( status ) ) {
2017-02-18 22:57:01 +00:00
+ threads_ . clear ( ) ;
2017-02-19 02:05:29 +00:00
+ return nullptr ;
2017-02-18 22:57:01 +00:00
+ }
+
2017-02-19 02:05:29 +00:00
+ auto e = std : : make_shared < PlatformEvent > ( ) ;
+
2017-02-19 05:48:54 +00:00
+ e - > pid_ = pid ;
2017-02-19 02:05:29 +00:00
+ e - > status_ = status ;
2017-02-19 05:48:54 +00:00
+ ptrace_getsiginfo ( pid , & e - > siginfo_ ) ;
2017-02-19 02:05:29 +00:00
+
+ return e ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: wait_debug_event
+ // Desc: waits for a debug event, msecs is a timeout
+ // it will return false if an error or timeout occurs
+ //------------------------------------------------------------------------------
+ IDebugEvent : : const_pointer DebuggerCore : : wait_debug_event ( int msecs ) {
+
+ if ( process_ ) {
+ if ( ! native : : wait_for_sigchld ( msecs ) ) {
+ int status ;
2017-02-19 05:48:54 +00:00
+ const edb : : pid_t wpid = native : : waitpid ( pid ( ) , & status , __WALL | WNOHANG ) ;
+ if ( wpid > 0 ) {
+ return handle_event ( pid ( ) , status ) ;
2017-02-19 02:05:29 +00:00
+ }
+ }
2017-02-18 22:57:01 +00:00
+ }
2017-02-19 02:05:29 +00:00
+ return nullptr ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: attach
+ // Desc:
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : attach ( edb : : pid_t pid ) {
+
+ static const QString statusOK { } ;
+
+ end_debug_session ( ) ;
+
+ lastMeansOfCapture = MeansOfCapture : : Attach ;
+
+ // create this, so the threads created can refer to it
+ process_ = new PlatformProcess ( this , pid ) ;
+
2017-02-19 05:48:54 +00:00
+ int lastErr = ptrace ( PT_ATTACH , pid , NULL , 0 ) ; // Fail early if we are going to
2017-02-19 02:05:29 +00:00
+ if ( lastErr ) return std : : strerror ( lastErr ) ;
+
2017-02-19 05:48:54 +00:00
+ pid_ = pid ;
+ binary_info_ = edb : : v1 : : get_binary_info ( edb : : v1 : : primary_code_region ( ) ) ;
+ detectDebuggeeBitness ( ) ;
+ return statusOK ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: detach
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ void DebuggerCore : : detach ( ) {
+ if ( process_ ) {
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ clear_breakpoints ( ) ;
+
2017-02-19 05:48:54 +00:00
+ ptrace ( PT_DETACH , pid ( ) , NULL , 0 ) ;
2017-02-19 02:05:29 +00:00
+
+ delete process_ ;
+ process_ = nullptr ;
+
+ reset ( ) ;
2017-02-18 22:57:01 +00:00
+ }
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: kill
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ void DebuggerCore : : kill ( ) {
2017-02-18 22:57:01 +00:00
+ if ( attached ( ) ) {
2017-02-19 02:05:29 +00:00
+ clear_breakpoints ( ) ;
+
2017-02-19 05:48:54 +00:00
+ ptrace ( PT_KILL , pid ( ) , NULL , 0 ) ;
2017-02-19 02:05:29 +00:00
+
+ native : : waitpid ( pid ( ) , 0 , __WALL ) ;
+
+ delete process_ ;
+ process_ = 0 ;
+
+ reset ( ) ;
+ }
+ }
+
+ void DebuggerCore : : detectDebuggeeBitness ( ) {
2017-02-19 05:48:54 +00:00
+ # if defined ( __i386__ )
+ qDebug ( ) < < " Debuggee is now 32 bit " ;
+ CapstoneEDB : : init ( CapstoneEDB : : Architecture : : ARCH_X86 ) ;
+ # elif defined ( __x86_64__ )
+ qDebug ( ) < < " Debuggee is now 64 bit " ;
+ CapstoneEDB : : init ( CapstoneEDB : : Architecture : : ARCH_AMD64 ) ;
+ # else
+ # error portme
+ # endif
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name: open
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : open ( const QString & path , const QString & cwd , const QList < QByteArray > & args , const QString & tty ) {
+
+ static const QString statusOK { } ;
+
+ end_debug_session ( ) ;
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ lastMeansOfCapture = MeansOfCapture : : Launch ;
+
2017-02-19 05:48:54 +00:00
+ static std : : size_t sharedMemSize = getpagesize ( ) ;
2017-02-19 02:05:29 +00:00
+ const auto sharedMem = static_cast < QChar * > ( : : mmap ( nullptr , sharedMemSize , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS , - 1 , 0 ) ) ;
+ std : : memset ( sharedMem , 0 , sharedMemSize ) ;
+
+ switch ( pid_t pid = fork ( ) ) {
2017-02-18 22:57:01 +00:00
+ case 0 :
2017-02-19 02:05:29 +00:00
+ {
2017-02-18 22:57:01 +00:00
+ // we are in the child now...
+
+ // set ourselves (the child proc) up to be traced
2017-02-19 02:05:29 +00:00
+ ptrace_traceme ( ) ;
2017-02-18 22:57:01 +00:00
+
+ // redirect it's I/O
+ if ( ! tty . isEmpty ( ) ) {
+ FILE * const std_out = freopen ( qPrintable ( tty ) , " r+b " , stdout ) ;
+ FILE * const std_in = freopen ( qPrintable ( tty ) , " r+b " , stdin ) ;
+ FILE * const std_err = freopen ( qPrintable ( tty ) , " r+b " , stderr ) ;
+
+ Q_UNUSED ( std_out ) ;
+ Q_UNUSED ( std_in ) ;
+ Q_UNUSED ( std_err ) ;
+ }
+
+ // do the actual exec
2017-02-19 02:05:29 +00:00
+ const QString error = execute_process ( path , cwd , args ) ;
+ static_assert ( std : : is_trivially_copyable < QChar > : : value , " Can't copy string of QChar to shared memory " ) ;
+ std : : memcpy ( sharedMem , error . constData ( ) , std : : min ( sizeof ( QChar ) * error . size ( ) , sharedMemSize - sizeof ( QChar ) /*prevent overwriting of last null*/ ) ) ;
2017-02-18 22:57:01 +00:00
+
+ // we should never get here!
+ abort ( ) ;
+ break ;
2017-02-19 02:05:29 +00:00
+ }
2017-02-18 22:57:01 +00:00
+ case - 1 :
2017-02-19 02:05:29 +00:00
+ // error! for some reason we couldn't fork
+ reset ( ) ;
+ return QObject : : tr ( " Failed to fork " ) ;
2017-02-18 22:57:01 +00:00
+ default :
+ // parent
+ do {
2017-02-19 02:05:29 +00:00
+ reset ( ) ;
2017-02-18 22:57:01 +00:00
+
+ int status ;
2017-02-19 02:05:29 +00:00
+ const auto wpidRet = native : : waitpid ( pid , & status , __WALL ) ;
+ const QString childError ( sharedMem ) ;
+ : : munmap ( sharedMem , sharedMemSize ) ;
+
+ if ( wpidRet = = - 1 )
+ return QObject : : tr ( " waitpid() failed: %1 " ) . arg ( std : : strerror ( errno ) ) + ( childError . isEmpty ( ) ? " " : QObject : : tr ( " . \n Error returned by child: \n %1. " ) . arg ( childError ) ) ;
+
+ if ( WIFEXITED ( status ) )
+ return QObject : : tr ( " The child unexpectedly exited with code %1. Error returned by child: \n %2 " ) . arg ( WEXITSTATUS ( status ) ) . arg ( childError ) ;
+ if ( WIFSIGNALED ( status ) )
+ return QObject : : tr ( " The child was unexpectedly killed by signal %1. Error returned by child: \n %2 " ) . arg ( WTERMSIG ( status ) ) . arg ( childError ) ;
+
+ // This happens when exec failed, but just in case it's something another return some description.
+ if ( WIFSTOPPED ( status ) & & WSTOPSIG ( status ) = = SIGABRT )
+ return childError . isEmpty ( ) ? QObject : : tr ( " The child unexpectedly aborted " ) : childError ;
2017-02-18 22:57:01 +00:00
+
+ // the very first event should be a STOP of type SIGTRAP
+ if ( ! WIFSTOPPED ( status ) | | WSTOPSIG ( status ) ! = SIGTRAP ) {
2017-02-19 02:05:29 +00:00
+ end_debug_session ( ) ;
+ return QObject : : tr ( " First event after waitpid() should be a STOP of type SIGTRAP, but wasn't, instead status=0x%1 " )
+ . arg ( status , 0 , 16 ) + ( childError . isEmpty ( ) ? " " : QObject : : tr ( " . \n Error returned by child: \n %1. " ) . arg ( childError ) ) ;
+ }
+
+ // create the process
+ process_ = new PlatformProcess ( this , pid ) ;
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ pid_ = pid ;
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ detectDebuggeeBitness ( ) ;
+
+ return statusOK ;
+ } while ( 0 ) ;
+ break ;
+ }
2017-02-18 22:57:01 +00:00
+ }
+
2017-02-19 02:05:29 +00:00
+
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: last_means_of_capture
+ // Desc: Returns how the last process was captured to debug
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ DebuggerCore : : MeansOfCapture DebuggerCore : : last_means_of_capture ( ) {
+ return lastMeansOfCapture ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: reset
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ void DebuggerCore : : reset ( ) {
+ threads_ . clear ( ) ;
+ pid_ = 0 ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: create_state
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ IState * DebuggerCore : : create_state ( ) const {
+ return new PlatformState ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: enumerate_processes
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QMap < edb : : pid_t , IProcess : : pointer > DebuggerCore : : enumerate_processes ( ) const {
+ QMap < edb : : pid_t , IProcess : : pointer > ret ;
2017-02-18 22:57:01 +00:00
+
2017-02-19 05:48:54 +00:00
+ int err ;
+ : : kinfo_proc2 * result ;
+ int mib [ 6 ] ;
+ size_t length = 0 ;
+
+ mib [ 0 ] = CTL_KERN ;
+ mib [ 1 ] = KERN_PROC2 ;
+ mib [ 2 ] = KERN_PROC_ALL ;
+ mib [ 3 ] = 0 ;
+ mib [ 4 ] = sizeof ( struct kinfo_proc2 ) ;
+ retry :
+ mib [ 5 ] = 0 ;
+
+ err = sysctl ( mib , __arraycount ( mib ) , NULL , & length , NULL , 0 ) ;
+ if ( err = = - 1 )
+ return ret ;
+
+ result = ( : : kinfo_proc2 * ) malloc ( length ) ;
+ if ( result = = NULL )
+ return ret ;
+
+ mib [ 5 ] = length / sizeof ( struct kinfo_proc2 ) ;
+ err = sysctl ( mib , __arraycount ( mib ) , result , & length , NULL , 0 ) ;
+ if ( err = = - 1 ) {
+ if ( errno = = ENOMEM )
+ goto retry ;
+
+ free ( result ) ;
+ return ret ;
+ }
2017-02-18 22:57:01 +00:00
+
2017-02-19 05:48:54 +00:00
+ for ( size_t i = 0 ; i < length / sizeof ( kinfo_proc2 ) ; i + + ) {
+ const edb : : pid_t pid = result [ i ] . p_pid ;
+ ret . insert ( pid , std : : make_shared < PlatformProcess > ( const_cast < DebuggerCore * > ( this ) , pid ) ) ;
2017-02-18 22:57:01 +00:00
+ }
+
2017-02-19 05:48:54 +00:00
+ free ( result ) ;
+
2017-02-19 02:05:29 +00:00
+ return ret ;
2017-02-18 22:57:01 +00:00
+ }
+
2017-02-19 02:05:29 +00:00
+
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
+ // Name:
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ edb : : pid_t DebuggerCore : : parent_pid ( edb : : pid_t pid ) const {
2017-02-18 22:57:01 +00:00
+
2017-02-19 02:05:29 +00:00
+ struct user_stat user_stat ;
+ int n = get_user_stat ( pid , & user_stat ) ;
+ if ( n > = 4 ) {
+ return user_stat . ppid ;
+ }
2017-02-18 22:57:01 +00:00
+
+ return 0 ;
+ }
+
+ //------------------------------------------------------------------------------
+ // Name:
2017-02-19 02:05:29 +00:00
+ // Desc: Returns EDB's native CPU type
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ quint64 DebuggerCore : : cpu_type ( ) const {
+ if ( EDB_IS_32_BIT )
+ return edb : : string_hash ( " x86 " ) ;
+ else
+ return edb : : string_hash ( " x86-64 " ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+
+ //------------------------------------------------------------------------------
+ // Name:
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : format_pointer ( edb : : address_t address ) const {
+ return address . toPointerString ( ) ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name:
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : stack_pointer ( ) const {
+ if ( edb : : v1 : : debuggeeIs32Bit ( ) )
+ return " esp " ;
+ else
+ return " rsp " ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name:
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : frame_pointer ( ) const {
+ if ( edb : : v1 : : debuggeeIs32Bit ( ) )
+ return " ebp " ;
+ else
+ return " rbp " ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
+ // Name:
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : instruction_pointer ( ) const {
+ if ( edb : : v1 : : debuggeeIs32Bit ( ) )
+ return " eip " ;
+ else
+ return " rip " ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: flag_register
+ // Desc: Returns the name of the flag register as a QString.
2017-02-18 22:57:01 +00:00
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ QString DebuggerCore : : flag_register ( ) const {
+ if ( edb : : v1 : : debuggeeIs32Bit ( ) )
+ return " eflags " ;
+ else
+ return " rflags " ;
2017-02-18 22:57:01 +00:00
+ }
+
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ // Name: process
2017-02-18 22:57:01 +00:00
+ // Desc:
+ //------------------------------------------------------------------------------
2017-02-19 02:05:29 +00:00
+ IProcess * DebuggerCore : : process ( ) const {
+ return process_ ;
2017-02-18 22:57:01 +00:00
+ }
+
+ # if QT_VERSION < 0x050000
+ Q_EXPORT_PLUGIN2 ( DebuggerCore , DebuggerCore )
+ # endif
+
+ }