Add breakpoints management
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 6 Jul 2017 18:10:55 +0000 (21:10 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Mon, 13 Nov 2017 19:22:40 +0000 (22:22 +0300)
src/debug/debugger/CMakeLists.txt
src/debug/debugger/breakpoints.cpp [new file with mode: 0644]
src/debug/debugger/main.cpp
src/debug/debugger/modules.cpp [new file with mode: 0644]
src/debug/debugger/symbolreader.cpp
src/debug/debugger/symbolreader.h
src/debug/debugger/torelease.h

index 4e3ac0e..fefe705 100644 (file)
@@ -1,6 +1,6 @@
 project(coreclrdbg)
 
-set(coreclrdbg_SRC main.cpp symbolreader.cpp tpa.cpp)
+set(coreclrdbg_SRC main.cpp symbolreader.cpp tpa.cpp breakpoints.cpp modules.cpp)
 
 if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
     add_definitions(-D_TARGET_AMD64_=1)
@@ -37,12 +37,13 @@ include_directories(${CLR_DIR}/src/debug/inc)
 include_directories(${CLR_DIR}/src/debug/shim)
 include_directories(${CLR_DIR}/src/coreclr/hosts/inc)
 
+include_directories(${CLR_DIR}/src/ToolBox/SOS/Strike)
+
 target_link_libraries(coreclrdbg
     corguids
     dbgshim
     mscordaccore
     palrt
-    edit
 )
 
 install_clr(coreclrdbg)
diff --git a/src/debug/debugger/breakpoints.cpp b/src/debug/debugger/breakpoints.cpp
new file mode 100644 (file)
index 0000000..2e7fe75
--- /dev/null
@@ -0,0 +1,261 @@
+#include <windows.h>
+
+#include "corhdr.h"
+#include "cor.h"
+#include "cordebug.h"
+#include "debugshim.h"
+
+#include <sstream>
+#include <mutex>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "torelease.h"
+
+// Modules
+HRESULT GetFrameLocation(ICorDebugFrame *pFrame,
+                         ULONG32 &ilOffset,
+                         mdMethodDef &methodToken,
+                         std::string &fullname,
+                         ULONG &linenum);
+std::string GetModuleName(ICorDebugModule *pModule);
+
+HRESULT GetLocationInModule(ICorDebugModule *pModule,
+                            std::string filename,
+                            ULONG linenum,
+                            ULONG32 &ilOffset,
+                            mdMethodDef &methodToken,
+                            std::string &fullname);
+
+
+std::mutex g_breakMutex;
+ULONG32 g_breakIndex = 1;
+
+struct Breakpoint {
+    ULONG32 id;
+    CORDB_ADDRESS modAddress;
+    mdMethodDef methodToken;
+    ULONG32 ilOffset;
+    std::string fullname;
+    int linenum;
+    ICorDebugBreakpoint *breakpoint;
+
+    bool IsResolved() const
+    {
+        return modAddress != 0;
+    }
+
+    Breakpoint() : id(0), modAddress(0), methodToken(0), ilOffset(0), linenum(0), breakpoint(nullptr) {}
+};
+
+std::vector<Breakpoint> g_breaks;
+
+HRESULT PrintBreakpoint(ULONG32 id, std::string &output)
+{
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+
+    for (Breakpoint &b : g_breaks)
+    {
+        if (b.id != id)
+            continue;
+
+        std::stringstream ss;
+
+        HRESULT Status;
+        if (b.IsResolved())
+        {
+            ss << "bkpt={number=\"" << id << "\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\","
+               "func=\"\",fullname=\"" << b.fullname << "\",line=\"" << b.linenum << "\"}";
+            Status = S_OK;
+        }
+        else
+        {
+            ss << "bkpt={number=\"" << id << "\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\","
+               "warning=\"No executable code of the debugger’s target code type is associated with this line.\"}";
+            Status = S_FALSE;
+        }
+        output = ss.str();
+        return Status;
+    }
+
+    return E_FAIL;
+}
+
+HRESULT FindCurrentBreakpointId(ICorDebugThread *pThread, ULONG32 &id)
+{
+    HRESULT Status;
+    ULONG32 ilOffset;
+    mdMethodDef methodToken;
+    std::string fullname;
+    ULONG linenum;
+
+    ToRelease<ICorDebugFrame> pFrame;
+    IfFailRet(pThread->GetActiveFrame(&pFrame));
+    IfFailRet(GetFrameLocation(pFrame, ilOffset, methodToken, fullname, linenum));
+
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+
+    for (Breakpoint &b : g_breaks)
+    {
+        if (b.fullname == fullname &&
+            b.ilOffset == ilOffset &&
+            b.methodToken == methodToken &&
+            b.linenum == linenum)
+        {
+            id = b.id;
+            return S_OK;
+        }
+    }
+
+    return E_FAIL;
+}
+
+HRESULT DeleteBreakpoint(ULONG32 id)
+{
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+
+    auto bpit = g_breaks.begin();
+
+    while(bpit != g_breaks.end())
+    {
+        if (bpit->id == id)
+        {
+            if (bpit->breakpoint)
+            {
+                bpit->breakpoint->Activate(0);
+                bpit->breakpoint->Release();
+            }
+            bpit = g_breaks.erase(bpit);
+            return S_OK;
+        }
+        else
+        {
+            ++bpit;
+        }
+    }
+
+    return E_FAIL;
+}
+
+void DeleteAllBreakpoints()
+{
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+
+    for (Breakpoint &b : g_breaks)
+    {
+        if (b.breakpoint)
+        {
+            b.breakpoint->Activate(0);
+            b.breakpoint->Release();
+        }
+    }
+
+    g_breaks.clear();
+}
+
+HRESULT ResolveBreakpoint(ICorDebugModule *pModule, std::string filename, int linenum, Breakpoint &bp)
+{
+    HRESULT Status;
+
+    mdMethodDef methodToken;
+    ULONG32 ilOffset;
+    std::string fullname;
+
+    IfFailRet(GetLocationInModule(pModule, filename,
+                                  linenum,
+                                  ilOffset,
+                                  methodToken,
+                                  fullname));
+
+    ToRelease<ICorDebugFunction> pFunc;
+    ToRelease<ICorDebugCode> pCode;
+    IfFailRet(pModule->GetFunctionFromToken(methodToken, &pFunc));
+    IfFailRet(pFunc->GetILCode(&pCode));
+
+    ToRelease<ICorDebugFunctionBreakpoint> pBreakpoint;
+    IfFailRet(pCode->CreateBreakpoint(ilOffset, &pBreakpoint));
+    IfFailRet(pBreakpoint->Activate(TRUE));
+
+    CORDB_ADDRESS modAddress;
+    IfFailRet(pModule->GetBaseAddress(&modAddress));
+
+    bp.modAddress = modAddress;
+    bp.methodToken = methodToken;
+    bp.ilOffset = ilOffset;
+    bp.fullname = fullname;
+    bp.linenum = linenum;
+    bp.breakpoint = pBreakpoint.Detach();
+
+    return S_OK;
+}
+
+HRESULT TryResolveBreakpointsForModule(ICorDebugModule *pModule)
+{
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+
+    for (Breakpoint &b : g_breaks)
+    {
+        if (b.IsResolved())
+            continue;
+
+        if (SUCCEEDED(ResolveBreakpoint(pModule, b.fullname, b.linenum, b)))
+        {
+            return S_OK;
+        }
+    }
+    return E_FAIL;
+}
+
+HRESULT CreateBreakpointInProcess(ICorDebugProcess *pProcess, std::string filename, int linenum, ULONG32 &id)
+{
+    HRESULT Status;
+
+    ToRelease<ICorDebugAppDomainEnum> domains;
+    IfFailRet(pProcess->EnumerateAppDomains(&domains));
+
+    Breakpoint bp;
+
+    ICorDebugAppDomain *curDomain;
+    ULONG domainsFetched;
+    while (SUCCEEDED(domains->Next(1, &curDomain, &domainsFetched)) && domainsFetched == 1)
+    {
+        ToRelease<ICorDebugAppDomain> pDomain = curDomain;
+
+        ToRelease<ICorDebugAssemblyEnum> assemblies;
+        IfFailRet(pDomain->EnumerateAssemblies(&assemblies));
+
+        ICorDebugAssembly *curAssembly;
+        ULONG assembliesFetched;
+        while (SUCCEEDED(assemblies->Next(1, &curAssembly, &assembliesFetched)) && assembliesFetched == 1)
+        {
+            ToRelease<ICorDebugAssembly> pAssembly = curAssembly;
+
+            ToRelease<ICorDebugModuleEnum> modules;
+            IfFailRet(pAssembly->EnumerateModules(&modules));
+
+            ICorDebugModule *curModule;
+            ULONG modulesFetched;
+            while (SUCCEEDED(modules->Next(1, &curModule, &modulesFetched)) && modulesFetched == 1)
+            {
+                ToRelease<ICorDebugModule> pModule = curModule;
+                if (SUCCEEDED(ResolveBreakpoint(pModule, filename, linenum, bp)))
+                {
+                    std::lock_guard<std::mutex> lock(g_breakMutex);
+                    id = g_breakIndex++;
+                    bp.id = id;
+                    g_breaks.push_back(bp);
+                    return S_OK;
+                }
+            }
+        }
+    }
+
+    // Add pending breakpoint
+    std::lock_guard<std::mutex> lock(g_breakMutex);
+    id = g_breakIndex++;
+    bp.id = id;
+    g_breaks.push_back(bp);
+
+    return S_FALSE;
+}
\ No newline at end of file
index 06e26c8..6c643aa 100644 (file)
@@ -1,10 +1,4 @@
-// #include <iostream>
-// #include <cstdlib>
-
 #include <windows.h>
-// #include <winver.h>
-// #include <winternl.h>
-// #include <psapi.h>
 
 #include "corhdr.h"
 #include "cor.h"
 #include "clrinternal.h"
 
 #include <unistd.h>
-#include <sys/syscall.h>
-
-#include <histedit.h>
 
 #include <sstream>
 #include <mutex>
 #include <memory>
 #include <unordered_map>
+#include <vector>
 #include <fstream>
 
-#include "symbolreader.h"
+typedef char * LPCUTF8;
+typedef uintptr_t TADDR;
+#include "sos_md.h"
+
+#include <arrayholder.h>
+#include "torelease.h"
 
 EXTERN_C HRESULT CreateDebuggingInterfaceFromVersionEx(
     int iDebuggerVersion,
@@ -38,9 +35,7 @@ CreateVersionStringFromModule(
     DWORD cchBuffer,
     DWORD* pdwLength);
 
-#include <arrayholder.h>
-#include "torelease.h"
-
+std::mutex g_processMutex;
 ICorDebugProcess *g_process = NULL;
 
 ULONG OSPageSize ()
@@ -69,6 +64,11 @@ size_t NextOSPageAddress (size_t addr)
 BOOL SafeReadMemory (TADDR offset, PVOID lpBuffer, ULONG cb,
                      PULONG lpcbBytesRead)
 {
+    std::lock_guard<std::mutex> lock(g_processMutex);
+
+    if (!g_process)
+        return FALSE;
+
     BOOL bRet = FALSE;
 
     SIZE_T bytesRead = 0;
@@ -87,36 +87,47 @@ BOOL SafeReadMemory (TADDR offset, PVOID lpBuffer, ULONG cb,
     return bRet;
 }
 
-/* This holds all the state for our line editor */
-EditLine *el;
-
-const char * prompt(EditLine *e) {
-    return "(gdb) ";
-}
+bool g_processExited = false;
 
-// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
-const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
+std::mutex g_outMutex;
 
-void _el_printf(EditLine *el, const char *fmt, ...)
-    __attribute__((format (printf, 2, 3)));
+void _out_printf(const char *fmt, ...)
+    __attribute__((format (printf, 1, 2)));
 
-#define el_printf(el, fmt, ...) _el_printf(el, fmt, ##__VA_ARGS__)
+#define out_printf(fmt, ...) _out_printf(fmt, ##__VA_ARGS__)
 
-void _el_printf(EditLine *el, const char *fmt, ...)
+void _out_printf(const char *fmt, ...)
 {
-    fwrite(undo_prompt_string , sizeof(char), sizeof(undo_prompt_string), stdout);
+    std::lock_guard<std::mutex> lock(g_outMutex);
     va_list arg;
 
-    /* Write the error message */
     va_start(arg, fmt);
     vfprintf(stdout, fmt, arg);
     va_end(arg);
 
     fflush(stdout);
-
-    el_set(el, EL_REFRESH);
 }
 
+// Breakpoints
+void DeleteAllBreakpoints();
+HRESULT FindCurrentBreakpointId(ICorDebugThread *pThread, ULONG32 &id);
+HRESULT DeleteBreakpoint(ULONG32 id);
+HRESULT CreateBreakpointInProcess(ICorDebugProcess *pProcess, std::string filename, int linenum, ULONG32 &id);
+HRESULT TryResolveBreakpointsForModule(ICorDebugModule *pModule);
+HRESULT PrintBreakpoint(ULONG32 id, std::string &output);
+
+// Modules
+void SetCoreCLRPath(const std::string &coreclrPath);
+std::string GetModuleName(ICorDebugModule *pModule);
+HRESULT GetStepRangeFromCurrentIP(ICorDebugThread *pThread, COR_DEBUG_STEP_RANGE *range);
+HRESULT TryLoadModuleSymbols(ICorDebugModule *pModule);
+HRESULT GetFrameLocation(ICorDebugFrame *pFrame,
+                         ULONG32 &ilOffset,
+                         mdMethodDef &methodToken,
+                         std::string &fullname,
+                         ULONG &linenum);
+
+
 HRESULT PrintThread(ICorDebugThread *pThread, std::string &output)
 {
     HRESULT Status = S_OK;
@@ -171,7 +182,7 @@ HRESULT PrintThreadsState(ICorDebugController *controller, std::string &output)
 
     std::stringstream ss;
 
-    ss << "^done,threads=[";
+    ss << "threads=[";
 
     ICorDebugThread *handle;
     ULONG fetched;
@@ -195,206 +206,40 @@ HRESULT PrintThreadsState(ICorDebugController *controller, std::string &output)
 HRESULT PrintFrameLocation(ICorDebugFrame *pFrame, std::string &output)
 {
     HRESULT Status;
+    ULONG32 ilOffset;
     mdMethodDef methodToken;
+    std::string fullname;
+    ULONG linenum;
 
-    IfFailRet(pFrame->GetFunctionToken(&methodToken));
-
-    ToRelease<ICorDebugFunction> pFunc;
-    IfFailRet(pFrame->GetFunction(&pFunc));
-
-    ToRelease<ICorDebugModule> pModule;
-    IfFailRet(pFunc->GetModule(&pModule));
-
-    ToRelease<IUnknown> pMDUnknown;
-    ToRelease<IMetaDataImport> pMDImport;
-    IfFailRet(pModule->GetMetaDataInterface(IID_IMetaDataImport, &pMDUnknown));
-
-    ToRelease<ICorDebugILFrame> pILFrame;
-    IfFailRet(pFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame));
-
-    ULONG32 nOffset;
-    CorDebugMappingResult mappingResult;
-    IfFailRet(pILFrame->GetIP(&nOffset, &mappingResult));
-
-    SymbolReader symbolReader;
-    if (SUCCEEDED(symbolReader.LoadSymbols(pMDImport, pModule)))
-    {
-        WCHAR name[mdNameLen];
-        ULONG linenum;
-        IfFailRet(symbolReader.GetLineByILOffset(methodToken, nOffset, &linenum, name, mdNameLen));
+    IfFailRet(GetFrameLocation(pFrame, ilOffset, methodToken, fullname, linenum));
 
-        char cname[mdNameLen];
-
-        WideCharToMultiByte(CP_UTF8, 0, name, (int)(PAL_wcslen(name) + 1), cname, mdNameLen, NULL, NULL);
-
-        std::stringstream ss;
-        ss << "line=\"" << linenum << "\",fullname=\"" << cname << "\"";
-        output = ss.str();
-    }
+    std::stringstream ss;
+    ss << "line=\"" << linenum << "\",fullname=\"" << fullname << "\"";
+    output = ss.str();
 
     return S_OK;
 }
-HRESULT PrintLocation(ICorDebugThread *pThread, std::string &output)
-{
-    HRESULT Status;
-    ToRelease<ICorDebugFrame> pFrame;
-    IfFailRet(pThread->GetActiveFrame(&pFrame));
 
-    return PrintFrameLocation(pFrame, output);
-}
-
-HRESULT GetStepRangeFromCurrentIP(ICorDebugThread *pThread, COR_DEBUG_STEP_RANGE *range)
+HRESULT PrintLocation(ICorDebugThread *pThread, std::string &output)
 {
     HRESULT Status;
     ToRelease<ICorDebugFrame> pFrame;
     IfFailRet(pThread->GetActiveFrame(&pFrame));
 
+    ULONG32 ilOffset;
     mdMethodDef methodToken;
-    IfFailRet(pFrame->GetFunctionToken(&methodToken));
-
-    ToRelease<ICorDebugFunction> pFunc;
-    IfFailRet(pFrame->GetFunction(&pFunc));
-
-    ToRelease<ICorDebugModule> pModule;
-    IfFailRet(pFunc->GetModule(&pModule));
-
-    ToRelease<IUnknown> pMDUnknown;
-    ToRelease<IMetaDataImport> pMDImport;
-    IfFailRet(pModule->GetMetaDataInterface(IID_IMetaDataImport, &pMDUnknown));
-
-    ToRelease<ICorDebugILFrame> pILFrame;
-    IfFailRet(pFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame));
-
-    ULONG32 nOffset;
-    CorDebugMappingResult mappingResult;
-    IfFailRet(pILFrame->GetIP(&nOffset, &mappingResult));
-
-    SymbolReader symbolReader;
-    IfFailRet(symbolReader.LoadSymbols(pMDImport, pModule));
-
-    ULONG32 ilStartOffset;
-    ULONG32 ilEndOffset;
-
-    IfFailRet(symbolReader.GetStepRangesFromIP(nOffset, methodToken, &ilStartOffset, &ilEndOffset));
+    std::string fullname;
+    ULONG linenum;
 
-    if (ilStartOffset == ilEndOffset)
-    {
-        ToRelease<ICorDebugCode> pCode;
-        IfFailRet(pFunc->GetILCode(&pCode));
-        IfFailRet(pCode->GetSize(&ilEndOffset));
-    }
+    IfFailRet(GetFrameLocation(pFrame, ilOffset, methodToken, fullname, linenum));
 
-    range->startOffset = ilStartOffset;
-    range->endOffset = ilEndOffset;
+    std::stringstream ss;
+    ss << "line=\"" << linenum << "\",fullname=\"" << fullname << "\"";
+    output = ss.str();
 
     return S_OK;
 }
 
-struct ModuleInfo
-{
-    CORDB_ADDRESS address;
-    std::shared_ptr<SymbolReader> symbols;
-    //ICorDebugModule *module;
-};
-
-std::mutex g_modulesInfoMutex;
-std::unordered_map<std::string, ModuleInfo> g_modulesInfo;
-
-std::string GetModuleName(ICorDebugModule *pModule)
-{
-    char cname[mdNameLen];
-    WCHAR name[mdNameLen];
-    ULONG32 name_len = 0;
-    if (SUCCEEDED(pModule->GetName(mdNameLen, &name_len, name)))
-    {
-        WideCharToMultiByte(CP_UTF8, 0, name, (int)(PAL_wcslen(name) + 1), cname, mdNameLen, NULL, NULL);
-        return cname;
-    }
-    return std::string();
-}
-
-HRESULT CreateBreakpoint(ICorDebugModule *pModule, std::string filename, int linenum)
-{
-    HRESULT Status;
-
-    WCHAR nameBuffer[MAX_LONGPATH];
-
-    Status = MultiByteToWideChar(CP_UTF8, 0, filename.c_str(), filename.size() + 1, nameBuffer, MAX_LONGPATH);
-
-    std::string modName = GetModuleName(pModule);
-
-    {
-        std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
-        auto info_pair = g_modulesInfo.find(modName);
-        if (info_pair == g_modulesInfo.end())
-        {
-            return E_FAIL;
-        }
-
-        CORDB_ADDRESS modAddress;
-        IfFailRet(pModule->GetBaseAddress(&modAddress));
-
-        mdMethodDef methodToken;
-        ULONG32 ilOffset;
-
-        IfFailRet(info_pair->second.symbols->ResolveSequencePoint(nameBuffer, linenum, modAddress, &methodToken, &ilOffset));
-
-        //el_printf(el, "  methodToken=0x%x ilOffset=%i\n", methodToken, ilOffset);
-
-        ToRelease<ICorDebugFunction> pFunc;
-        ToRelease<ICorDebugCode> pCode;
-        IfFailRet(pModule->GetFunctionFromToken(methodToken, &pFunc));
-        IfFailRet(pFunc->GetILCode(&pCode));
-
-        ToRelease<ICorDebugFunctionBreakpoint> pBreakpoint;
-        IfFailRet(pCode->CreateBreakpoint(ilOffset, &pBreakpoint));
-        IfFailRet(pBreakpoint->Activate(TRUE));
-
-        return S_OK;
-    }
-
-    return E_FAIL;
-}
-
-HRESULT CreateBreakpointInProcess(ICorDebugProcess *pProcess, std::string filename, int linenum)
-{
-    HRESULT Status;
-
-    ToRelease<ICorDebugAppDomainEnum> domains;
-    IfFailRet(pProcess->EnumerateAppDomains(&domains));
-
-    ICorDebugAppDomain *curDomain;
-    ULONG domainsFetched;
-    while (SUCCEEDED(domains->Next(1, &curDomain, &domainsFetched)) && domainsFetched == 1)
-    {
-        ToRelease<ICorDebugAppDomain> pDomain = curDomain;
-
-        ToRelease<ICorDebugAssemblyEnum> assemblies;
-        IfFailRet(pDomain->EnumerateAssemblies(&assemblies));
-
-        ICorDebugAssembly *curAssembly;
-        ULONG assembliesFetched;
-        while (SUCCEEDED(assemblies->Next(1, &curAssembly, &assembliesFetched)) && assembliesFetched == 1)
-        {
-            ToRelease<ICorDebugAssembly> pAssembly = curAssembly;
-
-            ToRelease<ICorDebugModuleEnum> modules;
-            IfFailRet(pAssembly->EnumerateModules(&modules));
-
-            ICorDebugModule *curModule;
-            ULONG modulesFetched;
-            while (SUCCEEDED(modules->Next(1, &curModule, &modulesFetched)) && modulesFetched == 1)
-            {
-                ToRelease<ICorDebugModule> pModule = curModule;
-
-                if (SUCCEEDED(CreateBreakpoint(pModule, filename, linenum)))
-                    return S_OK;
-            }
-        }
-    }
-    return S_FALSE;
-}
-
 HRESULT DisableAllBreakpointsAndSteppersInAppDomain(ICorDebugAppDomain *pAppDomain)
 {
     HRESULT Status;
@@ -411,6 +256,8 @@ HRESULT DisableAllBreakpointsAndSteppersInAppDomain(ICorDebugAppDomain *pAppDoma
         }
     }
 
+    DeleteAllBreakpoints();
+
     ToRelease<ICorDebugStepperEnum> steppers;
     if (SUCCEEDED(pAppDomain->EnumerateSteppers(&steppers)))
     {
@@ -443,33 +290,6 @@ HRESULT DisableAllBreakpointsAndSteppers(ICorDebugProcess *pProcess)
     return S_OK;
 }
 
-HRESULT TryLoadModuleSymbols(ICorDebugModule *pModule)
-{
-    HRESULT Status;
-    std::string name = GetModuleName(pModule);
-
-    if (name.empty())
-        return E_FAIL;
-
-    ToRelease<IUnknown> pMDUnknown;
-    ToRelease<IMetaDataImport> pMDImport;
-    IfFailRet(pModule->GetMetaDataInterface(IID_IMetaDataImport, &pMDUnknown));
-
-    IfFailRet(pMDUnknown->QueryInterface(IID_IMetaDataImport, (LPVOID*) &pMDImport));
-
-    auto symbolReader = std::make_shared<SymbolReader>();
-    IfFailRet(symbolReader->LoadSymbols(pMDImport, pModule));
-
-    CORDB_ADDRESS modAddress;
-    pModule->GetBaseAddress(&modAddress);
-
-    {
-        std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
-        g_modulesInfo.insert({name, {modAddress, symbolReader}});
-    }
-    return S_OK;
-}
-
 enum StepType {
     STEP_IN = 0,
     STEP_OVER,
@@ -661,6 +481,19 @@ HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output)
         }
         wcscat_s (m_szName, _countof(m_szName), szFunctionName);
 
+        ToRelease<IMDInternalImport> pIMDI;
+        IfFailRet(GetMDInternalFromImport(pMD, &pIMDI));
+
+        LPCSTR szName = NULL;
+        LPCSTR szNameSpace = NULL;
+        pIMDI->GetNameOfTypeDef(memTypeDef, &szName, &szNameSpace);
+
+        // CORDB_ADDRESS modAddress;
+        // IfFailRet(pModule->GetBaseAddress(&modAddress));
+        // WCHAR cBuffer[2048];
+        // PrettyPrintClassFromToken(modAddress, typeDef, cBuffer, 2048);
+        // IMDInternalImport *pIMDI;
+
         // TODO:
         // LONG lSigBlobRemaining;
         // hr = GetFullNameForMD(pbSigBlob, ulSigBlob, &lSigBlobRemaining);
@@ -668,7 +501,7 @@ HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output)
         char funcName[2048] = {0};
         WideCharToMultiByte(CP_UTF8, 0, m_szName, (int)(_wcslen(m_szName) + 1), funcName, _countof(funcName), NULL, NULL);
 
