diff --git a/share/qtcreator/dumper/bridge.py b/share/qtcreator/dumper/bridge.py
index af91e6196534dfb5ffa618ec0baaa7120abdf992..b95a57d8158736071da0a76d4ab98a6149e423b0 100644
--- a/share/qtcreator/dumper/bridge.py
+++ b/share/qtcreator/dumper/bridge.py
@@ -559,6 +559,53 @@ try:
     def fieldCount(type):
         return type.fieldCount();
 
+    def threadsData(threadsOptions):
+        result = "threads={threads=["
+        for i in range(lldb.process.num_threads):
+            thread = lldb.process.GetThreadAtIndex(i)
+            result += "{id=\"%d\"" % thread.id
+            result += ",target-id=\"%s\"" % thread.id
+            result += ",stop-reason=\"%s\"" % thread.stop_reason
+
+            if thread.IsSuspended():
+                result += ",state=\"stopped\""
+            else:
+                result += ",state=\"running\""
+
+            if not thread.name is None:
+                result += ",name=\"%s\"" % thread.name
+
+            result += ",frame={"
+            frame = thread.GetFrameAtIndex(0)
+            result += "pc=\"%s\"" % frame.pc
+            result += ",level=\"%d\"" % i
+            result += ",addr=\"%s\"" % frame.pc
+            result += ",fp=\"%s\"" % frame.fp
+            result += ",func=\"%s\"" % frame.function.name
+            result += ",line=\"%s\"" % frame.line_entry.line
+            result += ",fullname=\"%s\"" % frame.line_entry.file
+            result += ",file=\"%s\"" % frame.line_entry.file
+            result += "}},"
+
+        result += "],current-thread-id=\"%s\"}" % lldb.process.GetSelectedThread().id
+        return result
+
+    def stackData(stackOptions):
+        result = "stack=["
+        result += "],"
+        return result
+
+    def updateData(parts, localsOptions, stackOptions, threadsOptions):
+        result = "";
+        if parts & 1:
+            result += bb(localsOptions) + ','
+        if parts & 2:
+            result += stackData(stackOptions)
+        if parts & 4:
+            result += threadsData(threadsOptions)
+        return result
+
+
 except:
     #warn("LOADING LLDB FAILED")
     pass
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 24eb084d4e38cd18827f7b9b32fc7290a962016a..509ed97dda5edd8e72c5059c8e642c2f05459dae 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -43,6 +43,7 @@
 #include "registerhandler.h"
 #include "stackhandler.h"
 #include "sourceutils.h"
+#include "threadshandler.h"
 #include "watchhandler.h"
 #include "watchutils.h"
 
@@ -360,13 +361,13 @@ void LldbEngine::activateFrame(int frameIndex)
         return;
 
     postCommand("frame select " + QByteArray::number(frameIndex),
-        CB(handleUpdateAll));
+        CB(triggerUpdateAll));
 }
 
 void LldbEngine::selectThread(ThreadId threadId)
 {
     postCommand("thread select " + QByteArray::number(threadId.raw()),
-        CB(handleUpdateAll));
+        CB(triggerUpdateAll));
 }
 
 bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const
@@ -757,7 +758,7 @@ void LldbEngine::handleFirstCommand(const LldbResponse &response)
     Q_UNUSED(response);
 }
 
