CDB: Dump QStringRef.

Extend QString dumper to be able to dump a substring.

Change-Id: I1f64e441980a7c2c295f40317b2b187cfebcd7ea
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Friedemann Kleint
2013-01-18 14:19:20 +01:00
committed by hjk
parent 7fafeaa513
commit 23b7dc5b5c
2 changed files with 48 additions and 13 deletions

View File

@@ -71,6 +71,7 @@ enum KnownType
KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + KT_HasComplexDumper + 17, KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + KT_HasComplexDumper + 17,
KT_QBasicAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 18, KT_QBasicAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 18,
KT_QAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 19, KT_QAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 19,
KT_QStringRef = KT_Qt_Type + KT_HasSimpleDumper + 20,
KT_QObject = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 20, KT_QObject = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 20,
KT_QWindow = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 21, KT_QWindow = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 21,
KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 22, KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 22,

View File

@@ -30,6 +30,10 @@
// std::copy is perfectly fine, don't let MSVC complain about it being deprecated // std::copy is perfectly fine, don't let MSVC complain about it being deprecated
#pragma warning (disable: 4996) #pragma warning (disable: 4996)
#ifndef NOMINMAX
# define NOMINMAX
#endif
#include "symbolgroupvalue.h" #include "symbolgroupvalue.h"
#include "symbolgroup.h" #include "symbolgroup.h"
#include "stringutils.h" #include "stringutils.h"
@@ -38,6 +42,7 @@
#include <iomanip> #include <iomanip>
#include <algorithm> #include <algorithm>
#include <limits>
#include <ctype.h> #include <ctype.h>
typedef std::vector<int>::size_type VectorIndexType; typedef std::vector<int>::size_type VectorIndexType;
@@ -1263,6 +1268,8 @@ static KnownType knownClassTypeHelper(const std::string &type,
return KT_QTransform; return KT_QTransform;
if (!type.compare(qPos, 10, "QFixedSize")) if (!type.compare(qPos, 10, "QFixedSize"))
return KT_QFixedSize; return KT_QFixedSize;
if (!type.compare(qPos, 10, "QStringRef"))
return KT_QStringRef;
break; break;
case 11: case 11:
if (!type.compare(qPos, 11, "QStringList")) if (!type.compare(qPos, 11, "QStringList"))
@@ -1517,36 +1524,40 @@ QtStringAddressData readQtStringAddressData(const SymbolGroupValue &dV,
// Retrieve data from a QByteArrayData(char)/QStringData(wchar_t) // Retrieve data from a QByteArrayData(char)/QStringData(wchar_t)
// in desired type. For empty arrays, no data are allocated. // in desired type. For empty arrays, no data are allocated.
// All sizes are in CharType units. zeroTerminated means data are 0-terminated
// in the data type, but "size" does not contain it.
template <typename CharType> template <typename CharType>
bool readQt5StringData(const SymbolGroupValue &dV, int qtMajorVersion, bool readQt5StringData(const SymbolGroupValue &dV, int qtMajorVersion,
bool zeroTerminated, unsigned sizeLimit, bool zeroTerminated, unsigned position, unsigned sizeLimit,
unsigned *fullSize, unsigned *arraySize, unsigned *fullSize, unsigned *arraySize,
CharType **array) CharType **array)
{ {
*array = 0; *array = 0;
QtStringAddressData data = readQtStringAddressData(dV, qtMajorVersion); const QtStringAddressData data = readQtStringAddressData(dV, qtMajorVersion);
*arraySize = *fullSize = data.size; if (!data.address || position > data.size)
if (!data.address)
return false; return false;
const ULONG64 address = data.address + sizeof(CharType) * position;
*fullSize = data.size - position;
*arraySize = std::min(*fullSize, sizeLimit);
if (!*fullSize) if (!*fullSize)
return true; return true;
const bool truncated = *fullSize > sizeLimit;
*arraySize = truncated ? sizeLimit : *fullSize;
const unsigned memorySize = const unsigned memorySize =
sizeof(CharType) * (*arraySize + (zeroTerminated ? 1 : 0)); sizeof(CharType) * (*arraySize + (zeroTerminated ? 1 : 0));
unsigned char *memory = unsigned char *memory =
SymbolGroupValue::readMemory(dV.context().dataspaces, SymbolGroupValue::readMemory(dV.context().dataspaces,
data.address, memorySize); address, memorySize);
if (!memory) if (!memory)
return false; return false;
*array = reinterpret_cast<CharType *>(memory); *array = reinterpret_cast<CharType *>(memory);
if (truncated && zeroTerminated) if ((*arraySize < *fullSize) && zeroTerminated)
*(*array + *arraySize) = CharType(0); *(*array + *arraySize) = CharType(0);
return true; return true;
} }
static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str, static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str,
MemoryHandle **memoryHandle = 0) MemoryHandle **memoryHandle = 0,
unsigned position = 0,
unsigned length = std::numeric_limits<unsigned>::max())
{ {
const QtInfo &qtInfo = QtInfo::get(v.context()); const QtInfo &qtInfo = QtInfo::get(v.context());
const SymbolGroupValue dV = v["d"]; const SymbolGroupValue dV = v["d"];
@@ -1557,7 +1568,11 @@ static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str,
if (const SymbolGroupValue sizeValue = dV["size"]) { if (const SymbolGroupValue sizeValue = dV["size"]) {
const int size = sizeValue.intValue(); const int size = sizeValue.intValue();
if (size >= 0) { if (size >= 0) {
const std::wstring stringData = dV["data"].wcharPointerData(size); std::wstring stringData = dV["data"].wcharPointerData(size);
if (position && position < stringData.size())
stringData.erase(0, position);
if (length < stringData.size())
stringData.erase(length, stringData.size() - length);
str << L'"' << stringData << L'"'; str << L'"' << stringData << L'"';
if (memoryHandle) if (memoryHandle)
*memoryHandle = MemoryHandle::fromStdWString(stringData); *memoryHandle = MemoryHandle::fromStdWString(stringData);
@@ -1574,11 +1589,13 @@ static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str,
const SymbolGroupValue typeArrayV = dV[unsigned(0)]; const SymbolGroupValue typeArrayV = dV[unsigned(0)];
if (!typeArrayV) if (!typeArrayV)
return false; return false;
if (!readQt5StringData(typeArrayV, qtInfo.version, true, 10240, &fullSize, &size, &memory)) if (!readQt5StringData(typeArrayV, qtInfo.version, true, position,
std::min(length, unsigned(10240)),
&fullSize, &size, &memory))
return false; return false;
if (size) { if (size) {
str << L'"' << memory; str << L'"' << memory;
if (fullSize > size) if (std::min(fullSize, length) > size)
str << L"..."; str << L"...";
str << L'"'; str << L'"';
} else { } else {
@@ -1591,6 +1608,20 @@ static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str,
return true; return true;
} }
static inline bool dumpQStringRef(const SymbolGroupValue &v, std::wostream &str,
MemoryHandle **memoryHandle = 0)
{
const int position = v["m_position"].intValue();
const int size = v["m_size"].intValue();
if (position < 0 || size < 0)
return false;
const SymbolGroupValue string = v["m_string"];
if (!string || !dumpQString(string, str, memoryHandle, position, size))
return false;
str << L" (" << position << ',' << size << L')';
return true;
}
/* Pad a memory offset to align with pointer size */ /* Pad a memory offset to align with pointer size */
static inline unsigned padOffset(unsigned offset) static inline unsigned padOffset(unsigned offset)
{ {
@@ -1670,7 +1701,7 @@ static inline bool dumpQByteArray(const SymbolGroupValue &v, std::wostream &str,
const SymbolGroupValue typeArrayV = dV[unsigned(0)]; const SymbolGroupValue typeArrayV = dV[unsigned(0)];
if (!typeArrayV) if (!typeArrayV)
return false; return false;
if (!readQt5StringData(typeArrayV, qtInfo.version, false, 10240, &fullSize, &size, &memory)) if (!readQt5StringData(typeArrayV, qtInfo.version, false, 0, 10240, &fullSize, &size, &memory))
return false; return false;
if (size) { if (size) {
// Emulate CDB's behavior of replacing unprintable characters // Emulate CDB's behavior of replacing unprintable characters
@@ -2593,6 +2624,9 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
case KT_QString: case KT_QString:
rc = dumpQString(v, str, memoryHandleIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed; rc = dumpQString(v, str, memoryHandleIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
break; break;
case KT_QStringRef:
rc = dumpQStringRef(v, str, memoryHandleIn) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
break;
case KT_QColor: case KT_QColor:
rc = dumpQColor(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed; rc = dumpQColor(v, str) ? SymbolGroupNode::SimpleDumperOk : SymbolGroupNode::SimpleDumperFailed;
break; break;