summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/mcs/verbtoc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/superpmi/mcs/verbtoc.cpp')
-rw-r--r--src/ToolBox/superpmi/mcs/verbtoc.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/ToolBox/superpmi/mcs/verbtoc.cpp b/src/ToolBox/superpmi/mcs/verbtoc.cpp
new file mode 100644
index 0000000000..a99fbf0183
--- /dev/null
+++ b/src/ToolBox/superpmi/mcs/verbtoc.cpp
@@ -0,0 +1,108 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "verbtoc.h"
+#include "methodcontext.h"
+#include "methodcontextreader.h"
+#include "methodcontextiterator.h"
+#include "simpletimer.h"
+
+class TOCElementNode
+{
+public:
+ TOCElementNode *Next;
+ TOCElement tocElement;
+
+ TOCElementNode(int number, __int64 offset)
+ : Next(nullptr)
+ , tocElement(number, offset)
+ {
+ }
+};
+
+int verbTOC::DoWork(const char *nameOfInput)
+{
+ LogVerbose("Indexing from '%s' into '%s.mct'", nameOfInput, nameOfInput);
+
+ MethodContextIterator mci;
+ if (!mci.Initialize(nameOfInput))
+ return -1;
+
+ int savedCount = 0;
+
+ TOCElementNode *head = nullptr;
+ TOCElementNode *curElem = nullptr;
+
+ while (mci.MoveNext())
+ {
+ MethodContext* mc = mci.Current();
+
+ TOCElementNode *nxt = new TOCElementNode(mci.MethodContextNumber(), mci.CurrentPos());
+ mc->dumpMethodMD5HashToBuffer(nxt->tocElement.Hash, MD5_HASH_BUFFER_SIZE);
+
+ if (curElem != nullptr)
+ {
+ curElem->Next = nxt;
+ }
+ else
+ {
+ head = nxt;
+ }
+ curElem = nxt;
+ savedCount++;
+ }
+
+ size_t maxLen = strlen(nameOfInput) + 5;
+ char *nameOfOutput = (char*)_alloca(maxLen);
+ strcpy_s(nameOfOutput, maxLen, nameOfInput);
+ strcat_s(nameOfOutput, maxLen, ".mct");
+ HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFileOut == INVALID_HANDLE_VALUE)
+ {
+ LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
+ return -1;
+ }
+
+ DWORD written;
+ // Write out the signature "INDX" and then the element count
+ LARGE_INTEGER token;
+ token.u.LowPart = *(const int*)"INDX"; // cuz Type Safety is for languages that have good IO facilities
+ token.u.HighPart = savedCount;
+ if (!WriteFile(hFileOut, &token, sizeof(token), &written, nullptr) || written != sizeof(token))
+ {
+ LogError("Failed to write index header. GetLastError()=%u", GetLastError());
+ }
+
+ // Now just dump sizeof(TOCElement) byte chunks into the file.
+ // I could probably do this more efficiently, but I don't think it matters
+ DWORD chunkSize = sizeof(TOCElement);
+ for (curElem = head; curElem != nullptr; curElem = curElem->Next)
+ {
+ if (!WriteFile(hFileOut, &curElem->tocElement, chunkSize, &written, nullptr) || written != chunkSize)
+ {
+ LogError("Failed to write index element '%d'. GetLastError()=%u", curElem->tocElement.Number, GetLastError());
+ return -1;
+ }
+ }
+ // Now write out a final "INDX" to flag the end of the file...
+ if (!WriteFile(hFileOut, &token.u.LowPart, sizeof(token.u.LowPart), &written, nullptr) || (written != sizeof(token.u.LowPart)))
+ {
+ LogError("Failed to write index terminal. GetLastError()=%u", GetLastError());
+ }
+
+ LogInfo("Loaded %d, added %d to Table of Contents", mci.MethodContextNumber(), savedCount);
+
+ if (CloseHandle(hFileOut) == 0)
+ {
+ LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
+ return -1;
+ }
+
+ if (!mci.Destroy())
+ return -1;
+
+ return 0;
+}