cdbsymbolgroupcontext.cpp 19 KB
Newer Older
1
2
3
4
5
6
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
26
** contact the sales department at http://www.qtsoftware.com/contact.
27
28
29
30
31
32
**
**************************************************************************/

#include "cdbsymbolgroupcontext.h"
#include "cdbdebugengine_p.h"
#include "watchhandler.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
33
#include "watchutils.h"
hjk's avatar
hjk committed
34

Friedemann Kleint's avatar
Friedemann Kleint committed
35
#include <QtCore/QTextStream>
36
#include <QtCore/QRegExp>
Friedemann Kleint's avatar
Friedemann Kleint committed
37

Friedemann Kleint's avatar
Friedemann Kleint committed
38
39
enum { debug = 0 };

40
41
42
43
static inline QString msgSymbolNotFound(const QString &s)
{
    return QString::fromLatin1("The symbol '%1' could not be found.").arg(s);
}
44

hjk's avatar
hjk committed
45
46
47
48
static inline bool isTopLevelSymbol(const DEBUG_SYMBOL_PARAMETERS &p)
{
    return p.ParentSymbol == DEBUG_ANY_ID;
}
49

Friedemann Kleint's avatar
Friedemann Kleint committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
static inline void debugSymbolFlags(unsigned long f, QTextStream &str)
{
    if (f & DEBUG_SYMBOL_EXPANDED)
        str << "DEBUG_SYMBOL_EXPANDED";
    if (f & DEBUG_SYMBOL_READ_ONLY)
        str << "|DEBUG_SYMBOL_READ_ONLY";
    if (f & DEBUG_SYMBOL_IS_ARRAY)
        str << "|DEBUG_SYMBOL_IS_ARRAY";
    if (f & DEBUG_SYMBOL_IS_FLOAT)
        str << "|DEBUG_SYMBOL_IS_FLOAT";
    if (f & DEBUG_SYMBOL_IS_ARGUMENT)
        str << "|DEBUG_SYMBOL_IS_ARGUMENT";
    if (f & DEBUG_SYMBOL_IS_LOCAL)
        str << "|DEBUG_SYMBOL_IS_LOCAL";
}

hjk's avatar
hjk committed
66
QTextStream &operator<<(QTextStream &str, const DEBUG_SYMBOL_PARAMETERS &p)
Friedemann Kleint's avatar
Friedemann Kleint committed
67
68
{
    str << " Type=" << p.TypeId << " parent=";
69
    if (isTopLevelSymbol(p)) {
Friedemann Kleint's avatar
Friedemann Kleint committed
70
71
        str << "<ROOT>";
    } else {
hjk's avatar
hjk committed
72
        str << p.ParentSymbol;
Friedemann Kleint's avatar
Friedemann Kleint committed
73
74
75
76
77
    }
    str << " Subs=" << p.SubElements << " flags=" << p.Flags << '/';
    debugSymbolFlags(p.Flags, str);
    return str;
}
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

// A helper function to extract a string value from a member function of
// IDebugSymbolGroup2 taking the symbol index and a character buffer.
// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide'

typedef HRESULT  (__stdcall IDebugSymbolGroup2::*WideStringRetrievalFunction)(ULONG, PWSTR, ULONG, PULONG);

static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
                                      WideStringRetrievalFunction wsf,
                                      unsigned long index)
{
    static WCHAR nameBuffer[MAX_PATH + 1];
    // Name
    ULONG nameLength;
    const HRESULT hr = (sg->*wsf)(index, nameBuffer, MAX_PATH, &nameLength);
    if (SUCCEEDED(hr)) {
        nameBuffer[nameLength] = 0;
95
        return QString::fromUtf16(reinterpret_cast<const ushort *>(nameBuffer));
96
97
98
99
100
    }
    return QString();
}

namespace Debugger {
hjk's avatar
hjk committed
101
namespace Internal {
102

103
104
105
106
107
108
109
110
111
static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMBOL_PARAMETERS &p)
{
    if (p.SubElements == 0u)
        return CdbSymbolGroupContext::LeafSymbol;
    return (p.Flags & DEBUG_SYMBOL_EXPANDED) ?
               CdbSymbolGroupContext::ExpandedSymbol :
               CdbSymbolGroupContext::CollapsedSymbol;
}

112
CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
113
                                             CIDebugSymbolGroup *symbolGroup) :
