From 2cf1e2431eb962dfc045d06f4b9a7eac246fc33c Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <qtc-committer@nokia.com>
Date: Mon, 23 Feb 2009 16:13:35 +0100
Subject: [PATCH] Load library at runtime

---
 src/plugins/debugger/cdb/cdb.pri            |   3 -
 src/plugins/debugger/cdb/cdbdebugengine.cpp | 101 +++++++++++++++-----
 src/plugins/debugger/cdb/cdbdebugengine.h   |   8 +-
 src/plugins/debugger/cdb/cdbdebugengine_p.h |  21 +++-
 4 files changed, 104 insertions(+), 29 deletions(-)

diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri
index 8a098aa54b2..527cd0be298 100644
--- a/src/plugins/debugger/cdb/cdb.pri
+++ b/src/plugins/debugger/cdb/cdb.pri
@@ -25,9 +25,6 @@ SOURCES += \
     $$PWD/cdbdebugengine.cpp \
     $$PWD/cdbdebugeventcallback.cpp \
     $$PWD/cdbdebugoutput.cpp
-
-LIBS += -L$$CDB_LIBPATH Dbghelp.lib dbgeng.lib
-
 } else {
    error("Debugging Tools for Windows could not be found in $$CDB_PATH")
 }
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 7fa9afca716..e397410f7bd 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -44,14 +44,46 @@
 #include <QtCore/QTimerEvent>
 #include <QtCore/QFileInfo>
 #include <QtCore/QDir>
+#include <QtCore/QLibrary>
 
 #define DBGHELP_TRANSLATE_TCHAR
 #include <inc/Dbghelp.h>
 
-using namespace Debugger;
-using namespace Debugger::Internal;
+static const char *dbgEngineDllC = "dbgeng";
+static const char *debugCreateFuncC = "DebugCreate";
 
-CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine) :
+namespace Debugger {
+namespace Internal {
+
+DebuggerEngineLibrary::DebuggerEngineLibrary() :
+    m_debugCreate(0)
+{
+}
+
+bool DebuggerEngineLibrary::init(QString *errorMessage)
+{
+    // Load
+    QLibrary lib(QLatin1String(dbgEngineDllC), 0);
+
+    if (!lib.isLoaded() && !lib.load()) {
+        *errorMessage = CdbDebugEngine::tr("Unable to load the debugger engine library '%1': %2").
+                        arg(QLatin1String(dbgEngineDllC), lib.errorString());
+        return false;
+    }
+    // Locate symbols
+    void *createFunc = lib.resolve(debugCreateFuncC);
+    if (!createFunc) {
+        *errorMessage = CdbDebugEngine::tr("Unable to resolve '%1' in the debugger engine library '%2'").
+                        arg(QLatin1String(debugCreateFuncC), QLatin1String(dbgEngineDllC));
+        return false;
+    }
+    m_debugCreate = static_cast<DebugCreateFunction>(createFunc);
+    return true;
+}
+
+// --- CdbDebugEnginePrivate
+
+CdbDebugEnginePrivate::CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine) :
     m_hDebuggeeProcess(0),
     m_hDebuggeeThread(0),
     m_bIgnoreNextDebugEvent(false),
@@ -63,24 +95,40 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEn
     m_debuggerManagerAccess(parent->engineInterface())
 {
     HRESULT hr;
-    hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
-    if (FAILED(hr)) m_pDebugClient = 0;
-    hr = DebugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl));
-    if (FAILED(hr)) m_pDebugControl = 0;
-    hr = DebugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects));
+    hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
+    if (FAILED(hr)) {
+        m_pDebugClient = 0;
+    } else {
+        m_pDebugClient->SetOutputCallbacks(&m_debugOutputCallBack);
+        m_pDebugClient->SetEventCallbacks(&m_debugEventCallBack);
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl));
+    if (FAILED(hr)) {
+        m_pDebugControl = 0;
+    } else {
+        m_pDebugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects));
     if (FAILED(hr)) m_pDebugSystemObjects = 0;
-    hr = DebugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols));
+
+    hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols));
     if (FAILED(hr)) m_pDebugSymbols = 0;
-    hr = DebugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
+
+    hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
     if (FAILED(hr)) m_pDebugRegisters = 0;
+}
 