-        ss << "func=\"" << funcName << "\"}";
+        ss << "func=\"" << szName << "." << szName << "\"}";
     }
 
     ss << "]";
@@ -688,8 +521,7 @@ public:
 
         void HandleEvent(ICorDebugController *controller, const char *eventName)
         {
-            el_printf(el, "test");
-            el_printf(el, "event received on tid %li: %s\n", syscall(SYS_gettid), eventName);
+            out_printf("=message,text=\"event received %s\"\n", eventName);
             controller->Continue(0);
         }
 
@@ -746,14 +578,17 @@ public:
             /* [in] */ ICorDebugThread *pThread,
             /* [in] */ ICorDebugBreakpoint *pBreakpoint)
         {
+            ULONG32 id = 0;
+            FindCurrentBreakpointId(pThread, id);
+
             std::string output;
             PrintLocation(pThread, output);
 
             DWORD threadId = 0;
             pThread->GetID(&threadId);
 
-            el_printf(el, "*stopped,reason=\"breakpoint-hit\",thread-id=\"%i\",stopped-threads=\"all\",bkptno=\"1\",%s\n",
-                (int)threadId, output.c_str());
+            out_printf("*stopped,reason=\"breakpoint-hit\",thread-id=\"%i\",stopped-threads=\"all\",bkptno=\"%u\",%s\n",
+                (int)threadId, (unsigned int)id, output.c_str());
             {
                 std::lock_guard<std::mutex> lock(g_currentThreadMutex);
                 if (g_currentThread)
@@ -776,7 +611,7 @@ public:
             DWORD threadId = 0;
             pThread->GetID(&threadId);
 
-            el_printf(el, "*stopped,reason=\"end-stepping-range\",thread-id=\"%i\",stopped-threads=\"all\",%s\n",
+            out_printf("*stopped,reason=\"end-stepping-range\",thread-id=\"%i\",stopped-threads=\"all\",%s\n",
                 (int)threadId, output.c_str());
 
             {
@@ -797,7 +632,38 @@ public:
         virtual HRESULT STDMETHODCALLTYPE Exception(
             /* [in] */ ICorDebugAppDomain *pAppDomain,
             /* [in] */ ICorDebugThread *pThread,
-            /* [in] */ BOOL unhandled) { return S_OK; }
+            /* [in] */ BOOL unhandled)
+        {
+            std::string output;
+            PrintLocation(pThread, output);
+
+            DWORD threadId = 0;
+            pThread->GetID(&threadId);
+
+            if (unhandled)
+            {
+                ToRelease<ICorDebugFrame> pFrame;
+                std::string output;
+
+                if (SUCCEEDED(pThread->GetActiveFrame(&pFrame)))
+                    PrintFrameLocation(pFrame, output);
+
+                out_printf("*stopped,reason=\"exception-received\",exception-stage=\"%s\",thread-id=\"%i\",stopped-threads=\"all\",%s\n",
+                    unhandled ? "unhandled" : "handled", (int)threadId, output.c_str());
+
+                std::lock_guard<std::mutex> lock(g_currentThreadMutex);
+                if (g_currentThread)
+                    g_currentThread->Release();
+                pThread->AddRef();
+                g_currentThread = pThread;
+            } else {
+                out_printf("=message,text=\"Exception thrown: '%s' in %s\\n\",send-to=\"output-window\",source=\"target-exception\"\n",
+                    "<exceptions.name>", "<short.module.name>");
+                pAppDomain->Continue(0);
+            }
+
+            return S_OK;
+        }
 
         virtual HRESULT STDMETHODCALLTYPE EvalComplete(
             /* [in] */ ICorDebugAppDomain *pAppDomain,
@@ -820,7 +686,8 @@ public:
         virtual HRESULT STDMETHODCALLTYPE ExitProcess(
             /* [in] */ ICorDebugProcess *pProcess)
         {
-            el_printf(el, "*stopped,reason=\"exited\",exit-code=\"%i\"\n", 0);
+            out_printf("*stopped,reason=\"exited\",exit-code=\"%i\"\n", 0);
+            g_processExited = true;
             return S_OK;
         }
 
@@ -830,7 +697,7 @@ public:
         {
             DWORD threadId = 0;
             thread->GetID(&threadId);
-            el_printf(el, "=thread-created,id=\"%i\"\n", (int)threadId);
+            out_printf("=thread-created,id=\"%i\"\n", (int)threadId);
             pAppDomain->Continue(0);
             return S_OK;
         }
@@ -850,9 +717,10 @@ public:
             std::string name = GetModuleName(pModule);
             if (!name.empty())
             {
-                el_printf(el, "=library-loaded,target-name=\"%s\"\n", name.c_str());
+                out_printf("=library-loaded,target-name=\"%s\"\n", name.c_str());
             }
             TryLoadModuleSymbols(pModule);
+            TryResolveBreakpointsForModule(pModule);
             pAppDomain->Continue(0);
             return S_OK;
         }
@@ -968,7 +836,22 @@ public:
             /* [in] */ ICorDebugFrame *pFrame,
             /* [in] */ ULONG32 nOffset,
             /* [in] */ CorDebugExceptionCallbackType dwEventType,
-            /* [in] */ DWORD dwFlags) {return S_OK; }
+            /* [in] */ DWORD dwFlags)
+        {
+            // const char *cbTypeName;
+            // switch(dwEventType)
+            // {
+            //     case DEBUG_EXCEPTION_FIRST_CHANCE: cbTypeName = "FIRST_CHANCE"; break;
+            //     case DEBUG_EXCEPTION_USER_FIRST_CHANCE: cbTypeName = "USER_FIRST_CHANCE"; break;
+            //     case DEBUG_EXCEPTION_CATCH_HANDLER_FOUND: cbTypeName = "CATCH_HANDLER_FOUND"; break;
+            //     case DEBUG_EXCEPTION_UNHANDLED: cbTypeName = "UNHANDLED"; break;
+            //     default: cbTypeName = "?"; break;
+            // }
+            // out_printf("*stopped,reason=\"exception-received2\",exception-stage=\"%s\"\n",
+            //     cbTypeName);
+            pAppDomain->Continue(0);
+            return S_OK;
+        }
 
         virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind(
             /* [in] */ ICorDebugAppDomain *pAppDomain,
@@ -1078,7 +961,7 @@ int main(int argc, char *argv[])
         return EXIT_FAILURE;
     }
 
-    SymbolReader::SetCoreCLRPath(coreclrPath);
+    SetCoreCLRPath(coreclrPath);
 
     WCHAR szModuleName[MAX_LONGPATH];
     MultiByteToWideChar(CP_UTF8, 0, coreclrPath.c_str(), coreclrPath.size() + 1, szModuleName, MAX_LONGPATH);
@@ -1089,7 +972,7 @@ int main(int argc, char *argv[])
         pidDebuggee,
         szModuleName,
         pBuffer,
-        100,
+        _countof(pBuffer),
         &dwLength);
 
     if (FAILED(hr))