114
115
    m_prefix(prefix),
    m_nameDelimiter(QLatin1Char('.')),
116
117
    m_symbolGroup(symbolGroup),
    m_unnamedSymbolNumber(1)
118
119
120
121
122
123
124
125
{
}

CdbSymbolGroupContext::~CdbSymbolGroupContext()
{
    m_symbolGroup->Release();
}

Friedemann Kleint's avatar
Friedemann Kleint committed
126
CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
127
                                                     CIDebugSymbolGroup *symbolGroup,
Friedemann Kleint's avatar
Friedemann Kleint committed
128
129
                                                     QString *errorMessage)
{
hjk's avatar
hjk committed
130
    CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup);
Friedemann Kleint's avatar
Friedemann Kleint committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    if (!rc->init(errorMessage)) {
        delete rc;
        return 0;
    }
    return rc;
}

bool CdbSymbolGroupContext::init(QString *errorMessage)
{
    // retrieve the root symbols
    ULONG count;
    HRESULT hr = m_symbolGroup->GetNumberSymbols(&count);
    if (FAILED(hr)) {
        *errorMessage = msgComFailed("GetNumberSymbols", hr);
        return false;
    }

148
149
150
    if (count) {
        m_symbolParameters.reserve(3u * count);
        m_symbolParameters.resize(count);
Friedemann Kleint's avatar
Friedemann Kleint committed
151

152
153
154
155
156
157
        hr = m_symbolGroup->GetSymbolParameters(0, count, symbolParameters());
        if (FAILED(hr)) {
            *errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
            return false;
        }
        populateINameIndexMap(m_prefix, DEBUG_ANY_ID, 0, count);
Friedemann Kleint's avatar
Friedemann Kleint committed
158
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
159
    if (debug)
160
        qDebug() << Q_FUNC_INFO << '\n'<< toString();
Friedemann Kleint's avatar
Friedemann Kleint committed
161
162
163
    return true;
}

164
165
void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigned long parentId,
                                                  unsigned long start, unsigned long count)
Friedemann Kleint's avatar
Friedemann Kleint committed
166
{
167
168
    // Make the entries for iname->index mapping. We might encounter
    // already expanded subitems when doing it for top-level, recurse in that case.
Friedemann Kleint's avatar
Friedemann Kleint committed
169
    const QString symbolPrefix = prefix + m_nameDelimiter;
Friedemann Kleint's avatar
Friedemann Kleint committed
170
    if (debug)
171
172
173
174
175
176
177
178
        qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << start << count;
    const unsigned long end = m_symbolParameters.size();
    unsigned long seenChildren = 0;
    // Skip over expanded children
    for (unsigned long i = start; i < end && seenChildren < count; i++) {
        const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
        if (parentId == p.ParentSymbol) {
            seenChildren++;
179
180
181
182
183
184
185
186
187
            // "__formal" occurs when someone writes "void foo(int /* x */)..."
            static const QString unnamedFormalParameter = QLatin1String("__formal");
            QString symbolName = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
            if (symbolName == unnamedFormalParameter) {
                symbolName = QLatin1String("<unnamed");
                symbolName += QString::number(m_unnamedSymbolNumber++);
                symbolName += QLatin1Char('>');
            }
            const QString name = symbolPrefix + symbolName;
188
189
190
191
            m_inameIndexMap.insert(name, i);
            if (getSymbolState(p) == ExpandedSymbol)
                populateINameIndexMap(name, i, i + 1, p.SubElements);
        }
Friedemann Kleint's avatar
Friedemann Kleint committed
192
193
194
    }
}