-void LldbEngine::handleUpdateAll(const LldbResponse &response)
+void LldbEngine::triggerUpdateAll(const LldbResponse &response)
 {
     Q_UNUSED(response);
     updateAll();
@@ -765,43 +766,53 @@ void LldbEngine::handleUpdateAll(const LldbResponse &response)
 
 void LldbEngine::updateAll()
 {
-    //postCommand("bt", CB(handleBacktrace));
-    updateLocals();
+    updateData(DataKind(LocalsData | StackData | ThreadData));
 }
 
-void LldbEngine::updateLocals()
+void LldbEngine::updateData(DataKind kind)
 {
-    QByteArray watchers;
-    //if (!m_toolTipExpression.isEmpty())
-    //    watchers += m_toolTipExpression.toLatin1()
-    //        + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1());
+    QByteArray localsOptions;
+    QByteArray stackOptions;
+    QByteArray threadsOptions;
 
-    WatchHandler *handler = watchHandler();
-    QHash<QByteArray, int> watcherNames = handler->watcherNames();
-    QHashIterator<QByteArray, int> it(watcherNames);
-    while (it.hasNext()) {
-        it.next();
-        if (!watchers.isEmpty())
-            watchers += "##";
-        watchers += it.key() + "#watch." + QByteArray::number(it.value());
-    }
+    if (kind & LocalsData) {
+        QByteArray watchers;
+        //if (!m_toolTipExpression.isEmpty())
+        //    watchers += m_toolTipExpression.toLatin1()
+        //        + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1());
 
-    QByteArray options;
-    if (debuggerCore()->boolSetting(UseDebuggingHelpers))
-        options += "fancy,";
-    if (debuggerCore()->boolSetting(AutoDerefPointers))
-        options += "autoderef,";
-    if (options.isEmpty())
-        options += "defaults,";
-    options.chop(1);
+        WatchHandler *handler = watchHandler();
+        QHash<QByteArray, int> watcherNames = handler->watcherNames();
+        QHashIterator<QByteArray, int> it(watcherNames);
+        while (it.hasNext()) {
+            it.next();
+            if (!watchers.isEmpty())
+                watchers += "##";
+            watchers += it.key() + "#watch." + QByteArray::number(it.value());
+        }
 
-    postCommand("script bb('options:" + options + " "
-        + "vars: "
-        + "expanded:" + handler->expansionRequests() + " "
-        + "typeformats:" + handler->typeFormatRequests() + " "
-        + "formats:" + handler->individualFormatRequests() + " "
-        + "watcher:" + watchers.toHex() + "')",
-                CB(handleListLocals));
+        QByteArray options;
+        if (debuggerCore()->boolSetting(UseDebuggingHelpers))
+            options += "fancy,";
+        if (debuggerCore()->boolSetting(AutoDerefPointers))
+            options += "autoderef,";
+        if (options.isEmpty())
+            options += "defaults,";
+        options.chop(1);
+
+        localsOptions = "options:" + options + " "
+            + "vars: "
+            + "expanded:" + handler->expansionRequests() + " "
+            + "typeformats:" + handler->typeFormatRequests() + " "
+            + "formats:" + handler->individualFormatRequests() + " "
+            + "watcher:" + watchers.toHex();
+    }
+
+    postCommand("script updateData(" + QByteArray::number(kind) + ','
+            + '\'' + localsOptions + "',"
+            + '\'' + stackOptions + "',"
+            + '\'' + threadsOptions + "')",
+                CB(handleUpdateData));
 }
 
 void LldbEngine::handleBacktrace(const LldbResponse &response)
@@ -847,62 +858,69 @@ void LldbEngine::handleBacktrace(const LldbResponse &response)
         gotoLocation(stackFrames.at(currentIndex));
     }
 
-    updateLocals();
+    updateData(LocalsData);
 }
 