@@ -1145,103 +1028,77 @@ int main(int argc, char *argv[])
         return EXIT_FAILURE;
     }
 
-    g_process = pProcess;
-
-    //printf("libedit thread %li\n", syscall(SYS_gettid));
-
-
-    /* This holds the info for our history */
-    History *myhistory;
-
-    /* Temp variables */
-    int keepreading = 1;
-    HistEvent ev;
-
-    /* Initialize the EditLine state to use our prompt function and
-    emacs style editing. */
-
-    el = el_init(argv[0], stdin, stdout, stderr);
-    el_set(el, EL_PROMPT, &prompt);
-    el_set(el, EL_EDITOR, "emacs");
-    el_set(el, EL_SIGNAL, 1);
-
-    /* Initialize the history */
-    myhistory = history_init();
-    if (myhistory == 0) {
-        fprintf(stderr, "history could not be initialized\n");
-        return 1;
+    {
+        std::lock_guard<std::mutex> lock(g_processMutex);
+        g_process = pProcess;
     }
 
-    /* Set the size of the history */
-    history(myhistory, &ev, H_SETSIZE, 800);
-
-    /* This sets up the call back functions for history functionality */
-    el_set(el, EL_HIST, history, myhistory);
+    static char inputBuffer[1024];
+    const char *token = "";
 
-    std::string prev_command;
+    for (;;) {
+        token = "";
 
-    while (keepreading) {
-        /* count is the number of characters read.
-           line is a const char* of our command line with the tailing \n */
-        int count;
+        out_printf("(gdb)\n");
+        if (!fgets(inputBuffer, _countof(inputBuffer), stdin))
+            break;
 
-        const char *raw_line = el_gets(el, &count);
-        // Sleep(3000);
-        // const char *raw_line = "-gdb-exit\n";
-        // count = strlen(raw_line);
+        size_t count = strlen(inputBuffer);
 
-        if (count <= 0)
-        {
-            keepreading = 0;
+        if (count < 1 || inputBuffer[count - 1] != '\n')
             break;
-        }
 
-        /* In order to use our history we have to explicitly add commands
-        to the history */
+        if (count >= 2 && inputBuffer[count - 2] == '\r')
+            --count;
 
-        std::string line(raw_line, count - 1);
-
-        if (!line.empty())
-        {
-            history(myhistory, &ev, H_ENTER, raw_line);
-            prev_command = line;
-        }
+        int miCmdStart = 0;
+        char *tokenEnd = strchr(inputBuffer, '-');
+        if (tokenEnd)
+            miCmdStart = tokenEnd - inputBuffer + 1;
         else
-        {
-            line = prev_command;
-        }
+            tokenEnd = inputBuffer;
+        std::string line(inputBuffer + miCmdStart, count - miCmdStart - 1);
+        *tokenEnd = '\0';
+        token = inputBuffer;
 
-        if (line == "-thread-info")
+        if (line == "thread-info")
         {
             std::string output;
             HRESULT hr = PrintThreadsState(pProcess, output);
-            printf("%x:%s\n", hr, output.c_str());
+            if (SUCCEEDED(hr))
+            {
+                out_printf("%s^done,%s\n", token, output.c_str());
+            }
+            else
+            {
+                out_printf("%s^error,msg=\"HRESULT=%x\"\n", token, hr);
+            }
         }
-        else if (line == "-exec-continue")
+        else if (line == "exec-continue")
         {
             HRESULT hr = pProcess->Continue(0);
             if (SUCCEEDED(hr))
             {
-                printf("^done\n");
+                out_printf("%s^done\n", token);
             }
             else
             {
-                printf("^error,msg=\"HRESULT=%x\"\n", hr);
+                out_printf("%s^error,msg=\"HRESULT=%x\"\n", token, hr);
             }
         }
-        else if (line == "-exec-interrupt")
+        else if (line == "exec-interrupt")
         {
             HRESULT hr = pProcess->Stop(0);
             if (SUCCEEDED(hr))
             {
-                printf("^done\n");
+                out_printf("%s^done\n", token);
             }
             else
             {
-                printf("^error,msg=\"HRESULT=%x\"\n", hr);
+                out_printf("%s^error,msg=\"HRESULT=%x\"\n", token, hr);
             }
         }
-        else if (line.find("-break-insert ") == 0)
+        else if (line.find("break-insert ") == 0)
         {
             // TODO: imlement proper argument parsing
             std::size_t i1 = line.find(' ');
@@ -1253,25 +1110,34 @@ int main(int argc, char *argv[])
                 std::string slinenum = line.substr(i2 + 1);
 
                 int linenum = std::stoi(slinenum);
-                if (CreateBreakpointInProcess(pProcess, filename, linenum) == S_OK)
+                ULONG32 id;
+                if (SUCCEEDED(CreateBreakpointInProcess(pProcess, filename, linenum, id)))
                 {
-                    int bkpt_num = 1;
-                    printf("^done,bkpt={number=\"%i\",fullname=\"%s\",line=\"%i\"}\n", bkpt_num, filename.c_str(), linenum);
+                    std::string output;
+                    PrintBreakpoint(id, output);
+                    out_printf("%s^done,%s\n", token, output.c_str());
                 }
             }
             else
             {
-                printf("^error,msg=\"Unknown breakpoint location format\"\n");
+                out_printf("%s^error,msg=\"Unknown breakpoint location format\"\n", token);
             }
         }
-        else if (line == "-exec-next" || line == "-exec-step" || line == "-exec-finish")
+        else if (line.find("break-delete ") == 0)
+        {
+            std::size_t i = line.find(' ');
+            ULONG32 id = std::stoul(line.substr(i));
+            DeleteBreakpoint(id);
+            out_printf("%s^done\n", token);
+        }
+        else if (line == "exec-next" || line == "exec-step" || line == "exec-finish")
         {
             StepType stepType;
-            if (line == "-exec-next")
+            if (line == "exec-next")
                 stepType = STEP_OVER;
-            else if (line == "-exec-step")
+            else if (line == "exec-step")
                 stepType = STEP_IN;
-            else if (line == "-exec-finish")
+            else if (line == "exec-finish")
                 stepType = STEP_OUT;
 
             HRESULT hr;
@@ -1282,23 +1148,24 @@ int main(int argc, char *argv[])
 
             if (FAILED(hr))
             {
-                printf("^error,msg=\"Cannot create stepper: %x\"\n", hr);
+                out_printf("%s^error,msg=\"Cannot create stepper: %x\"\n", token, hr);
             }
             else
             {
                 hr = pProcess->Continue(0);
                 if (SUCCEEDED(hr))
                 {
-                    printf("^done\n");
+                    out_printf("%s^done\n", token);
                 }
                 else
                 {
-                    printf("^error,msg=\"HRESULT=%x\"\n", hr);
+                    out_printf("%s^error,msg=\"HRESULT=%x\"\n", token, hr);
                 }
             }
         }
-        else if (line == "-stack-list-frames")
+        else if (line == "stack-list-frames")
         {
+            // TODO: Add parsing frame indeces
             std::string output;
             HRESULT hr;
             {
@@ -1307,14 +1174,14 @@ int main(int argc, char *argv[])
             }
             if (SUCCEEDED(hr))
             {
-                printf("^done,%s\n", output.c_str());
+                out_printf("%s^done,%s\n", inputBuffer, output.c_str());
             }
             else
             {
-                printf("^error,msg=\"HRESULT=%x\"\n", hr);
+                out_printf("%s^error,msg=\"HRESULT=%x\"\n", inputBuffer, hr);
             }
         }
-        else if (line == "-gdb-exit")
+        else if (line == "gdb-exit")
         {
             hr = pProcess->Stop(0);
             if (SUCCEEDED(hr))
@@ -1323,36 +1190,29 @@ int main(int argc, char *argv[])
 
                 hr = pProcess->Terminate(0);
 
-                // TODO: wait for process exit event
-                Sleep(2000);
+                while (!g_processExited)
+                    Sleep(100);
 
                 pProcess.Release();
             }
-            keepreading = 0;
+            break;
         } else {
-            printf("^error,msg=\"Unknown command: %s\"\n", line.c_str());
+            out_printf("%s^error,msg=\"Unknown command: %s\"\n", token, line.c_str());
         }
     }
 