Friedemann Kleint's avatar
Friedemann Kleint committed
195
QString CdbSymbolGroupContext::toString(bool verbose) const
Friedemann Kleint's avatar
Friedemann Kleint committed
196
197
198
199
200
201
202
{
    QString rc;
    QTextStream str(&rc);
    const int count = m_symbolParameters.size();
    for (int i = 0; i < count; i++) {
        str << i << ' ';
        const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
203
        if (!isTopLevelSymbol(p))
Friedemann Kleint's avatar
Friedemann Kleint committed
204
205
206
207
208
209
            str << "    ";
        str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
        if (p.Flags & DEBUG_SYMBOL_IS_LOCAL)
            str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i);
        str << p << '\n';
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
210
211
212
213
214
215
    if (verbose) {
        str << "NameIndexMap\n";
        NameIndexMap::const_iterator ncend = m_inameIndexMap.constEnd();
        for (NameIndexMap::const_iterator it = m_inameIndexMap.constBegin() ; it != ncend; ++it)
            str << it.key() << ' ' << it.value() << '\n';
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
216
217
218
    return rc;
}

219
220
221
222
CdbSymbolGroupContext::SymbolState CdbSymbolGroupContext::symbolState(unsigned long index) const
{
    return getSymbolState(m_symbolParameters.at(index));
}
Friedemann Kleint's avatar
Friedemann Kleint committed
223

224
CdbSymbolGroupContext::SymbolState CdbSymbolGroupContext::symbolState(const QString &prefix) const
Friedemann Kleint's avatar
Friedemann Kleint committed
225
{
226
227
    if (prefix == m_prefix) // root
        return ExpandedSymbol;
Friedemann Kleint's avatar
Friedemann Kleint committed
228
229
    unsigned long index;
    if (!lookupPrefix(prefix, &index)) {
230
        qWarning("WARNING %s: %s\n", Q_FUNC_INFO, qPrintable(msgSymbolNotFound(prefix)));
Friedemann Kleint's avatar
Friedemann Kleint committed
231
232
233
234
235
236
237
238
239
        return LeafSymbol;
    }
    return symbolState(index);
}

// Find index of a prefix
bool CdbSymbolGroupContext::lookupPrefix(const QString &prefix, unsigned long *index) const
{
    *index = 0;
240
    const NameIndexMap::const_iterator it = m_inameIndexMap.constFind(prefix);
Friedemann Kleint's avatar
Friedemann Kleint committed
241
242
243
244
    if (it == m_inameIndexMap.constEnd())
        return false;
    *index = it.value();
    return true;
Friedemann Kleint's avatar
Friedemann Kleint committed
245
246
247
248
249
250
251
}

/* Retrieve children and get the position. */
bool CdbSymbolGroupContext::getChildSymbolsPosition(const QString &prefix,
                                                    unsigned long *start,
                                                    unsigned long *parentId,
                                                    QString *errorMessage)
252
{
Friedemann Kleint's avatar
Friedemann Kleint committed
253
    if (debug)
Friedemann Kleint's avatar
Friedemann Kleint committed
254
        qDebug() << Q_FUNC_INFO << '\n'<< prefix;
255

Friedemann Kleint's avatar
Friedemann Kleint committed
256
257
258
259
260
    *start = *parentId = 0;
    // Root item?
    if (prefix == m_prefix) {
        *start = 0;
        *parentId = DEBUG_ANY_ID;
Friedemann Kleint's avatar
Friedemann Kleint committed
261
        if (debug)
262
            qDebug() << '<' << prefix << "at" << *start;
Friedemann Kleint's avatar
Friedemann Kleint committed
263
264
265
266
267
268
269
        return true;
    }
    // Get parent index, make sure it is expanded
    NameIndexMap::const_iterator nit = m_inameIndexMap.constFind(prefix);
    if (nit == m_inameIndexMap.constEnd()) {
        *errorMessage = QString::fromLatin1("'%1' not found.").arg(prefix);
        return false;
270
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
271
272
273
274
    *parentId = nit.value();
    *start = nit.value() + 1;
    if (!expandSymbol(prefix, *parentId, errorMessage))
        return false;
Friedemann Kleint's avatar
Friedemann Kleint committed
275
    if (debug)
276
        qDebug() << '<' << prefix << "at" << *start;
Friedemann Kleint's avatar
Friedemann Kleint committed
277
    return true;
278
279
}

280
281
282
283
284
static inline QString msgExpandFailed(const QString &prefix, unsigned long index, const QString &why)
{
    return QString::fromLatin1("Unable to expand '%1' %2: %3").arg(prefix).arg(index).arg(why);
}

Friedemann Kleint's avatar
Friedemann Kleint committed
285
286
// Expand a symbol using the symbol group interface.
bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long index, QString *errorMessage)
287
{
Friedemann Kleint's avatar
Friedemann Kleint committed
288
    if (debug)
289
        qDebug() << '>' << Q_FUNC_INFO << '\n' << prefix << index;
290

291
292
293
294
295
    switch (symbolState(index)) {
    case LeafSymbol:
        *errorMessage = QString::fromLatin1("Attempt to expand leaf node '%1' %2!").arg(prefix).arg(index);
        return false;
    case ExpandedSymbol:
Friedemann Kleint's avatar
Friedemann Kleint committed
296
        return true;
297
298
299
    case CollapsedSymbol:
        break;
    }
300

Friedemann Kleint's avatar
Friedemann Kleint committed
301
302
    HRESULT hr = m_symbolGroup->ExpandSymbol(index, TRUE);
    if (FAILED(hr)) {
303
        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("ExpandSymbol", hr));
Friedemann Kleint's avatar
Friedemann Kleint committed
304
305
306
307
308
309
310
        return false;
    }
    // Hopefully, this will never fail, else data structure will be foobar.
    const ULONG oldSize = m_symbolParameters.size();
    ULONG newSize;
    hr = m_symbolGroup->GetNumberSymbols(&newSize);
    if (FAILED(hr)) {
311
        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("GetNumberSymbols", hr));
Friedemann Kleint's avatar
Friedemann Kleint committed
312
313
        return false;
    }
