summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Andreenko <seandree@microsoft.com>2018-07-27 18:44:32 -0700
committerGitHub <noreply@github.com>2018-07-27 18:44:32 -0700
commit6227652bcf2158df7f52be71106e9264b876fa2a (patch)
treeee3fb65cc5aaaef1f81724c09d18114a6b5d1685 /src
parent6510cdc02d791447afe9b766407a6b59135f420f (diff)
downloadcoreclr-6227652bcf2158df7f52be71106e9264b876fa2a.tar.gz
coreclr-6227652bcf2158df7f52be71106e9264b876fa2a.tar.bz2
coreclr-6227652bcf2158df7f52be71106e9264b876fa2a.zip
spmi: exclude methods using a file with saved md5 hashes. (#18769)
* read md5, linear search for each method. * rewrite with HANDLE * fix linux * do not waste time dumping md5 if no methods exluded
Diffstat (limited to 'src')
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp107
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h16
-rw-r--r--src/inc/clr_std/string13
3 files changed, 131 insertions, 5 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp
index a978fa2c2e..ad9c126786 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp
@@ -116,6 +116,8 @@ MethodContextReader::MethodContextReader(
{
GetFileSizeEx(this->fileHandle, (PLARGE_INTEGER) & this->fileSize);
}
+
+ ReadExcludedMethods(mchFileName);
}
MethodContextReader::~MethodContextReader()
@@ -130,6 +132,8 @@ MethodContextReader::~MethodContextReader()
}
CloseHandle(this->mutex);
+
+ CleanExcludedMethods();
}
bool MethodContextReader::AcquireLock()
@@ -477,3 +481,106 @@ MethodContextBuffer MethodContextReader::GetSpecificMethodContext(unsigned int m
return MethodContextBuffer(-4);
}
}
+
+// Read the file with excluded methods hashes and save them.
+void MethodContextReader::ReadExcludedMethods(std::string mchFileName)
+{
+ excludedMethodsList = nullptr;
+
+ size_t suffix_offset = mchFileName.find_last_of('.');
+ if (suffix_offset == std::string::npos)
+ {
+ LogError("Failed to get file extension from %s", mchFileName.c_str());
+ return;
+ }
+ std::string suffix = mchFileName.substr(suffix_offset);
+ std::string excludeFileName = MethodContextReader::CheckForPairedFile(mchFileName, suffix.c_str(), ".exc");
+
+ if (excludeFileName.empty())
+ {
+ return;
+ }
+ HANDLE excludeFileHandle = OpenFile(excludeFileName.c_str());
+ if (excludeFileHandle != INVALID_HANDLE_VALUE)
+ {
+ __int64 excludeFileSizeLong;
+ GetFileSizeEx(excludeFileHandle, (PLARGE_INTEGER)&excludeFileSizeLong);
+ unsigned excludeFileSize = (unsigned)excludeFileSizeLong;
+
+ char* buffer = new char[excludeFileSize + 1];
+ DWORD bytesRead;
+ bool success = (ReadFile(excludeFileHandle, buffer, excludeFileSize, &bytesRead, NULL) == TRUE);
+ CloseHandle(excludeFileHandle);
+
+ if (!success || excludeFileSize != bytesRead)
+ {
+ LogError("Failed to read the exclude file.");
+ delete[] buffer;
+ return;
+ }
+
+ buffer[excludeFileSize] = 0;
+
+ int counter = 0;
+
+ char* curr = buffer;
+ while (*curr != 0)
+ {
+ while (isspace(*curr))
+ {
+ curr++;
+ }
+
+ std::string hash;
+ while (*curr != 0 && !isspace(*curr))
+ {
+ hash += *curr;
+ curr++;
+ }
+
+ if (hash.length() == MD5_HASH_BUFFER_SIZE - 1)
+ {
+ StringList* node = new StringList();
+ node->hash = hash;
+ node->next = excludedMethodsList;
+ excludedMethodsList = node;
+ counter++;
+ }
+ else
+ {
+ LogInfo("The exclude file contains wrong values: %s.", hash.c_str());
+ }
+ }
+ delete[] buffer;
+ LogInfo("Exclude file %s contains %d methods.", excludeFileName.c_str(), counter);
+ }
+}
+
+// Free memory used for excluded methods.
+void MethodContextReader::CleanExcludedMethods()
+{
+ while (excludedMethodsList != nullptr)
+ {
+ StringList* next = excludedMethodsList->next;
+ delete excludedMethodsList;
+ excludedMethodsList = next;
+ }
+}
+
+// Return should this method context be excluded from the replay or not.
+bool MethodContextReader::IsMethodExcluded(MethodContext* mc)
+{
+ if (excludedMethodsList != nullptr)
+ {
+ char md5HashBuf[MD5_HASH_BUFFER_SIZE] = {0};
+ mc->dumpMethodMD5HashToBuffer(md5HashBuf, MD5_HASH_BUFFER_SIZE);
+ for (StringList* node = excludedMethodsList; node != nullptr; node = node->next)
+ {
+ if (strcmp(node->hash.c_str(), md5HashBuf) == 0)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
index ab1c693219..41c77d2445 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
@@ -83,6 +83,13 @@ private:
int Offset;
int Increment;
+ struct StringList
+ {
+ StringList* next;
+ std::string hash;
+ };
+ StringList* excludedMethodsList;
+
// Binary search to get this method number from the index
// Returns -1 for not found, or -2 for not indexed
__int64 GetOffset(unsigned int methodNumber);
@@ -114,6 +121,9 @@ private:
// Do we have a valid index?
bool hasIndex();
+ void ReadExcludedMethods(std::string mchFileName);
+ void CleanExcludedMethods();
+
public:
MethodContextReader(const char* inputFileName,
const int* indexes = nullptr,
@@ -137,11 +147,7 @@ public:
}
// Return should this method context be excluded from the replay or not.
- bool IsMethodExcluded(MethodContext* mc)
- {
- // Right now it is just a stub.
- return false;
- }
+ bool IsMethodExcluded(MethodContext* mc);
};
#pragma pack(pop)
diff --git a/src/inc/clr_std/string b/src/inc/clr_std/string
index e4476a60c6..78a3d1bb60 100644
--- a/src/inc/clr_std/string
+++ b/src/inc/clr_std/string
@@ -146,6 +146,14 @@ public:
return (*this);
}
+ basic_string<T>& operator+=(value_type _Ch)
+ {
+ size_type oldsize = size(); // doesn't include null terminator
+ m_string[oldsize] = _Ch; // Replace the null terminator with the new symbol.
+ m_string.push_back(T()); // Return the replaced terminator again.
+ return (*this);
+ }
+
~basic_string()
{
// vector destructor does all the work
@@ -157,6 +165,11 @@ public:
return m_string.size() - 1; // Don't report the null terminator.
}
+ size_t length() const
+ {
+ return size();
+ }
+
T& operator[](size_t iIndex)
{
assert(iIndex < size() + 1); // allow looking at the null terminator