-    /* Clean up our memory */
-    history_end(myhistory);
-    el_end(el);
-
     if (pProcess)
     {
-        hr = pProcess->Stop(0);
-        //fprintf(stderr, "Stop : hr=%x\n", hr);
-        if (SUCCEEDED(hr))
+        if (SUCCEEDED(pProcess->Stop(0)))
         {
             DisableAllBreakpointsAndSteppers(pProcess);
             hr = pProcess->Detach();
         }
     }
-    //fprintf(stderr, "Detach : hr=%x\n", hr);
 
     pCorDebug->Terminate();
 
-    printf("^exit\n");
+    out_printf("%s^exit\n", token);
 
     // TODO: Cleanup libcoreclr.so instance
 
diff --git a/src/debug/debugger/modules.cpp b/src/debug/debugger/modules.cpp
new file mode 100644 (file)
index 0000000..77d8d1e
--- /dev/null
@@ -0,0 +1,205 @@
+#include <windows.h>
+
+#include "corhdr.h"
+#include "cor.h"
+#include "cordebug.h"
+#include "debugshim.h"
+
+#include <sstream>
+#include <mutex>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "torelease.h"
+#include "symbolreader.h"
+
+struct ModuleInfo
+{
+    CORDB_ADDRESS address;
+    std::shared_ptr<SymbolReader> symbols;
+    //ICorDebugModule *module;
+};
+
+std::mutex g_modulesInfoMutex;
+std::unordered_map<std::string, ModuleInfo> g_modulesInfo;
+
+void SetCoreCLRPath(const std::string &coreclrPath)
+{
+    SymbolReader::SetCoreCLRPath(coreclrPath);
+}
+
+std::string GetModuleName(ICorDebugModule *pModule)
+{
+    char cname[mdNameLen];
+    WCHAR name[mdNameLen];
+    ULONG32 name_len = 0;
+    if (SUCCEEDED(pModule->GetName(mdNameLen, &name_len, name)))
+    {
+        WideCharToMultiByte(CP_UTF8, 0, name, (int)(PAL_wcslen(name) + 1), cname, mdNameLen, NULL, NULL);
+        return cname;
+    }
+    return std::string();
+}
+
+HRESULT GetLocationInModule(ICorDebugModule *pModule,
+                            std::string filename,
+                            ULONG linenum,
+                            ULONG32 &ilOffset,
+                            mdMethodDef &methodToken,
+                            std::string &fullname)
+{
+    HRESULT Status;
+
+    WCHAR nameBuffer[MAX_LONGPATH];
+
+    Status = MultiByteToWideChar(CP_UTF8, 0, filename.c_str(), filename.size() + 1, nameBuffer, MAX_LONGPATH);
+
+    std::string modName = GetModuleName(pModule);
+
+    std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
+    auto info_pair = g_modulesInfo.find(modName);
+    if (info_pair == g_modulesInfo.end())
+    {
+        return E_FAIL;
+    }
+
+    CORDB_ADDRESS modAddress;
+    IfFailRet(pModule->GetBaseAddress(&modAddress));
+    IfFailRet(info_pair->second.symbols->ResolveSequencePoint(nameBuffer, linenum, modAddress, &methodToken, &ilOffset));
+
+    WCHAR wFilename[MAX_LONGPATH];
+    ULONG resolvedLinenum;
+    IfFailRet(info_pair->second.symbols->GetLineByILOffset(methodToken, ilOffset, &resolvedLinenum, wFilename, _countof(wFilename)));
+
+    char cFilename[MAX_LONGPATH];
+    WideCharToMultiByte(CP_UTF8, 0, wFilename, (int)(PAL_wcslen(wFilename) + 1), cFilename, _countof(cFilename), NULL, NULL);
+    fullname = cFilename;
+
+    return S_OK;
+}
+
+HRESULT GetFrameLocation(ICorDebugFrame *pFrame,
+                         ULONG32 &ilOffset,
+                         mdMethodDef &methodToken,
+                         std::string &fullname,
+                         ULONG &linenum)
+{
+    HRESULT Status;
+
+    IfFailRet(pFrame->GetFunctionToken(&methodToken));
+
+    ToRelease<ICorDebugFunction> pFunc;
+    IfFailRet(pFrame->GetFunction(&pFunc));
+
+    ToRelease<ICorDebugModule> pModule;
+    IfFailRet(pFunc->GetModule(&pModule));
+
+    ToRelease<IUnknown> pMDUnknown;
+    ToRelease<IMetaDataImport> pMDImport;
+    IfFailRet(pModule->GetMetaDataInterface(IID_IMetaDataImport, &pMDUnknown));
+
+    ToRelease<ICorDebugILFrame> pILFrame;
+    IfFailRet(pFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame));
+
+    CorDebugMappingResult mappingResult;
+    IfFailRet(pILFrame->GetIP(&ilOffset, &mappingResult));
+
+    std::string modName = GetModuleName(pModule);
+    WCHAR name[MAX_LONGPATH];
+
+    {
+        std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
+        auto info_pair = g_modulesInfo.find(modName);
+        if (info_pair == g_modulesInfo.end())
+        {
+            return E_FAIL;
+        }
+
+        IfFailRet(info_pair->second.symbols->GetLineByILOffset(methodToken, ilOffset, &linenum, name, _countof(name)));
+    }
+
+    char cname[MAX_LONGPATH];
+
+    WideCharToMultiByte(CP_UTF8, 0, name, (int)(PAL_wcslen(name) + 1), cname, _countof(cname), NULL, NULL);
+
+    fullname = cname;
+
+    return S_OK;
+}
+
+HRESULT GetStepRangeFromCurrentIP(ICorDebugThread *pThread, COR_DEBUG_STEP_RANGE *range)
+{
+    HRESULT Status;
+    ToRelease<ICorDebugFrame> pFrame;
+    IfFailRet(pThread->GetActiveFrame(&pFrame));
+
+    mdMethodDef methodToken;
+    IfFailRet(pFrame->GetFunctionToken(&methodToken));
+
+    ToRelease<ICorDebugFunction> pFunc;
+    IfFailRet(pFrame->GetFunction(&pFunc));
+
+    ToRelease<ICorDebugModule> pModule;
+    IfFailRet(pFunc->GetModule(&pModule));
+
+    ToRelease<ICorDebugILFrame> pILFrame;
+    IfFailRet(pFrame->QueryInterface(IID_ICorDebugILFrame, (LPVOID*) &pILFrame));
+
+    ULONG32 nOffset;
+    CorDebugMappingResult mappingResult;
+    IfFailRet(pILFrame->GetIP(&nOffset, &mappingResult));
+
+    ULONG32 ilStartOffset;
+    ULONG32 ilEndOffset;
+
+    {
+        std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
+        auto info_pair = g_modulesInfo.find(GetModuleName(pModule));
+        if (info_pair == g_modulesInfo.end())
+        {
+            return E_FAIL;
+        }
+
+        IfFailRet(info_pair->second.symbols->GetStepRangesFromIP(nOffset, methodToken, &ilStartOffset, &ilEndOffset));
+    }
+
+    if (ilStartOffset == ilEndOffset)
+    {
+        ToRelease<ICorDebugCode> pCode;
+        IfFailRet(pFunc->GetILCode(&pCode));
+        IfFailRet(pCode->GetSize(&ilEndOffset));
+    }
+
+    range->startOffset = ilStartOffset;
+    range->endOffset = ilEndOffset;
+
+    return S_OK;
+}
+
+HRESULT TryLoadModuleSymbols(ICorDebugModule *pModule)
+{
+    HRESULT Status;
+    std::string name = GetModuleName(pModule);
+
+    if (name.empty())
+        return E_FAIL;
+
+    ToRelease<IUnknown> pMDUnknown;
+    ToRelease<IMetaDataImport> pMDImport;
+    IfFailRet(pModule->GetMetaDataInterface(IID_IMetaDataImport, &pMDUnknown));
+
+    IfFailRet(pMDUnknown->QueryInterface(IID_IMetaDataImport, (LPVOID*) &pMDImport));
+
+    auto symbolReader = std::make_shared<SymbolReader>();
+    IfFailRet(symbolReader->LoadSymbols(pMDImport, pModule));
+
+    CORDB_ADDRESS modAddress;
+    pModule->GetBaseAddress(&modAddress);
+
+    {
+        std::lock_guard<std::mutex> lock(g_modulesInfoMutex);
+        g_modulesInfo.insert({name, {modAddress, symbolReader}});
+    }
+    return S_OK;
+}
index 4c55a8a..06fd879 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <string>
 