314

Friedemann Kleint's avatar
Friedemann Kleint committed
315
316
317
    // Retrieve the new parameter structs which will be inserted
    // after the parents, offsetting consecutive indexes.
    m_symbolParameters.resize(newSize);
318

Friedemann Kleint's avatar
Friedemann Kleint committed
319
320
    hr = m_symbolGroup->GetSymbolParameters(0, newSize, symbolParameters());
    if (FAILED(hr)) {
321
        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("GetSymbolParameters", hr));
Friedemann Kleint's avatar
Friedemann Kleint committed
322
        return false;
323
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
324
325
326
327
328
329
330
331
    // The new symbols are inserted after the parent symbol.
    // We need to correct the following values in the name->index map
    const unsigned long newSymbolCount = newSize - oldSize;
    const NameIndexMap::iterator nend = m_inameIndexMap.end();
    for (NameIndexMap::iterator it = m_inameIndexMap.begin(); it != nend; ++it)
        if (it.value() > index)
            it.value() += newSymbolCount;
    // insert the new symbols
332
    populateINameIndexMap(prefix, index, index + 1, newSymbolCount);
Friedemann Kleint's avatar
Friedemann Kleint committed
333
    if (debug > 1)
334
        qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString();
Friedemann Kleint's avatar
Friedemann Kleint committed
335
    return true;
336
337
338
339
340
}

void CdbSymbolGroupContext::clear()
{
    m_symbolParameters.clear();
Friedemann Kleint's avatar
Friedemann Kleint committed
341
342
343
    m_inameIndexMap.clear();
}

344
QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
345
{
346
347
    return m_inameIndexMap.key(index);
}
348

349
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
350
351
352
353
354
355
356
{
    ULONG64 rc = 0;
    if (FAILED(sg->GetSymbolOffset(index, &rc)))
        rc = 0;
    return QLatin1String("0x") + QString::number(rc, 16);
}

357
358
359
360
361
362
363
364
365
366
367
368
369
370
// check for "0x000", "0x000 class X"
static inline bool isNullPointer(const WatchData &wd)
{
    if (!isPointerType(wd.type))
        return false;
    static const QRegExp hexNullPattern(QLatin1String("0x0+"));
    Q_ASSERT(hexNullPattern.isValid());
    const int blankPos = wd.value.indexOf(QLatin1Char(' '));
    if (blankPos == -1)
        return hexNullPattern.exactMatch(wd.value);
    const QString addr = wd.value.mid(0, blankPos);
    return hexNullPattern.exactMatch(addr);
}

