diff options
author | Sergey Andreenko <seandree@microsoft.com> | 2018-07-27 18:44:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-27 18:44:32 -0700 |
commit | 6227652bcf2158df7f52be71106e9264b876fa2a (patch) | |
tree | ee3fb65cc5aaaef1f81724c09d18114a6b5d1685 /src | |
parent | 6510cdc02d791447afe9b766407a6b59135f420f (diff) | |
download | coreclr-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.cpp | 107 | ||||
-rw-r--r-- | src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h | 16 | ||||
-rw-r--r-- | src/inc/clr_std/string | 13 |
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 |