+#include "torelease.h"
 #include "symbolreader.h"
 
 std::string SymbolReader::coreClrPath;
index 7c4cb84..8c73424 100644 (file)
@@ -1,42 +1,3 @@
-#ifndef IfFailRet
-#define IfFailRet(EXPR) do { Status = (EXPR); if(FAILED(Status)) { return (Status); } } while (0)
-#endif
-
-#ifndef _countof
-#define _countof(x) (sizeof(x)/sizeof(x[0]))
-#endif
-
-#ifdef PAL_STDCPP_COMPAT
-#define _iswprint   PAL_iswprint
-#define _wcslen     PAL_wcslen
-#define _wcsncmp    PAL_wcsncmp
-#define _wcsrchr    PAL_wcsrchr
-#define _wcscmp     PAL_wcscmp
-#define _wcschr     PAL_wcschr
-#define _wcscspn    PAL_wcscspn
-#define _wcscat     PAL_wcscat
-#define _wcsstr     PAL_wcsstr
-#else // PAL_STDCPP_COMPAT
-#define _iswprint   iswprint
-#define _wcslen     wcslen
-#define _wcsncmp    wcsncmp
-#define _wcsrchr    wcsrchr
-#define _wcscmp     wcscmp
-#define _wcschr     wcschr
-#define _wcscspn    wcscspn
-#define _wcscat     wcscat
-#define _wcsstr     wcsstr
-#endif // !PAL_STDCPP_COMPAT
-
-typedef uintptr_t TADDR;
-typedef ULONG64 CLRDATA_ADDRESS;
-
-// Convert between CLRDATA_ADDRESS and TADDR.
-#define TO_TADDR(cdaddr) ((TADDR)(cdaddr))
-#define TO_CDADDR(taddr) ((CLRDATA_ADDRESS)(LONG_PTR)(taddr))
-
-const int mdNameLen = 2048;
-
 static const char *SymbolReaderDllName = "SOS.NETCore";
 static const char *SymbolReaderClassName = "SOS.SymbolReader";
 