-    if (m_pDebugControl) {
-        m_pDebugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
-    }
-    if (m_pDebugClient) {
-        m_pDebugClient->SetOutputCallbacks(&m_debugOutputCallBack);
-        m_pDebugClient->SetEventCallbacks(&m_debugEventCallBack);
+IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent)
+{
+    DebuggerEngineLibrary lib;
+    QString errorMessage;
+    if (!lib.init(&errorMessage)) {
+        qWarning("%s", qPrintable(errorMessage));
+        return 0;
     }
+    return new CdbDebugEngine(lib, parent);
 }
 
 CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
@@ -97,9 +145,9 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
         m_pDebugRegisters->Release();
 }
 
-CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
-  : IDebuggerEngine(parent),
-    m_d(new CdbDebugEnginePrivate(parent, this))
+CdbDebugEngine::CdbDebugEngine(const DebuggerEngineLibrary &lib, DebuggerManager *parent) :
+    IDebuggerEngine(parent),
+    m_d(new CdbDebugEnginePrivate(lib, parent, this))
 {
 }
 
@@ -628,11 +676,6 @@ void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT pBP)
         qDebug() << Q_FUNC_INFO;
 }
 
-IDebuggerEngine *createWinEngine(DebuggerManager *parent)
-{
-    return new CdbDebugEngine(parent);
-}
-
 void CdbDebugEngine::setDebugDumpers(bool on)
 {
     Q_UNUSED(on)
@@ -646,3 +689,13 @@ void CdbDebugEngine::setUseCustomDumpers(bool on)
 void CdbDebugEngine::reloadSourceFiles()
 {
 }
+
+} // namespace Internal
+} // namespace Debugger
+
+// Accessed by DebuggerManager
+Debugger::Internal::IDebuggerEngine *createWinEngine(Debugger::Internal::DebuggerManager *parent)
+{
+    return Debugger::Internal::CdbDebugEngine::create(parent);
+}
+
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h
index aee16bfc38d..b8476d55afc 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine.h
@@ -41,16 +41,22 @@ namespace Internal {
 
 class DebuggerManager;
 class CdbDebugEventCallback;
+class DebuggerEngineLibrary;
 class CdbDebugOutput;
 struct CdbDebugEnginePrivate;
 
 class CdbDebugEngine : public IDebuggerEngine
 {
+    Q_DISABLE_COPY(CdbDebugEngine)
     Q_OBJECT
+    explicit CdbDebugEngine(const DebuggerEngineLibrary &lib, DebuggerManager *parent);
+
 public:
-    CdbDebugEngine(DebuggerManager *parent);
     ~CdbDebugEngine();
 
+    // Factory function that returns 0 if the debug engine library cannot be found.
+    static IDebuggerEngine *create(DebuggerManager *parent);
+
     virtual void shutdown();
     virtual void setToolTipExpression(const QPoint &pos, const QString &exp);
     virtual bool startDebugger();
diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h
index db3a19e0a8b..57f5499dd44 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine_p.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h
@@ -43,9 +43,27 @@ namespace Internal {
 class DebuggerManager;
 class IDebuggerManagerAccessForEngines;
 
+// Thin wrapper around the 'DBEng' debugger engine shared library
+// which is loaded at runtime.
+
+class DebuggerEngineLibrary {
+public:
+    DebuggerEngineLibrary();
+    bool init(QString *errorMessage);
+
+    inline HRESULT debugCreate(REFIID interfaceId, PVOID *interfaceHandle) const
+        { return m_debugCreate(interfaceId, interfaceHandle); }
+
+private:
+    // The exported functions of the library
+    typedef HRESULT (*DebugCreateFunction)(REFIID, PVOID *);
+
+    DebugCreateFunction m_debugCreate;
+};
+
 struct CdbDebugEnginePrivate
 {    
-    explicit CdbDebugEnginePrivate(DebuggerManager *parent,  CdbDebugEngine* engine);
+    explicit CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent,  CdbDebugEngine* engine);
     ~CdbDebugEnginePrivate();
 
     bool isDebuggeeRunning() const { return m_watchTimer != -1; }
@@ -80,3 +98,4 @@ enum { debugCDB = 0 };
 } // namespace Debugger
 
 #endif // DEBUGGER_CDBENGINEPRIVATE_H
+
-- 
GitLab