371
372
WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
{
373
    WatchData wd;
374
    wd.iname = symbolINameAt(index);
375
    wd.exp = wd.iname;
376
377
    const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter);
    wd.name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1);
378
    wd.addr = hexSymbolOffset(m_symbolGroup, index);
Friedemann Kleint's avatar
Friedemann Kleint committed
379
380
381
382
383
    wd.setType(getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index));
    wd.setValue(getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index).toUtf8());
    wd.setChildrenNeeded(); // compensate side effects of above setters
    // Figure out children. The SubElement is only a guess unless the symbol,
    // is expanded, so, we leave this as a guess for later updates.
384
    // If the symbol has children (expanded or not), we leave the 'Children' flag
385
386
387
388
    // in 'needed' state. Suppress 0-pointers right ("0x000 class X")
    // here as they only lead to children with memory access errors.
    const bool hasChildren = m_symbolParameters.at(index).SubElements && !isNullPointer(wd);
    wd.setHasChildren(hasChildren);
Friedemann Kleint's avatar
Friedemann Kleint committed
389
    if (debug > 1)
390
        qDebug() << Q_FUNC_INFO << index << '\n' << wd.toString();
Friedemann Kleint's avatar
Friedemann Kleint committed
391
392
393
    return wd;
}

394
395
396
397
398
399
400
401
402
403
404
bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &value,
                                        QString *newValue, QString *errorMessage)
{
    if (debugCDB)
        qDebug() << Q_FUNC_INFO << '\n' << iname << value;
    const NameIndexMap::const_iterator it = m_inameIndexMap.constFind(iname);
    if (it == m_inameIndexMap.constEnd()) {
        *errorMessage = msgSymbolNotFound(iname);
        return false;
    }
    const unsigned long  index = it.value();
405
    const HRESULT hr = m_symbolGroup->WriteSymbolWide(index, reinterpret_cast<PCWSTR>(value.utf16()));
406
407
408
409
410
411
412
413
414
415
    if (FAILED(hr)) {
        *errorMessage = QString::fromLatin1("Unable to assign '%1' to '%2': %3").
                        arg(value, iname, msgComFailed("WriteSymbolWide", hr));
        return false;
    }
    if (newValue)
        *newValue = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
    return true;
}

Friedemann Kleint's avatar
Friedemann Kleint committed
416
417
// format an array of integers as "0x323, 0x2322, ..."
template <class Integer>
418
static QString formatArrayHelper(const Integer *array, int size, int base = 10)
Friedemann Kleint's avatar
Friedemann Kleint committed
419
420
421
{
    QString rc;
    const QString hexPrefix = QLatin1String("0x");
hjk's avatar
hjk committed
422
    const QString separator = QLatin1String(", ");
423
    const bool hex = base == 16;
Friedemann Kleint's avatar
Friedemann Kleint committed
424
425
426
    for (int i = 0; i < size; i++) {
        if (i)
            rc += separator;
427
428
429
        if (hex)
            rc += hexPrefix;
        rc += QString::number(array[i], base);
Friedemann Kleint's avatar
Friedemann Kleint committed
430
431
432
433
434
435
    }
    return rc;
}

QString CdbSymbolGroupContext::hexFormatArray(const unsigned short *array, int size)
{
436
    return formatArrayHelper(array, size, 16);
Friedemann Kleint's avatar
Friedemann Kleint committed
437
438
}

439
440
441
442
443
444
445
446
447
448
449
450
// Helper to format an integer with
// a hex prefix in case base = 16
template <class Integer>
        inline QString formatInteger(Integer value, int base)
{
    QString rc;
    if (base == 16)
        rc = QLatin1String("0x");
    rc += QString::number(value, base);
    return rc;
}

451
QString CdbSymbolGroupContext::debugValueToString(const DEBUG_VALUE &dv, CIDebugControl *ctl,
452
453
                                                  QString *qType,
                                                  int integerBase)
