diff options
Diffstat (limited to 'lldb/tools/debugserver')
16 files changed, 441 insertions, 91 deletions
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index dd54c6a7b09..b7feeb3a249 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -1765,6 +1765,31 @@ DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *bu 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. //---------------------------------------------------------------------- diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 986cab9becb..c70ede989d5 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -18,8 +18,6 @@ #include <mach/thread_info.h> #include <string> -#define DNB_EXPORT __attribute__((visibility("default"))) - typedef bool (*DNBShouldCancelCallback) (void *); void DNBInitialize (); @@ -41,11 +39,11 @@ nub_process_t DNBProcessLaunch (const char *path, nub_launch_flavor_t launch_flavor, int disable_aslr, char *err_str, - size_t err_len) DNB_EXPORT; + size_t err_len); -nub_process_t DNBProcessAttach (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT; -nub_process_t DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT; -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) DNB_EXPORT; +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. @@ -54,97 +52,99 @@ nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavo // 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 DNBProcessKill (nub_process_t pid) DNB_EXPORT; -nub_size_t DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf) 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; +nub_bool_t DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions); +nub_bool_t DNBProcessHalt (nub_process_t pid); +nub_bool_t DNBProcessDetach (nub_process_t pid); +nub_bool_t DNBProcessSignal (nub_process_t pid, int signal); +nub_bool_t DNBProcessKill (nub_process_t pid); +nub_size_t DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf); +nub_size_t DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf); +nub_addr_t DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions); +nub_bool_t DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr); +int DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info); +std::string DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType); +nub_bool_t DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type); //---------------------------------------------------------------------- // 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; -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; -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; +nub_bool_t DNBProcessIsAlive (nub_process_t pid); +nub_state_t DNBProcessGetState (nub_process_t pid); +nub_bool_t DNBProcessGetExitStatus (nub_process_t pid, int *status); +nub_bool_t DNBProcessSetExitStatus (nub_process_t pid, int status); +nub_size_t DNBProcessGetNumThreads (nub_process_t pid); +nub_thread_t DNBProcessGetCurrentThread (nub_process_t pid); +nub_thread_t DNBProcessGetCurrentThreadMachPort (nub_process_t pid); +nub_thread_t DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid); +nub_thread_t DNBProcessGetThreadAtIndex (nub_process_t pid, nub_size_t thread_idx); +nub_bool_t DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid); +nub_addr_t DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid); +nub_bool_t DNBProcessSharedLibrariesUpdated (nub_process_t pid); +nub_size_t DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, DNBExecutableImageInfo **image_infos); +nub_bool_t DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton); +nub_bool_t DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton); +nub_addr_t DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib); +nub_size_t DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size); +nub_size_t DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size); +nub_size_t DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size); +nub_size_t DNBProcessGetStopCount (nub_process_t pid); +uint32_t DNBProcessGetCPUType (nub_process_t pid); //---------------------------------------------------------------------- // Process executable and arguments //---------------------------------------------------------------------- -const char * DNBProcessGetExecutablePath (nub_process_t pid) DNB_EXPORT; -const char * DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx) DNB_EXPORT; -nub_size_t DNBProcessGetArgumentCount (nub_process_t pid) DNB_EXPORT; +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) DNB_EXPORT; -void DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask) DNB_EXPORT; +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) DNB_EXPORT; -nub_bool_t DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info) DNB_EXPORT; -nub_state_t DNBThreadGetState (nub_process_t pid, nub_thread_t tid) DNB_EXPORT; -nub_bool_t DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value) DNB_EXPORT; -nub_bool_t DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) DNB_EXPORT; -nub_size_t DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len) DNB_EXPORT; -nub_size_t DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len) DNB_EXPORT; -nub_bool_t DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t set, const char *name, DNBRegisterValue *value) DNB_EXPORT; -nub_bool_t DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, DNBThreadStopInfo *stop_info) DNB_EXPORT; -const char * DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid) DNB_EXPORT; +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); //---------------------------------------------------------------------- // Breakpoint functions //---------------------------------------------------------------------- -nub_bool_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) DNB_EXPORT; -nub_bool_t DNBBreakpointClear (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; +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) DNB_EXPORT; -nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; -uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid) DNB_EXPORT; +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); const DNBRegisterSetInfo * - DNBGetRegisterSetInfo (nub_size_t *num_reg_sets) DNB_EXPORT; -nub_bool_t DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info) DNB_EXPORT; + DNBGetRegisterSetInfo (nub_size_t *num_reg_sets); +nub_bool_t DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info); //---------------------------------------------------------------------- // Printf style formatting for printing values in the inferior memory // space and registers. //---------------------------------------------------------------------- -nub_size_t DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t addr, FILE *file, const char *format) DNB_EXPORT; +nub_size_t DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t addr, FILE *file, const char *format); //---------------------------------------------------------------------- // Other static nub information calls. //---------------------------------------------------------------------- -const char * DNBStateAsString (nub_state_t state) DNB_EXPORT; -nub_bool_t DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size) DNB_EXPORT; +const char * DNBStateAsString (nub_state_t state); +nub_bool_t DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size); #endif diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h index 1c5c5b2db6f..e4f6bd2fada 100644 --- a/lldb/tools/debugserver/source/DNBArch.h +++ b/lldb/tools/debugserver/source/DNBArch.h @@ -58,10 +58,22 @@ public: static bool SetArchitecture (uint32_t cpu_type); + DNBArchProtocol () : + m_save_id(0) + { + + } + + virtual ~DNBArchProtocol () + { + + } virtual bool GetRegisterValue (int set, int reg, DNBRegisterValue *value) = 0; virtual bool SetRegisterValue (int set, int 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; @@ -85,6 +97,11 @@ public: protected: friend class MachThread; + uint32_t GetNextRegisterStateSaveID () + { + return ++m_save_id; + } + enum { Trans_Pending = 0, // Transaction is pending, and checkpoint state has been snapshotted. @@ -94,6 +111,9 @@ protected: 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 + }; diff --git a/lldb/tools/debugserver/source/DNBLog.h b/lldb/tools/debugserver/source/DNBLog.h index d019e2d1a1f..01add065abc 100644 --- a/lldb/tools/debugserver/source/DNBLog.h +++ b/lldb/tools/debugserver/source/DNBLog.h @@ -34,29 +34,27 @@ extern "C" { #if defined (DNBLOG_ENABLED) -#define DNB_EXPORT __attribute__((visibility("default"))) - -void _DNBLog(uint32_t flags, const char *format, ...) __attribute__ ((format (printf, 2, 3))) DNB_EXPORT; -void _DNBLogDebug (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogDebugVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogThreaded (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogThreadedIf (uint32_t mask, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))) DNB_EXPORT; -void _DNBLogError (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogFatalError (int err, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))) DNB_EXPORT; -void _DNBLogVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogWarning (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -void _DNBLogWarningVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) DNB_EXPORT; -bool DNBLogCheckLogBit (uint32_t bit) DNB_EXPORT; -uint32_t DNBLogSetLogMask (uint32_t mask) DNB_EXPORT; -uint32_t DNBLogGetLogMask () DNB_EXPORT; -void DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) DNB_EXPORT; -DNBCallbackLog DNBLogGetLogCallback () DNB_EXPORT; -bool DNBLogEnabled () DNB_EXPORT; -bool DNBLogEnabledForAny (uint32_t mask) DNB_EXPORT; -int DNBLogGetDebug () DNB_EXPORT; -void DNBLogSetDebug (int g) DNB_EXPORT; -int DNBLogGetVerbose () DNB_EXPORT; -void DNBLogSetVerbose (int g) DNB_EXPORT; +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) diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index c11d2c2ca82..f3a9d51c808 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -617,6 +617,18 @@ MachThread::SetRegisterContext (const void *buf, nub_size_t 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()) diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index 7e16d49b78c..c3121112980 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -92,6 +92,9 @@ public: 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) { } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index b5ce58d3438..adad95f2f7c 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -200,6 +200,25 @@ MachThreadList::SetRegisterContext (nub_thread_t tid, const void *buf, size_t bu 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 { diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h index 85097314b02..46bccfee8de 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h @@ -30,6 +30,8 @@ public: bool SetRegisterValue (nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, 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); diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 75282c5966c..88073afee00 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -1805,5 +1805,57 @@ DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) } +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 = GetFPUState(force)) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::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 UINT32_MAX; +} +bool +DNBArchMachARM::RestoreRegisterState (uint32_t save_id) +{ + SaveRegiterStates::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 = SetFPUState()) != KERN_SUCCESS) + { + DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::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; +} + + #endif // #if defined (__arm__) diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h index 7aeba6e9f18..4021fd5668e 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h @@ -18,6 +18,8 @@ #include "DNBArch.h" +#include <map> + class MachThread; class DNBArchMachARM : public DNBArchProtocol diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index f76ec0da021..9c708f31359 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -515,6 +515,10 @@ DNBArchImplI386::GetEXCState(bool force) 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); } @@ -1793,6 +1797,60 @@ DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len) } +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) +{ + SaveRegiterStates::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) diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 6b526f35914..ae9ef4980fc 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -20,16 +20,20 @@ #include "../HasAVX.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_2pc_trans_state(Trans_Done), + m_saved_register_states() { } virtual ~DNBArchImplI386() @@ -42,6 +46,9 @@ public: virtual bool SetRegisterValue(int set, int 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; @@ -240,6 +247,8 @@ protected: 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> SaveRegiterStates; + SaveRegiterStates m_saved_register_states; }; #endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 20e91961b47..0ceabc56547 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -447,7 +447,7 @@ 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()); + 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" @@ -2189,6 +2189,59 @@ DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len) 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) +{ + SaveRegiterStates::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) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index 895bfa97491..4302c6b319d 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -19,16 +19,20 @@ #include "../HasAVX.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_2pc_trans_state(Trans_Done), + m_saved_register_states() { } virtual ~DNBArchImplX86_64() @@ -36,10 +40,13 @@ public: } static void Initialize(); + virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); virtual bool SetRegisterValue(int set, int 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); @@ -246,6 +253,8 @@ protected: 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> SaveRegiterStates; + SaveRegiterStates m_saved_register_states; }; #endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 2a94c6cc55b..22db738cfea 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -191,6 +191,8 @@ RNBRemote::CreatePacketTable () // 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 previosly 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.")); @@ -2730,6 +2732,88 @@ RNBRemote::HandlePacket_DeallocateMemory (const char *p) 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"); + } + + StringExtractor 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) { diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 1d5cf012e0b..ca70c7f4271 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -119,7 +119,9 @@ public: watchpoint_support_info, // 'qWatchpointSupportInfo:' allocate_memory, // '_M' deallocate_memory, // '_m' - + save_register_state, // '_g' + restore_register_state, // '_G' + unknown_type } PacketEnum; @@ -216,6 +218,8 @@ public: 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); |