-void LldbEngine::handleListLocals(const LldbResponse &response)
+GdbMi LldbEngine::parseFromString(QByteArray out)
 {
-    //qDebug() << " LOCALS: '" << response.data << "'";
-    QByteArray out = response.data;
+    GdbMi all;
 
-    {
-        int pos = out.indexOf("data=");
-        if (pos == -1) {
-            showMessage(_("UNEXPECTED LOCALS OUTPUT:" + out));
-            return;
-        }
+    int pos = out.indexOf("data=");
+    if (pos == -1) {
+        showMessage(_("UNEXPECTED LOCALS OUTPUT:" + out));
+        return all;
+    }
 
-        // The value in 'out' should be single-quoted as this is
-        // what the command line does with strings.
-        if (pos != 1) {
-            showMessage(_("DISCARDING JUNK AT BEGIN OF RESPONSE: "
-                + out.left(pos)));
-        }
-        out = out.mid(pos);
-        if (out.endsWith('\''))
-            out.chop(1);
-        else
-            showMessage(_("JUNK AT END OF RESPONSE: " + out));
+    // The value in 'out' should be single-quoted as this is
+    // what the command line does with strings.
+    if (pos != 1) {
+        showMessage(_("DISCARDING JUNK AT BEGIN OF RESPONSE: "
+            + out.left(pos)));
     }
+    out = out.mid(pos);
+    if (out.endsWith('\''))
+        out.chop(1);
+    else
+        showMessage(_("JUNK AT END OF RESPONSE: " + out));
 
-    GdbMi all;
     all.fromStringMultiple(out);
-    GdbMi data = all.findChild("data");
-
-    const bool partial = response.cookie.toBool();
-    WatchHandler *handler = watchHandler();
-    QList<WatchData> list;
+    return all;
+}
 
-    if (!partial) {
-        list.append(*handler->findData("local"));
-        list.append(*handler->findData("watch"));
-        list.append(*handler->findData("return"));
-    }
+void LldbEngine::handleUpdateData(const LldbResponse &response)
+{
+    //qDebug() << " LOCALS: '" << response.data << "'";
+    GdbMi all = parseFromString(response.data);
+
+    GdbMi vars = all.findChild("data");
+    if (vars.isValid()) {
+        const bool partial = response.cookie.toBool();
+        WatchHandler *handler = watchHandler();
+        QList<WatchData> list;
+
+        if (!partial) {
+            list.append(*handler->findData("local"));
+            list.append(*handler->findData("watch"));
+            list.append(*handler->findData("return"));
+        }
 
-    foreach (const GdbMi &child, data.children()) {
-        WatchData dummy;
-        dummy.iname = child.findChild("iname").data();
-        GdbMi wname = child.findChild("wname");
-        if (wname.isValid()) {
-            // Happens (only) for watched expressions. They are encoded as
-            // base64 encoded 8 bit data, without quotes
-            dummy.name = decodeData(wname.data(), Base64Encoded8Bit);
-            dummy.exp = dummy.name.toUtf8();
-        } else {
-            dummy.name = _(child.findChild("name").data());
+        foreach (const GdbMi &child, vars.children()) {
+            WatchData dummy;
+            dummy.iname = child.findChild("iname").data();
+            GdbMi wname = child.findChild("wname");
+            if (wname.isValid()) {
+                // Happens (only) for watched expressions. They are encoded as
+                // base64 encoded 8 bit data, without quotes
+                dummy.name = decodeData(wname.data(), Base64Encoded8Bit);
+                dummy.exp = dummy.name.toUtf8();
+            } else {
+                dummy.name = _(child.findChild("name").data());
+            }
+            parseWatchData(handler->expandedINames(), dummy, child, &list);
         }
-        parseWatchData(handler->expandedINames(), dummy, child, &list);
+        handler->insertData(list);
     }
+
 //    const GdbMi typeInfo = all.findChild("typeinfo");
 //    if (typeInfo.type() == GdbMi::List) {
 //        foreach (const GdbMi &s, typeInfo.children()) {
@@ -919,11 +937,23 @@ void LldbEngine::handleListLocals(const LldbResponse &response)
 //            list[i].size = ti.size;
 //    }
 
-    handler->insertData(list);
+    GdbMi stack = all.findChild("stack");
+    if (stack.isValid()) {
+        //if (!partial)
+        //    emit stackFrameCompleted();
+    }
 
-    //rebuildWatchModel();
-    if (!partial)
-        emit stackFrameCompleted();
+    GdbMi threads = all.findChild("threads");
+    if (threads.isValid()) {
+        ThreadsHandler *handler = threadsHandler();
+        handler->updateThreads(threads);
+        if (!handler->currentThread().isValid()) {
+            ThreadId other = handler->threadAt(0);
+            if (other.isValid())
+                selectThread(other);
+        }
+        updateViews(); // Adjust Threads combobox.
+    }
 }
 
 void LldbEngine::loadPythonDumpers()
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index 9efe1e8589e1d08a9485dbb7ccba7e9b33e6aab9..7071d31bfa451fb2ef73ebc9b8f7cb2c9be92e49 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -121,10 +121,13 @@ private:
     Q_SLOT void handleOutput2(const QByteArray &data);
     void handleResponse(const QByteArray &ba);
 
+    enum DataKind { LocalsData = 1, StackData = 2, ThreadData = 4 };
+
     void loadPythonDumpers();
     void updateAll();
-    void updateLocals();
-    void handleUpdateAll(const LldbResponse &response);
+    void updateData(DataKind kind);
+    void triggerUpdateAll(const LldbResponse &response);
+    void handleUpdateData(const LldbResponse &response);
     void handleFirstCommand(const LldbResponse &response);
     void handleExecuteDebuggerCommand(const LldbResponse &response);
     void handleInferiorSetup(const LldbResponse &response);
@@ -152,6 +155,8 @@ private:
     void handleListModules(const LldbResponse &response);
     void handleListSymbols(const LldbResponse &response);
     void handleBreakInsert(const LldbResponse &response);
+    void handleUpdateStack(const LldbResponse &response);
+    void handleUpdateThreads(const LldbResponse &response);
 
     void handleChildren(const WatchData &data0, const GdbMi &item,
         QList<WatchData> *list);
@@ -160,6 +165,7 @@ private:
                      const char *callbackName = 0,
                      const QVariant &cookie = QVariant());
     void postDirectCommand(const QByteArray &command);
+    GdbMi parseFromString(QByteArray out);
 
     QQueue<LldbCommand> m_commands;