Enable SuperPMI asm diffs using CoreDisTools
authorBruce Forstall <brucefo@microsoft.com>
Fri, 18 Aug 2017 01:29:20 +0000 (18:29 -0700)
committerBruce Forstall <brucefo@microsoft.com>
Fri, 18 Aug 2017 01:40:11 +0000 (18:40 -0700)
Change SuperPMI to dynamically load coredistools.dll on demand.

Commit migrated from https://github.com/dotnet/coreclr/commit/c024d72af6e7110dab147b2ed3bd3808bacf9fe6

src/coreclr/src/ToolBox/superpmi/superpmi/CMakeLists.txt
src/coreclr/src/ToolBox/superpmi/superpmi/commandline.cpp
src/coreclr/src/ToolBox/superpmi/superpmi/commandline.h
src/coreclr/src/ToolBox/superpmi/superpmi/neardiffer.cpp
src/coreclr/src/ToolBox/superpmi/superpmi/neardiffer.h
src/coreclr/src/ToolBox/superpmi/superpmi/superpmi.cpp

index eb3f08a..5b9897e 100644 (file)
@@ -5,6 +5,7 @@ remove_definitions(-D_UNICODE)
 
 add_definitions(-DFEATURE_NO_HOST)
 add_definitions(-DSELF_NO_HOST)
+add_definitions(-DUSE_COREDISTOOLS)
 
 if(WIN32)
   #use static crt
@@ -14,10 +15,6 @@ endif(WIN32)
 include_directories(.)
 include_directories(../superpmi-shared)
 
-# When it is ready (the build works on all platforms, referencing the coredistools
-# package), define this:
-# add_definitions(-DUSE_COREDISTOOLS)
-
 set(SUPERPMI_SOURCES
     commandline.cpp
     coreclrcallbacks.cpp
index 8546afa..c77337f 100644 (file)
@@ -108,11 +108,16 @@ void CommandLine::DumpHelp(const char* program)
     printf("     Used by the assembly differences calculator. This specifies the target\n");
     printf("     architecture for cross-compilation. Currently allowed <target> value: arm64\n");
     printf("\n");
-#ifdef USE_COREDISTOOLS
     printf(" -coredistools\n");
     printf("     Use disassembly tools from the CoreDisTools library\n");
+#if defined(USE_MSVCDIS)
+    printf("     Default: use MSVCDIS.\n");
+#elif defined(USE_COREDISTOOLS)
+    printf("     Ignored: MSVCDIS is not available, so CoreDisTools will be used.\n");
+#else
+    printf("     Ignored: neither MSVCDIS nor CoreDisTools is available.\n");
+#endif
     printf("\n");
-#endif // USE_COREDISTOOLS
     printf("Inputs are case sensitive.\n");
     printf("\n");
     printf("SuperPMI method contexts are stored in files with extension .MC, implying\n");
@@ -353,12 +358,12 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o)
 
                 o->compileList = argv[i]; // Save this in case we need it for -parallel.
             }
-#ifdef USE_COREDISTOOLS
             else if ((_strnicmp(&argv[i][1], "coredistools", argLen) == 0))
             {
+#ifndef USE_COREDISTOOLS // If USE_COREDISTOOLS is not defined, then allow the switch, but ignore it.
                 o->useCoreDisTools = true;
-            }
 #endif // USE_COREDISTOOLS