Friedemann Kleint's avatar
Friedemann Kleint committed
454
455
456
{
    switch (dv.Type) {
    case DEBUG_VALUE_INT8:
457
458
459
        if (qType)
            *qType = QLatin1String("char");
        return formatInteger(dv.I8, integerBase);
Friedemann Kleint's avatar
Friedemann Kleint committed
460
    case DEBUG_VALUE_INT16:
461
462
463
        if (qType)
            *qType = QLatin1String("short");
        return formatInteger(static_cast<short>(dv.I16), integerBase);
Friedemann Kleint's avatar
Friedemann Kleint committed
464
    case DEBUG_VALUE_INT32:
465
466
467
        if (qType)
            *qType = QLatin1String("long");
        return formatInteger(static_cast<long>(dv.I32), integerBase);
Friedemann Kleint's avatar
Friedemann Kleint committed
468
    case DEBUG_VALUE_INT64:
469
470
471
        if (qType)
            *qType = QLatin1String("long long");
        return formatInteger(static_cast<long long>(dv.I64), integerBase);
Friedemann Kleint's avatar
Friedemann Kleint committed
472
    case DEBUG_VALUE_FLOAT32:
473
474
        if (qType)
            *qType = QLatin1String("float");
Friedemann Kleint's avatar
Friedemann Kleint committed
475
476
        return QString::number(dv.F32);
    case DEBUG_VALUE_FLOAT64:
477
478
        if (qType)
            *qType = QLatin1String("double");
Friedemann Kleint's avatar
Friedemann Kleint committed
479
480
481
482
483
484
485
        return QString::number(dv.F64);
    case DEBUG_VALUE_FLOAT80:
    case DEBUG_VALUE_FLOAT128: { // Convert to double
            DEBUG_VALUE doubleValue;
            double d = 0.0;
            if (SUCCEEDED(ctl->CoerceValue(const_cast<DEBUG_VALUE*>(&dv), DEBUG_VALUE_FLOAT64, &doubleValue)))
                d = dv.F64;
486
487
            if (qType)
                *qType = QLatin1String(dv.Type == DEBUG_VALUE_FLOAT80 ? "80bit-float" : "128bit-float");
Friedemann Kleint's avatar
Friedemann Kleint committed
488
489
490
            return QString::number(d);
        }
    case DEBUG_VALUE_VECTOR64: {
491
492
493
494
495
496
497
498
            if (qType)
                *qType = QLatin1String("64bit-vector");
            QString rc = QLatin1String("bytes: ");
            rc += formatArrayHelper(dv.VI8, 8, integerBase);
            rc += QLatin1String(" long: ");
            rc += formatArrayHelper(dv.VI32, 2, integerBase);
            return rc;
        }
Friedemann Kleint's avatar
Friedemann Kleint committed
499
    case DEBUG_VALUE_VECTOR128: {
500
501
502
503
504
505
506
507
            if (qType)
                *qType = QLatin1String("128bit-vector");
            QString rc = QLatin1String("bytes: ");
            rc += formatArrayHelper(dv.VI8, 16, integerBase);
            rc += QLatin1String(" long long: ");
            rc += formatArrayHelper(dv.VI64, 2, integerBase);
            return rc;
        }
Friedemann Kleint's avatar
Friedemann Kleint committed
508
    }
509
510
511
    if (qType)
        *qType = QString::fromLatin1("Unknown type #%1:").arg(dv.Type);
    return formatArrayHelper(dv.RawBytes, 24, integerBase);
Friedemann Kleint's avatar
Friedemann Kleint committed
512
513
}

514
bool CdbSymbolGroupContext::debugValueToInteger(const DEBUG_VALUE &dv, qint64 *value)
Friedemann Kleint's avatar
Friedemann Kleint committed
515
{
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    *value = 0;
    switch (dv.Type) {
    case DEBUG_VALUE_INT8:
        *value = dv.I8;
        return true;
    case DEBUG_VALUE_INT16:
        *value = static_cast<short>(dv.I16);
        return true;
    case DEBUG_VALUE_INT32:
        *value = static_cast<long>(dv.I32);
        return true;
    case DEBUG_VALUE_INT64:
        *value = static_cast<long long>(dv.I64);
        return true;
    default:
        break;
Friedemann Kleint's avatar
Friedemann Kleint committed
532
    }
533
    return false;
534
535
}

hjk's avatar
hjk committed
536
537
} // namespace Internal
} // namespace Debugger