index 81612be..e48b86a 100644 (file)
@@ -70,3 +70,42 @@ public:
 private:
     T* m_ptr;
 };
+
+#ifndef IfFailRet
+#define IfFailRet(EXPR) do { Status = (EXPR); if(FAILED(Status)) { return (Status); } } while (0)
+#endif
+
+#ifndef _countof
+#define _countof(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+#ifdef PAL_STDCPP_COMPAT
+#define _iswprint   PAL_iswprint
+#define _wcslen     PAL_wcslen
+#define _wcsncmp    PAL_wcsncmp
+#define _wcsrchr    PAL_wcsrchr
+#define _wcscmp     PAL_wcscmp
+#define _wcschr     PAL_wcschr
+#define _wcscspn    PAL_wcscspn
+#define _wcscat     PAL_wcscat
+#define _wcsstr     PAL_wcsstr
+#else // PAL_STDCPP_COMPAT
+#define _iswprint   iswprint
+#define _wcslen     wcslen
+#define _wcsncmp    wcsncmp
+#define _wcsrchr    wcsrchr
+#define _wcscmp     wcscmp
+#define _wcschr     wcschr
+#define _wcscspn    wcscspn
+#define _wcscat     wcscat
+#define _wcsstr     wcsstr
+#endif // !PAL_STDCPP_COMPAT
+
+typedef uintptr_t TADDR;
+typedef ULONG64 CLRDATA_ADDRESS;
+
+// Convert between CLRDATA_ADDRESS and TADDR.
+#define TO_TADDR(cdaddr) ((TADDR)(cdaddr))
+#define TO_CDADDR(taddr) ((CLRDATA_ADDRESS)(LONG_PTR)(taddr))
+
+const int mdNameLen = 2048;