|
Lines 11-16
Link Here
|
| 11 |
* |
11 |
* |
| 12 |
* $Id: ProfEnv.cpp,v 1.31 2008/12/08 13:37:37 jkubasta Exp $ |
12 |
* $Id: ProfEnv.cpp,v 1.31 2008/12/08 13:37:37 jkubasta Exp $ |
| 13 |
************************************************************************/ |
13 |
************************************************************************/ |
|
|
14 |
#ifndef LIN |
| 15 |
#pragma warning(disable:4786) // Add for bug 194081 to disable VC compiler warning when use STL |
| 16 |
#endif |
| 14 |
|
17 |
|
| 15 |
#include "ProfEnv.h" |
18 |
#include "ProfEnv.h" |
| 16 |
#include "log.h" |
19 |
#include "log.h" |
|
Lines 19-24
Link Here
|
| 19 |
using namespace Martini::MPI; |
22 |
using namespace Martini::MPI; |
| 20 |
using namespace Martini::OSA; |
23 |
using namespace Martini::OSA; |
| 21 |
using namespace Martini::JPIAgent; |
24 |
using namespace Martini::JPIAgent; |
|
|
25 |
using namespace std; // Add for bug 194081 |
| 22 |
|
26 |
|
| 23 |
CProfEnv::CProfEnv(){ |
27 |
CProfEnv::CProfEnv(){ |
| 24 |
m_pClassSData = 0; |
28 |
m_pClassSData = 0; |
|
Lines 61-66
Link Here
|
| 61 |
m_pAggStorage->Destroy(); |
65 |
m_pAggStorage->Destroy(); |
| 62 |
m_pSSMethodLeaveData_LockObject->Destroy(); |
66 |
m_pSSMethodLeaveData_LockObject->Destroy(); |
| 63 |
lockGetThreadInfoObject->Destroy(); |
67 |
lockGetThreadInfoObject->Destroy(); |
|
|
68 |
|
| 69 |
// Add for bug 194081 |
| 70 |
m_pShadowStackTracker = NULL; |
| 71 |
// Add for bug 194081 |
| 64 |
} |
72 |
} |
| 65 |
|
73 |
|
| 66 |
void |
74 |
void |
|
Lines 101-106
Link Here
|
| 101 |
delete m_pMethodSData; |
109 |
delete m_pMethodSData; |
| 102 |
} |
110 |
} |
| 103 |
m_pMethodSDataLockObject->Leave(); |
111 |
m_pMethodSDataLockObject->Leave(); |
|
|
112 |
|
| 113 |
// Add for bug 194081 |
| 114 |
if (m_pShadowStackTracker) |
| 115 |
{ |
| 116 |
delete m_pShadowStackTracker; |
| 117 |
m_pShadowStackTracker = NULL; |
| 118 |
} |
| 119 |
// Add for bug 194081 |
| 104 |
} |
120 |
} |
| 105 |
|
121 |
|
| 106 |
/* |
122 |
/* |
|
Lines 124-129
Link Here
|
| 124 |
} |
140 |
} |
| 125 |
libraryLoader->Destroy(); |
141 |
libraryLoader->Destroy(); |
| 126 |
(*ecpEnv)(profName, &ec_env); |
142 |
(*ecpEnv)(profName, &ec_env); |
|
|
143 |
|
| 144 |
// Add for bug 194081 |
| 145 |
m_pShadowStackTracker = new CCGShadowStackTracker(*this); |
| 146 |
if ( (NULL == m_pShadowStackTracker) || |
| 147 |
!(m_pShadowStackTracker->ValidateCGShadowStackTracker()) ) |
| 148 |
{ |
| 149 |
return MRTE_ERROR_FAIL; |
| 150 |
} |
| 151 |
// Add for bug 194081 |
| 152 |
|
| 127 |
return MRTE_RESULT_OSA_PLACE_HOLDER; |
153 |
return MRTE_RESULT_OSA_PLACE_HOLDER; |
| 128 |
} |
154 |
} |
| 129 |
|
155 |
|
|
Lines 209-214
Link Here
|
| 209 |
return ret; |
235 |
return ret; |
| 210 |
} |
236 |
} |
| 211 |
|
237 |
|
|
|
238 |
// Add for bug 194081 |
| 239 |
void |
| 240 |
CProfEnv::DeleteMethodsData() |
| 241 |
{ |
| 242 |
if (m_pMethodSData) |
| 243 |
{ |
| 244 |
delete m_pMethodSData; |
| 245 |
m_pMethodSData = NULL; |
| 246 |
} |
| 247 |
} |
| 248 |
// Add for bug 194081 |
| 249 |
|
| 212 |
void |
250 |
void |
| 213 |
CProfEnv::AddNewMethodData(SMethodInfo* pSMethodInfo, TId methodId, bool isPrinted) |
251 |
CProfEnv::AddNewMethodData(SMethodInfo* pSMethodInfo, TId methodId, bool isPrinted) |
| 214 |
{ |
252 |
{ |
|
Lines 791-793
Link Here
|
| 791 |
return MRTE_RESULT_OK; |
829 |
return MRTE_RESULT_OK; |
| 792 |
} |
830 |
} |
| 793 |
|
831 |
|
|
|
832 |
//================================================================== |
| 833 |
// Add for bug 194081 |
| 834 |
CCGShadowStackTracker::CCGShadowStackTracker(CProfEnv& profEnv) |
| 835 |
: m_refProfEnv(profEnv) |
| 836 |
{ |
| 837 |
m_lockVMStackDataMap = CreateThreadSync(); |
| 838 |
} |
| 839 |
|
| 840 |
CCGShadowStackTracker::~CCGShadowStackTracker() |
| 841 |
{ |
| 842 |
if (m_lockVMStackDataMap) |
| 843 |
{ |
| 844 |
m_lockVMStackDataMap->Destroy(); |
| 845 |
} |
| 846 |
} |
| 847 |
|
| 848 |
bool CCGShadowStackTracker::isNeedTrack() |
| 849 |
{ |
| 850 |
return ( |
| 851 |
((m_refProfEnv.ec_env)->isCGExecDetails()) && |
| 852 |
!((m_refProfEnv.ec_env)->isStandAlone()) |
| 853 |
); |
| 854 |
} |
| 855 |
|
| 856 |
bool CCGShadowStackTracker::ValidateCGShadowStackTracker() |
| 857 |
{ |
| 858 |
if (!isNeedTrack()) |
| 859 |
{ |
| 860 |
return true; |
| 861 |
} |
| 862 |
|
| 863 |
// You can add additional validate condition in this function |
| 864 |
return (NULL != m_lockVMStackDataMap); |
| 865 |
} |
| 866 |
|
| 867 |
void CCGShadowStackTracker::TrackVMShutdown() |
| 868 |
{ |
| 869 |
if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH))) |
| 870 |
{// For profilers' common events, just handle for call graph |
| 871 |
return; |
| 872 |
} |
| 873 |
|
| 874 |
if (!isNeedTrack()) |
| 875 |
{ |
| 876 |
return; |
| 877 |
} |
| 878 |
|
| 879 |
ReportLeftStackTrackDataMethodsLeave(); |
| 880 |
} |
| 881 |
|
| 882 |
TResult CCGShadowStackTracker::InitNewThreadInfoArray( |
| 883 |
SThreadInfoArray& threadInfoArray, |
| 884 |
int MAX_THREADS, int MAX_FRAMES) |
| 885 |
{ |
| 886 |
DestroyThreadInfoArray(threadInfoArray); |
| 887 |
|
| 888 |
threadInfoArray.pEntries = |
| 889 |
(SThreadInfoArrayEntry*)malloc(sizeof(SThreadInfoArrayEntry) * MAX_THREADS); |
| 890 |
if (NULL == threadInfoArray.pEntries) |
| 891 |
{ |
| 892 |
return MRTE_ERROR_OUT_OF_MEMORY; |
| 893 |
} |
| 894 |
|
| 895 |
threadInfoArray.uiSize = MAX_THREADS; |
| 896 |
memset(threadInfoArray.pEntries, 0, sizeof(SThreadInfoArrayEntry) * MAX_THREADS); |
| 897 |
|
| 898 |
unsigned int i = 0; |
| 899 |
for (i = 0; i < MAX_THREADS; i++) |
| 900 |
{ |
| 901 |
threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.uiSize = MAX_FRAMES; |
| 902 |
threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries = new SStackEntry[MAX_FRAMES]; |
| 903 |
|
| 904 |
if (NULL == threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries) |
| 905 |
{ |
| 906 |
DestroyThreadInfoArray(threadInfoArray); |
| 907 |
return MRTE_ERROR_OUT_OF_MEMORY; |
| 908 |
} |
| 909 |
|
| 910 |
memset(threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries, 0, |
| 911 |
sizeof(SStackEntry) * MAX_FRAMES); |
| 912 |
} |
| 913 |
|
| 914 |
return MRTE_RESULT_OK; |
| 915 |
} |
| 916 |
|
| 917 |
void CCGShadowStackTracker::DestroyThreadInfoArray( |
| 918 |
SThreadInfoArray& threadInfoArray) |
| 919 |
{ |
| 920 |
if (NULL != threadInfoArray.pEntries) |
| 921 |
{ |
| 922 |
for (unsigned int i = 0; i < threadInfoArray.uiSize; i++) |
| 923 |
{ |
| 924 |
if (NULL != threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries) |
| 925 |
{ |
| 926 |
delete [](threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries); |
| 927 |
} |
| 928 |
} |
| 929 |
|
| 930 |
free(threadInfoArray.pEntries); |
| 931 |
} |
| 932 |
|
| 933 |
threadInfoArray.uiSize = 0; |
| 934 |
threadInfoArray.uiActualSize = 0; |
| 935 |
} |
| 936 |
|
| 937 |
TResult CCGShadowStackTracker::GetInitialShadowStackTraces( |
| 938 |
SThreadInfoArray& threadInfoArray) |
| 939 |
{ |
| 940 |
// Suspend all VM threads and Get all threads stack traces |
| 941 |
TResult res = (m_refProfEnv.m_pMpiApi)->SuspendVM(); |
| 942 |
if (MRTE_FAILED(res)) |
| 943 |
{ |
| 944 |
LOG_ERROR("Can not suspend VM when try to get shadow stack sanpshot") |
| 945 |
return res; |
| 946 |
} |
| 947 |
|
| 948 |
// TODO: This fixed thread num and frame num is a limit, referring to original AttachEvent.cpp |
| 949 |
int MAX_THREADS = 100; |
| 950 |
int MAX_FRAMES = 100; |
| 951 |
|
| 952 |
res = InitNewThreadInfoArray(threadInfoArray, MAX_THREADS, MAX_FRAMES); |
| 953 |
if (MRTE_FAILED(res)) |
| 954 |
{ |
| 955 |
(m_refProfEnv.m_pMpiApi)->ResumeVM(); |
| 956 |
return res; |
| 957 |
} |
| 958 |
|
| 959 |
res = (m_refProfEnv.m_pMpiApi)->GetAllThreadsInfo(m_refProfEnv.m_clientId, MAX_FRAMES, |
| 960 |
DR_VM_RELATIVE_STACK_TRACE, &threadInfoArray); |
| 961 |
if (MRTE_FAILED(res)) |
| 962 |
{ |
| 963 |
(m_refProfEnv.m_pMpiApi)->ResumeVM(); |
| 964 |
DestroyThreadInfoArray(threadInfoArray); |
| 965 |
} |
| 966 |
|
| 967 |
return res; |
| 968 |
} |
| 969 |
|
| 970 |
void CCGShadowStackTracker::ReportThreadsStart(SThreadInfoArray& threadInfoArray) |
| 971 |
{ |
| 972 |
for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++) |
| 973 |
{ |
| 974 |
SThreadInfoArrayEntry* pThread = &(threadInfoArray.pEntries[threadIdx]); |
| 975 |
|
| 976 |
// Clear outdated data |
| 977 |
m_refProfEnv.m_Tickets.ReleaseTicket(pThread->threadId); |
| 978 |
m_refProfEnv.m_Tickets.DeleteThread(pThread->threadId); |
| 979 |
|
| 980 |
// Add new data info |
| 981 |
m_refProfEnv.m_Tickets.AddNewThread(pThread->threadId); |
| 982 |
|
| 983 |
m_refProfEnv.GetThreadInfo(m_refProfEnv.m_clientId, pThread->threadId, |
| 984 |
DR_THREAD_INFO | DR_THREAD_ELAPSED_TIME | DR_THREAD_CPU_TIME, &(pThread->threadInfo)); |
| 985 |
|
| 986 |
if (m_refProfEnv.m_profilerIsActive) |
| 987 |
{ |
| 988 |
(m_refProfEnv.ec_env)->PrintThreadStartElement(pThread->threadId, 0, |
| 989 |
&(pThread->threadInfo)); |
| 990 |
} |
| 991 |
else |
| 992 |
{ |
| 993 |
m_refProfEnv.StoreThreadEvent(pThread->threadId, THREAD_START_EVENT, |
| 994 |
&(pThread->threadInfo), 0); |
| 995 |
} |
| 996 |
} |
| 997 |
} |
| 998 |
|
| 999 |
void CCGShadowStackTracker::ReportMethodEnter(TId threadId, SThreadInfo* pThreadInfo, TId methodId) |
| 1000 |
{ |
| 1001 |
// Get classId according to methodId |
| 1002 |
SMethodInfo methodInfo = {0}; |
| 1003 |
TResult iRes = (m_refProfEnv.m_pMpiApi)->GetMethodInfo(m_refProfEnv.m_clientId, |
| 1004 |
methodId, DR_CLASS_ID, &methodInfo); |
| 1005 |
LOG_ASSERT(iRes == MRTE_RESULT_OK); |
| 1006 |
LOG_ASSERT((methodInfo.validData & DR_CLASS_ID) != 0); |
| 1007 |
|
| 1008 |
// Just for Exec Details |
| 1009 |
m_refProfEnv.CheckMethodId(methodId); |
| 1010 |
|
| 1011 |
if (m_refProfEnv.m_profilerIsActive) |
| 1012 |
{// Profiler is in run mode |
| 1013 |
unsigned long ticket = m_refProfEnv.m_Tickets.GetNewTicket(threadId, |
| 1014 |
pThreadInfo->uiCpuNanos, true); |
| 1015 |
unsigned long stackDepth = m_refProfEnv.m_Tickets.GetStackDepth(threadId); |
| 1016 |
(m_refProfEnv.ec_env)->PrintMethodEntryElement(threadId, methodId, |
| 1017 |
methodInfo.classId, ticket, stackDepth); |
| 1018 |
} |
| 1019 |
else |
| 1020 |
{// Profiler is in pause mode |
| 1021 |
m_refProfEnv.m_Tickets.AddMethodEnterData(threadId, methodId, |
| 1022 |
methodInfo.classId, pThreadInfo->uiCpuNanos); |
| 1023 |
} |
| 1024 |
} |
| 1025 |
|
| 1026 |
void CCGShadowStackTracker::ReportMethodsEnter(SThreadInfoArray& threadInfoArray) |
| 1027 |
{ |
| 1028 |
for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++) |
| 1029 |
{ |
| 1030 |
TId threadId = threadInfoArray.pEntries[threadIdx].threadId; |
| 1031 |
SThreadInfo* pThreadInfo = &(threadInfoArray.pEntries[threadIdx].threadInfo); |
| 1032 |
|
| 1033 |
for (int stackTraceIdx = (pThreadInfo->vmOffsetStack).uiActualSize - 1; stackTraceIdx >= 0 ; |
| 1034 |
stackTraceIdx--) |
| 1035 |
{ |
| 1036 |
// Get methodId from stack trace info |
| 1037 |
SStackEntry* pStackEntry = &(pThreadInfo->vmOffsetStack.pStackEntries[stackTraceIdx]); |
| 1038 |
|
| 1039 |
ReportMethodEnter(threadId, pThreadInfo, pStackEntry->methodId); |
| 1040 |
} |
| 1041 |
} |
| 1042 |
} |
| 1043 |
|
| 1044 |
void CCGShadowStackTracker::SaveAllShadowStacksMethods(SThreadInfoArray& threadInfoArray) |
| 1045 |
{ |
| 1046 |
for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++) |
| 1047 |
{ |
| 1048 |
SThreadInfoArrayEntry* pThread = &(threadInfoArray.pEntries[threadIdx]); |
| 1049 |
CVMStackTrackData vmStacks; |
| 1050 |
vmStacks.threadId = pThread->threadId; |
| 1051 |
unsigned int stackTraceSize = |
| 1052 |
(pThread->threadInfo).vmOffsetStack.uiActualSize; |
| 1053 |
|
| 1054 |
for (int stackTraceIdx = stackTraceSize - 1; stackTraceIdx >= 0; stackTraceIdx--) |
| 1055 |
{ |
| 1056 |
vmStacks.shadowStack.push( |
| 1057 |
(pThread->threadInfo).vmOffsetStack.pStackEntries[stackTraceIdx].methodId); |
| 1058 |
} |
| 1059 |
|
| 1060 |
m_lockVMStackDataMap->Enter(); |
| 1061 |
m_VMStacktraceDataMap.insert( |
| 1062 |
std::pair<MPI::TId, CVMStackTrackData>(vmStacks.threadId, vmStacks)); |
| 1063 |
m_lockVMStackDataMap->Leave(); |
| 1064 |
} |
| 1065 |
} |
| 1066 |
|
| 1067 |
void CCGShadowStackTracker::TrackECAttach() |
| 1068 |
{ |
| 1069 |
if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH))) |
| 1070 |
{// For profilers' common events, just handle for call graph |
| 1071 |
return; |
| 1072 |
} |
| 1073 |
|
| 1074 |
if (!isNeedTrack()) |
| 1075 |
{ |
| 1076 |
return; |
| 1077 |
} |
| 1078 |
|
| 1079 |
SThreadInfoArray threadInfoArray = {0}; |
| 1080 |
TResult res = GetInitialShadowStackTraces(threadInfoArray); |
| 1081 |
if (MRTE_FAILED(res)) |
| 1082 |
{ |
| 1083 |
LOG_ERROR("Can not get VM thread stack traces info.") |
| 1084 |
return; |
| 1085 |
} |
| 1086 |
|
| 1087 |
// Report related events and get initial shadow stacks |
| 1088 |
ReportThreadsStart(threadInfoArray); |
| 1089 |
|
| 1090 |
ReportMethodsEnter(threadInfoArray); |
| 1091 |
|
| 1092 |
SaveAllShadowStacksMethods(threadInfoArray); |
| 1093 |
|
| 1094 |
DestroyThreadInfoArray(threadInfoArray); |
| 1095 |
(m_refProfEnv.m_pMpiApi)->ResumeVM(); |
| 1096 |
} |
| 1097 |
|
| 1098 |
void CCGShadowStackTracker::TrackECDetach() |
| 1099 |
{ |
| 1100 |
if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH))) |
| 1101 |
{// For profilers' common events, just handle for call graph |
| 1102 |
return; |
| 1103 |
} |
| 1104 |
|
| 1105 |
if (!isNeedTrack()) |
| 1106 |
{ |
| 1107 |
return; |
| 1108 |
} |
| 1109 |
|
| 1110 |
ReportLeftStackTrackDataMethodsLeave(); |
| 1111 |
} |
| 1112 |
|
| 1113 |
void CCGShadowStackTracker::ReportMethodLeave(TId threadId, TId methodId, |
| 1114 |
TTimeStamp uiCpuNanos) |
| 1115 |
{ |
| 1116 |
SMethodInfo methodInfo; |
| 1117 |
TResult iRes = (m_refProfEnv.m_pMpiApi)->GetMethodInfo(m_refProfEnv.m_clientId, |
| 1118 |
methodId, DR_CLASS_ID, &methodInfo); |
| 1119 |
LOG_ASSERT(iRes == MRTE_RESULT_OK); |
| 1120 |
LOG_ASSERT((methodInfo.validData & DR_CLASS_ID) != 0); |
| 1121 |
|
| 1122 |
// Just for Exec Details |
| 1123 |
U64 cpuTime = uiCpuNanos - m_refProfEnv.m_Tickets.GetCpuTime(threadId); |
| 1124 |
unsigned long ticket = m_refProfEnv.m_Tickets.ReleaseTicket(threadId); |
| 1125 |
|
| 1126 |
if (m_refProfEnv.m_profilerIsActive) |
| 1127 |
{ |
| 1128 |
(m_refProfEnv.ec_env)->PrintMethodExitElement(threadId, methodId, |
| 1129 |
methodInfo.classId, ticket, cpuTime); |
| 1130 |
} |
| 1131 |
else if (ticket != -1) |
| 1132 |
{ |
| 1133 |
m_refProfEnv.AddMethodLeaveData(threadId, methodId, methodInfo.classId, |
| 1134 |
ticket, cpuTime); |
| 1135 |
} |
| 1136 |
} |
| 1137 |
|
| 1138 |
void CCGShadowStackTracker::UpdateShadowStack(stack< TId >& tmpShadowStack, |
| 1139 |
stack< TId >& shadowStack, const SMethodEnterEventData& data) |
| 1140 |
{ |
| 1141 |
// Because normal stack is empty now, the tmpShadowStack must less or equal shadowStack |
| 1142 |
while (tmpShadowStack.size() < shadowStack.size()) |
| 1143 |
{// Geneate method leave events for shadow stack method |
| 1144 |
TId methodId = shadowStack.top(); |
| 1145 |
shadowStack.pop(); |
| 1146 |
ReportMethodLeave(data.threadId, methodId, data.uiCpuNanos); |
| 1147 |
} |
| 1148 |
} |
| 1149 |
|
| 1150 |
void CCGShadowStackTracker::TrackMethodEnter(SMethodEnterEventData &data) |
| 1151 |
{ |
| 1152 |
if (!isNeedTrack()) |
| 1153 |
{ |
| 1154 |
return; |
| 1155 |
} |
| 1156 |
|
| 1157 |
m_lockVMStackDataMap->Enter(); |
| 1158 |
map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId); |
| 1159 |
m_lockVMStackDataMap->Leave(); |
| 1160 |
|
| 1161 |
if (pos == m_VMStacktraceDataMap.end()) |
| 1162 |
{// Enter a new thread after attach, it has no shadow stack record and can be handled normally |
| 1163 |
return; |
| 1164 |
} |
| 1165 |
|
| 1166 |
CVMStackTrackData& refVmStacks = pos->second; |
| 1167 |
|
| 1168 |
if (refVmStacks.normalStack.empty()) |
| 1169 |
{ |
| 1170 |
SStackTrace_ stackTrace = {0}; |
| 1171 |
m_refProfEnv.GetStackTrace(data.threadId, &stackTrace); |
| 1172 |
|
| 1173 |
std::stack< MPI::TId > tmpShadowStack; |
| 1174 |
// Ignore the new entered method, CGProxy.EarlyMethodEnter and CGProxy.MethodEnter on the stack top |
| 1175 |
const int ignoredMethodNum = 3; |
| 1176 |
for (int stackTraceIdx = stackTrace.uiSize - 1; stackTraceIdx > ignoredMethodNum - 1; stackTraceIdx--) |
| 1177 |
{ |
| 1178 |
tmpShadowStack.push(stackTrace.pStackEntries[stackTraceIdx].methodId); |
| 1179 |
} |
| 1180 |
|
| 1181 |
UpdateShadowStack(tmpShadowStack, refVmStacks.shadowStack, data); |
| 1182 |
m_refProfEnv.FreeStackTrace(&stackTrace); |
| 1183 |
} |
| 1184 |
|
| 1185 |
refVmStacks.normalStack.push(data.methodId); |
| 1186 |
} |
| 1187 |
|
| 1188 |
// return value: If continue to handle the MethodLeave events |
| 1189 |
bool CCGShadowStackTracker::TrackMethodLeave(SMethodLeaveEventData &data) |
| 1190 |
{ |
| 1191 |
if (!isNeedTrack()) |
| 1192 |
{ |
| 1193 |
return true; |
| 1194 |
} |
| 1195 |
|
| 1196 |
m_lockVMStackDataMap->Enter(); |
| 1197 |
map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId); |
| 1198 |
m_lockVMStackDataMap->Leave(); |
| 1199 |
|
| 1200 |
if (pos == m_VMStacktraceDataMap.end()) |
| 1201 |
{// Enter a new thread after attach, it has no shadow stack record and can be handled normally |
| 1202 |
return true; |
| 1203 |
} |
| 1204 |
|
| 1205 |
CVMStackTrackData& refVmStacks = pos->second; |
| 1206 |
|
| 1207 |
if (refVmStacks.normalStack.empty()) |
| 1208 |
{// Method leave notification is generated by instrumet before reattach, ignore it |
| 1209 |
return false; |
| 1210 |
} |
| 1211 |
else |
| 1212 |
{ |
| 1213 |
refVmStacks.normalStack.pop(); |
| 1214 |
return true; |
| 1215 |
} |
| 1216 |
} |
| 1217 |
|
| 1218 |
void CCGShadowStackTracker::TrackThreadEnd(SThreadEventData &data) |
| 1219 |
{ |
| 1220 |
if (!isNeedTrack()) |
| 1221 |
{ |
| 1222 |
return; |
| 1223 |
} |
| 1224 |
|
| 1225 |
m_lockVMStackDataMap->Enter(); |
| 1226 |
map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId); |
| 1227 |
m_lockVMStackDataMap->Leave(); |
| 1228 |
|
| 1229 |
if (pos == m_VMStacktraceDataMap.end()) |
| 1230 |
{// Enter a new thread after attach, it has no shadow stack record and can be handled normally |
| 1231 |
return; |
| 1232 |
} |
| 1233 |
|
| 1234 |
CVMStackTrackData& refVmStacks = pos->second; |
| 1235 |
|
| 1236 |
// refVmStacks.shadowStack report method leave events |
| 1237 |
while (!refVmStacks.shadowStack.empty()) |
| 1238 |
{ |
| 1239 |
TId methodId = refVmStacks.shadowStack.top(); |
| 1240 |
refVmStacks.shadowStack.pop(); |
| 1241 |
ReportMethodLeave(data.threadId, methodId, m_refProfEnv.m_Tickets.GetCpuTime(data.threadId)); |
| 1242 |
} |
| 1243 |
} |
| 1244 |
|
| 1245 |
void CCGShadowStackTracker::ReportLeftStackTrackDataMethodsLeave() |
| 1246 |
{ |
| 1247 |
m_lockVMStackDataMap->Enter(); |
| 1248 |
|
| 1249 |
map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.begin(); |
| 1250 |
for(; pos != m_VMStacktraceDataMap.end(); pos++) |
| 1251 |
{ |
| 1252 |
CVMStackTrackData& refVmStacks = pos->second; |
| 1253 |
|
| 1254 |
while (!refVmStacks.normalStack.empty()) |
| 1255 |
{ |
| 1256 |
TId methodId = refVmStacks.normalStack.top(); |
| 1257 |
refVmStacks.normalStack.pop(); |
| 1258 |
ReportMethodLeave(pos->first, methodId, m_refProfEnv.m_Tickets.GetCpuTime(pos->first)); |
| 1259 |
} |
| 1260 |
|
| 1261 |
while (!refVmStacks.shadowStack.empty()) |
| 1262 |
{ |
| 1263 |
TId methodId = refVmStacks.shadowStack.top(); |
| 1264 |
refVmStacks.shadowStack.pop(); |
| 1265 |
ReportMethodLeave(pos->first, methodId, m_refProfEnv.m_Tickets.GetCpuTime(pos->first)); |
| 1266 |
} |
| 1267 |
} |
| 1268 |
m_lockVMStackDataMap->Leave(); |
| 1269 |
} |
| 1270 |
// Add for bug 194081 |