+            }
             else if ((_strnicmp(&argv[i][1], "matchHash", argLen) == 0))
             {
                 if (++i >= argc)
index 9937c3c..8703447 100644 (file)
@@ -25,7 +25,11 @@ public:
             , breakOnAssert(false)
             , applyDiff(false)
             , parallel(false)
-            , useCoreDisTools(false)
+#if !defined(USE_MSVCDIS) && defined(USE_COREDISTOOLS)
+            , useCoreDisTools(true)     // if CoreDisTools is available (but MSVCDIS is not), use it.
+#else
+            , useCoreDisTools(false)    // Otherwise, use MSVCDIS if that is available (else no diffs are available).
+#endif
             , skipCleanup(false)
             , workerCount(-1)
             , indexCount(-1)
index d3ccae5..d31a406 100644 (file)
@@ -29,38 +29,89 @@ static void LogFromCoreDisToolsHelper(LogLevel level, const char* msg, va_list a
 }
 
 #define LOGGER(L)                                                                                                      \
-    \
-static void Log##L(const char* msg, ...)                                                                               \
-    \
-{                                                                                                               \
-        va_list argList;                                                                                               \
-        va_start(argList, msg);                                                                                        \
-        LogFromCoreDisToolsHelper(LOGLEVEL_##L, msg, argList);                                                         \
-        va_end(argList);                                                                                               \
-    \
+static void __cdecl CorDisToolsLog##L(const char* msg, ...)                                                            \
+{                                                                                                                      \
+    va_list argList;                                                                                                   \
+    va_start(argList, msg);                                                                                            \
+    LogFromCoreDisToolsHelper(LOGLEVEL_##L, msg, argList);                                                             \
+    va_end(argList);                                                                                                   \
 }
 
 LOGGER(VERBOSE)
 LOGGER(ERROR)
 LOGGER(WARNING)
 
-const PrintControl CorPrinter = {LogERROR, LogWARNING, LogVERBOSE, LogVERBOSE};
+const PrintControl CorPrinter = {CorDisToolsLogERROR, CorDisToolsLogWARNING, CorDisToolsLogVERBOSE, CorDisToolsLogVERBOSE};
 
 #endif // USE_COREDISTOOLS
 
+#ifdef USE_COREDISTOOLS
+NewDiffer_t* g_PtrNewDiffer = nullptr;
+FinishDiff_t* g_PtrFinishDiff = nullptr;
+NearDiffCodeBlocks_t* g_PtrNearDiffCodeBlocks = nullptr;
+DumpDiffBlocks_t* g_PtrDumpDiffBlocks = nullptr;
+#endif // USE_COREDISTOOLS
+
 //
-// The NearDiff Disassembler Initialization
+// The NearDiff Disassembler initialization.
+// 
+// Returns true on success, false on failure.
 //
-void NearDiffer::InitAsmDiff()
+bool NearDiffer::InitAsmDiff()
 {
 #ifdef USE_COREDISTOOLS
+
     if (UseCoreDisTools)
     {
-        corAsmDiff = NewDiffer(Target_Host, &CorPrinter, NearDiffer::compareOffsets);
+        const char* coreDisToolsLibrary = MAKEDLLNAME_A("coredistools");
+
+        HMODULE hCoreDisToolsLib = ::LoadLibraryA(coreDisToolsLibrary);
+        if (hCoreDisToolsLib == 0)
+        {
+            LogError("LoadLibrary(%s) failed (0x%08x)", coreDisToolsLibrary, ::GetLastError());
+            return false;
+        }
+        g_PtrNewDiffer = (NewDiffer_t*)::GetProcAddress(hCoreDisToolsLib, "NewDiffer");
+        if (g_PtrNewDiffer == nullptr)
+        {
+            LogError("GetProcAddress 'NewDiffer' failed (0x%08x)", ::GetLastError());
+            return false;
+        }
+        g_PtrFinishDiff = (FinishDiff_t*)::GetProcAddress(hCoreDisToolsLib, "FinishDiff");
+        if (g_PtrFinishDiff == nullptr)
+        {
+            LogError("GetProcAddress 'FinishDiff' failed (0x%08x)", ::GetLastError());
+            return false;
+        }
+        g_PtrNearDiffCodeBlocks = (NearDiffCodeBlocks_t*)::GetProcAddress(hCoreDisToolsLib, "NearDiffCodeBlocks");
+        if (g_PtrNearDiffCodeBlocks == nullptr)
+        {
+            LogError("GetProcAddress 'NearDiffCodeBlocks' failed (0x%08x)", ::GetLastError());
+            return false;
+        }
+        g_PtrDumpDiffBlocks = (DumpDiffBlocks_t*)::GetProcAddress(hCoreDisToolsLib, "DumpDiffBlocks");
+        if (g_PtrDumpDiffBlocks == nullptr)
+        {
+            LogError("GetProcAddress 'DumpDiffBlocks' failed (0x%08x)", ::GetLastError());
+            return false;
+        }
+
+        corAsmDiff = (*g_PtrNewDiffer)(Target_Host, &CorPrinter, NearDiffer::CoreDisCompareOffsetsCallback);
     }
 #endif // USE_COREDISTOOLS
+
+    return true;
 }
 
+#ifdef USE_COREDISTOOLS
+// static
+bool __cdecl NearDiffer::CoreDisCompareOffsetsCallback(
+        const void* payload, size_t blockOffset, size_t instrLen, uint64_t offset1, uint64_t offset2)
+{
+    return compareOffsets(payload, blockOffset, instrLen, offset1, offset2);
+}
+#endif // USE_COREDISTOOLS
+
 //
 // The NearDiff destructor
 //
@@ -69,7 +120,7 @@ NearDiffer::~NearDiffer()
 #ifdef USE_COREDISTOOLS
     if (corAsmDiff != nullptr)
     {
-        FinishDiff(corAsmDiff);
+        (*g_PtrFinishDiff)(corAsmDiff);
     }
 #endif // USE_COREDISTOOLS
 }
@@ -403,12 +454,12 @@ bool NearDiffer::compareCodeSection(MethodContext* mc,
 #ifdef USE_COREDISTOOLS
     if (UseCoreDisTools)
     {
-        bool areSame = NearDiffCodeBlocks(corAsmDiff, &data, (const uint8_t*)originalBlock1, block1, blocksize1,
+        bool areSame = (*g_PtrNearDiffCodeBlocks)(corAsmDiff, &data, (const uint8_t*)originalBlock1, block1, blocksize1,
                                           (const uint8_t*)originalBlock2, block2, blocksize2);
 
         if (!areSame)
         {
-            DumpDiffBlocks(corAsmDiff, (const uint8_t*)originalBlock1, block1, blocksize1,
+            (*g_PtrDumpDiffBlocks)(corAsmDiff, (const uint8_t*)originalBlock1, block1, blocksize1,
                            (const uint8_t*)originalBlock2, block2, blocksize2);
         }
 
index 100f87c..a2c7f8f 100644 (file)
@@ -26,7 +26,7 @@ public:
 
     ~NearDiffer();
 
-    void InitAsmDiff();
+    bool InitAsmDiff();
 
     bool compare(MethodContext* mc, CompileResult* cr1, CompileResult* cr2);
 
@@ -74,7 +74,12 @@ private:
         const void* payload, size_t blockOffset, size_t instrLen, uint64_t offset1, uint64_t offset2);
 
 #ifdef USE_COREDISTOOLS
+
+    static bool __cdecl CoreDisCompareOffsetsCallback(
+        const void* payload, size_t blockOffset, size_t instrLen, uint64_t offset1, uint64_t offset2);
+
     CorAsmDiff* corAsmDiff;
+
 #endif // USE_COREDISTOOLS
 
 #ifdef USE_MSVCDIS
index c1225e4..58d7787 100644 (file)
@@ -240,7 +240,10 @@ int __cdecl main(int argc, char* argv[])
 
     if (o.applyDiff)
     {
-        nearDiffer.InitAsmDiff();
+        if (!nearDiffer.InitAsmDiff())
+        {
+            return -1;
+        }
     }
 
     while (true)