Merge remote-tracking branch 'origin/4.0'

Conflicts:
	src/plugins/debugger/watchdata.cpp
	src/plugins/debugger/watchdata.h
	src/shared/qbs

Change-Id: I19b338b316d9c4c046074eb85b3fec79e86e6c32
This commit is contained in:
Eike Ziller
2016-06-09 12:07:01 +02:00
10 changed files with 147 additions and 86 deletions

View File

@@ -652,7 +652,6 @@ void CdbEngine::setupInferior()
symbolPaths += symbolPath; symbolPaths += symbolPath;
runCommand({".sympath \"" + symbolPaths.join(';') + '"', NoFlags}); runCommand({".sympath \"" + symbolPaths.join(';') + '"', NoFlags});
runCommand({"!sym noisy", NoFlags}); // Show symbol load information.
runCommand({"sxn 0x4000001f", NoFlags}); // Do not break on WowX86 exceptions. runCommand({"sxn 0x4000001f", NoFlags}); // Do not break on WowX86 exceptions.
runCommand({"sxn ibp", NoFlags}); // Do not break on initial breakpoints. runCommand({"sxn ibp", NoFlags}); // Do not break on initial breakpoints.
runCommand({".asm source_line", NoFlags}); // Source line in assembly runCommand({".asm source_line", NoFlags}); // Source line in assembly

View File

@@ -324,61 +324,75 @@ QString decodeItemHelper(const double &t)
return QString::number(t, 'g', 16); return QString::number(t, 'g', 16);
} }
template <class T> class ArrayDataDecoder
void decodeArrayHelper(WatchItem *item, const QString &rawData, int size, const QString &childType)
{ {
public:
template <class T>
void decodeArrayHelper(int childSize)
{
const QByteArray ba = QByteArray::fromHex(rawData.toUtf8()); const QByteArray ba = QByteArray::fromHex(rawData.toUtf8());
const T *p = (const T *) ba.data(); const T *p = (const T *) ba.data();
for (int i = 0, n = ba.size() / sizeof(T); i < n; ++i) { for (int i = 0, n = ba.size() / sizeof(T); i < n; ++i) {
WatchItem *child = new WatchItem; WatchItem *child = new WatchItem;
child->arrayIndex = i; child->arrayIndex = i;
child->value = decodeItemHelper(p[i]); child->value = decodeItemHelper(p[i]);
child->size = size; child->size = childSize;
child->type = childType; child->type = childType;
child->address = addrbase + i * addrstep;
child->valueEditable = true;
child->setAllUnneeded(); child->setAllUnneeded();
item->appendChild(child); item->appendChild(child);
} }
} }
static void decodeArrayData(WatchItem *item, const QString &rawData, void decode()
const DebuggerEncoding &encoding, const QString &childType) {
{ if (addrstep == 0)
addrstep = encoding.size;
switch (encoding.type) { switch (encoding.type) {
case DebuggerEncoding::HexEncodedSignedInteger: case DebuggerEncoding::HexEncodedSignedInteger:
switch (encoding.size) { switch (encoding.size) {
case 1: case 1:
return decodeArrayHelper<signed char>(item, rawData, encoding.size, childType); return decodeArrayHelper<signed char>(encoding.size);
case 2: case 2:
return decodeArrayHelper<short>(item, rawData, encoding.size, childType); return decodeArrayHelper<short>(encoding.size);
case 4: case 4:
return decodeArrayHelper<int>(item, rawData, encoding.size, childType); return decodeArrayHelper<int>(encoding.size);
case 8: case 8:
return decodeArrayHelper<qint64>(item, rawData, encoding.size, childType); return decodeArrayHelper<qint64>(encoding.size);
} }
case DebuggerEncoding::HexEncodedUnsignedInteger: case DebuggerEncoding::HexEncodedUnsignedInteger:
switch (encoding.size) { switch (encoding.size) {
case 1: case 1:
return decodeArrayHelper<uchar>(item, rawData, encoding.size, childType); return decodeArrayHelper<uchar>(encoding.size);
case 2: case 2:
return decodeArrayHelper<ushort>(item, rawData, encoding.size, childType); return decodeArrayHelper<ushort>(encoding.size);
case 4: case 4:
return decodeArrayHelper<uint>(item, rawData, encoding.size, childType); return decodeArrayHelper<uint>(encoding.size);
case 8: case 8:
return decodeArrayHelper<quint64>(item, rawData, encoding.size, childType); return decodeArrayHelper<quint64>(encoding.size);
} }
break; break;
case DebuggerEncoding::HexEncodedFloat: case DebuggerEncoding::HexEncodedFloat:
switch (encoding.size) { switch (encoding.size) {
case 4: case 4:
return decodeArrayHelper<float>(item, rawData, encoding.size, childType); return decodeArrayHelper<float>(encoding.size);
case 8: case 8:
return decodeArrayHelper<double>(item, rawData, encoding.size, childType); return decodeArrayHelper<double>(encoding.size);
} }
default: default:
break; break;
} }
qDebug() << "ENCODING ERROR: " << encoding.toString(); qDebug() << "ENCODING ERROR: " << encoding.toString();
} }
WatchItem *item;
QString rawData;
QString childType;
DebuggerEncoding encoding;
quint64 addrbase;
quint64 addrstep;
};
static bool sortByName(const Utils::TreeItem *a, const Utils::TreeItem *b) static bool sortByName(const Utils::TreeItem *a, const Utils::TreeItem *b)
{ {
@@ -473,9 +487,14 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
mi = input["arraydata"]; mi = input["arraydata"];
if (mi.isValid()) { if (mi.isValid()) {
DebuggerEncoding encoding(input["arrayencoding"].data()); ArrayDataDecoder decoder;
QString childType = input["childtype"].data(); decoder.item = this;
decodeArrayData(this, mi.data(), encoding, childType); decoder.rawData = mi.data();
decoder.childType = input["childtype"].data();
decoder.addrbase = input["addrbase"].toAddress();
decoder.addrstep = input["addrstep"].toAddress();
decoder.encoding = DebuggerEncoding(input["arrayencoding"].data());
decoder.decode();
} else { } else {
const GdbMi children = input["children"]; const GdbMi children = input["children"];
if (children.isValid()) { if (children.isValid()) {
@@ -510,7 +529,8 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
child->iname = this->iname + '.' + nn; child->iname = this->iname + '.' + nn;
if (addressStep) { if (addressStep) {
child->address = addressBase + i * addressStep; child->address = addressBase + i * addressStep;
child->exp = "*(" + gdbQuoteTypes(child->type) + "*)" + child->hexAddress(); child->exp = "*(" + gdbQuoteTypes(child->type) + "*)0x"
+ QString::number(child->address, 16);
} }
QString key = subinput["key"].data(); QString key = subinput["key"].data();
if (!key.isEmpty()) if (!key.isEmpty())
@@ -581,8 +601,8 @@ QString WatchItem::toToolTip() const
} }
formatToolTipRow(str, tr("Value"), val); formatToolTipRow(str, tr("Value"), val);
} }
if (realAddress()) if (address)
formatToolTipRow(str, tr("Object Address"), formatToolTipAddress(realAddress())); formatToolTipRow(str, tr("Object Address"), formatToolTipAddress(address));
if (origaddr) if (origaddr)
formatToolTipRow(str, tr("Pointer Address"), formatToolTipAddress(origaddr)); formatToolTipRow(str, tr("Pointer Address"), formatToolTipAddress(origaddr));
if (arrayIndex >= 0) if (arrayIndex >= 0)
@@ -618,15 +638,6 @@ bool WatchItem::isInspect() const
return iname.startsWith("inspect."); return iname.startsWith("inspect.");
} }
quint64 WatchItem::realAddress() const
{
if (arrayIndex >= 0) {
if (const WatchItem *p = parentItem())
return p->address + arrayIndex * size;
}
return address;
}
QString WatchItem::internalName() const QString WatchItem::internalName() const
{ {
if (arrayIndex >= 0) { if (arrayIndex >= 0) {
@@ -647,7 +658,7 @@ QString WatchItem::expression() const
{ {
if (!exp.isEmpty()) if (!exp.isEmpty())
return exp; return exp;
if (quint64 addr = realAddress()) { if (quint64 addr = address) {
if (!type.isEmpty()) if (!type.isEmpty())
return QString("*(%1*)0x%2").arg(type).arg(addr, 0, 16); return QString("*(%1*)0x%2").arg(type).arg(addr, 0, 16);
} }

View File

@@ -52,7 +52,6 @@ public:
QString expression() const; QString expression() const;
QString realName() const; QString realName() const;
quint64 realAddress() const;
QString internalName() const; QString internalName() const;
QString toToolTip() const; QString toToolTip() const;

View File

@@ -793,13 +793,13 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
<< MsvcToolChain::arm << MsvcToolChain::x86_arm << MsvcToolChain::amd64_arm << MsvcToolChain::arm << MsvcToolChain::x86_arm << MsvcToolChain::amd64_arm
<< MsvcToolChain::ia64 << MsvcToolChain::x86_ia64; << MsvcToolChain::ia64 << MsvcToolChain::x86_ia64;
foreach (const MsvcToolChain::Platform &platform, platforms) { foreach (const MsvcToolChain::Platform &platform, platforms) {
QString vcvarsBat = vcVarsBatFor(path, platform); const bool toolchainInstalled = QFileInfo(vcVarsBatFor(path, platform)).isFile();
if (hostSupportsPlatform(platform) && QFileInfo(vcvarsBat).isFile()) { if (hostSupportsPlatform(platform) && toolchainInstalled) {
results.append(findOrCreateToolChain( results.append(findOrCreateToolChain(
alreadyKnown, alreadyKnown,
generateDisplayName(vsName, MsvcToolChain::VS, platform), generateDisplayName(vsName, MsvcToolChain::VS, platform),
findAbiOfMsvc(MsvcToolChain::VS, platform, vsName), findAbiOfMsvc(MsvcToolChain::VS, platform, vsName),
vcvarsBat, platformName(platform), vcvarsAllbat, platformName(platform),
ToolChain::AutoDetection)); ToolChain::AutoDetection));
} }
} }

View File

@@ -60,7 +60,7 @@ void QbsLogSink::sendMessages()
} }
foreach (const QString &msg, toSend) foreach (const QString &msg, toSend)
Core::MessageManager::write(msg); Core::MessageManager::write(msg, Core::MessageManager::Silent);
} }
void QbsLogSink::doPrintWarning(const qbs::ErrorInfo &warning) void QbsLogSink::doPrintWarning(const qbs::ErrorInfo &warning)

View File

@@ -295,8 +295,8 @@ void BindingModel::updateExpression(int row)
{ {
BindingProperty bindingProperty = bindingPropertyForRow(row); BindingProperty bindingProperty = bindingPropertyForRow(row);
const QString sourceNode = data(index(row, SourceModelNodeRow)).toString(); const QString sourceNode = data(index(row, SourceModelNodeRow)).toString().trimmed();
const QString sourceProperty = data(index(row, SourcePropertyNameRow)).toString(); const QString sourceProperty = data(index(row, SourcePropertyNameRow)).toString().trimmed();
QString expression; QString expression;
if (sourceProperty.isEmpty()) { if (sourceProperty.isEmpty()) {

View File

@@ -98,6 +98,7 @@ bool openRegistryKey(HKEY category, // HKEY_LOCAL_MACHINE, etc.
const WCHAR *key, const WCHAR *key,
bool readWrite, bool readWrite,
HKEY *keyHandle, HKEY *keyHandle,
AccessMode mode,
QString *errorMessage) QString *errorMessage)
{ {
Q_UNUSED(debuggerRegistryKeyC); // avoid warning from MinGW Q_UNUSED(debuggerRegistryKeyC); // avoid warning from MinGW
@@ -105,6 +106,16 @@ bool openRegistryKey(HKEY category, // HKEY_LOCAL_MACHINE, etc.
REGSAM accessRights = KEY_READ; REGSAM accessRights = KEY_READ;
if (readWrite) if (readWrite)
accessRights |= KEY_SET_VALUE; accessRights |= KEY_SET_VALUE;
switch (mode) {
case RegistryAccess::DefaultAccessMode:
break;
case RegistryAccess::Registry32Mode:
accessRights |= KEY_WOW64_32KEY;
break;
case RegistryAccess::Registry64Mode:
accessRights |= KEY_WOW64_64KEY;
break;
}
const LONG rc = RegOpenKeyEx(category, key, 0, accessRights, keyHandle); const LONG rc = RegOpenKeyEx(category, key, 0, accessRights, keyHandle);
if (rc != ERROR_SUCCESS) { if (rc != ERROR_SUCCESS) {
*errorMessage = msgFunctionFailed("RegOpenKeyEx", rc); *errorMessage = msgFunctionFailed("RegOpenKeyEx", rc);

View File

@@ -36,6 +36,12 @@
namespace RegistryAccess { namespace RegistryAccess {
enum AccessMode {
DefaultAccessMode,
Registry32Mode = 0x2, // Corresponds to QSettings::Registry32Format (5.7)
Registry64Mode = 0x4 // Corresponds to QSettings::Registry64Format (5.7)
};
static const char *debuggerApplicationFileC = "qtcdebugger"; static const char *debuggerApplicationFileC = "qtcdebugger";
static const WCHAR *debuggerRegistryKeyC = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug"; static const WCHAR *debuggerRegistryKeyC = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
static const WCHAR *debuggerRegistryValueNameC = L"Debugger"; static const WCHAR *debuggerRegistryValueNameC = L"Debugger";
@@ -67,8 +73,12 @@ bool openRegistryKey(HKEY category, // HKEY_LOCAL_MACHINE, etc.
const WCHAR *key, const WCHAR *key,
bool readWrite, bool readWrite,
HKEY *keyHandle, HKEY *keyHandle,
AccessMode mode,
QString *errorMessage); QString *errorMessage);
inline bool openRegistryKey(HKEY category, const WCHAR *key, bool readWrite, HKEY *keyHandle, QString *errorMessage)
{ return openRegistryKey(category, key, readWrite, keyHandle, DefaultAccessMode, errorMessage); }
QString debuggerCall(const QString &additionalOption = QString()); QString debuggerCall(const QString &additionalOption = QString());
bool isRegistered(HKEY handle, const QString &call, QString *errorMessage, QString *oldDebugger = 0); bool isRegistered(HKEY handle, const QString &call, QString *errorMessage, QString *oldDebugger = 0);

View File

@@ -70,6 +70,9 @@ static const char creatorBinaryC[] = "qtcreator.exe";
enum Mode { HelpMode, RegisterMode, UnregisterMode, PromptMode, ForceCreatorMode, ForceDefaultMode }; enum Mode { HelpMode, RegisterMode, UnregisterMode, PromptMode, ForceCreatorMode, ForceDefaultMode };
Mode optMode = PromptMode; Mode optMode = PromptMode;
// WOW: Indicates registry key access mode:
// - Accessing 32bit using a 64bit built Qt Creator or,
// - Accessing 64bit using a 32bit built Qt Creator on 64bit Windows
bool optIsWow = false; bool optIsWow = false;
bool noguiMode = false; bool noguiMode = false;
unsigned long argProcessId = 0; unsigned long argProcessId = 0;
@@ -172,6 +175,14 @@ static void usage(const QString &binary, const QString &message = QString())
msgBox.exec(); msgBox.exec();
} }
static bool is64BitWindowsSystem() // Courtesy utils library
{
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
|| systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64;
}
// ------- Registry helpers // ------- Registry helpers
static inline bool registryWriteBinaryKey(HKEY handle, static inline bool registryWriteBinaryKey(HKEY handle,
@@ -303,8 +314,15 @@ bool readDefaultDebugger(QString *defaultDebugger,
{ {
bool success = false; bool success = false;
HKEY handle; HKEY handle;
if (openRegistryKey(HKEY_LOCAL_MACHINE, optIsWow ? debuggerWow32RegistryKeyC : debuggerRegistryKeyC, const RegistryAccess::AccessMode accessMode = optIsWow
false, &handle, errorMessage)) { #ifdef Q_OS_WIN64
? RegistryAccess::Registry32Mode
#else
? RegistryAccess::Registry64Mode
#endif
: RegistryAccess::DefaultAccessMode;
if (openRegistryKey(HKEY_LOCAL_MACHINE, debuggerRegistryKeyC, false, &handle, accessMode, errorMessage)) {
success = registryReadStringKey(handle, debuggerRegistryDefaultValueNameC, success = registryReadStringKey(handle, debuggerRegistryDefaultValueNameC,
defaultDebugger, errorMessage); defaultDebugger, errorMessage);
RegCloseKey(handle); RegCloseKey(handle);
@@ -372,12 +390,13 @@ bool chooseDebugger(QString *errorMessage)
static bool registerDebuggerKey(const WCHAR *key, static bool registerDebuggerKey(const WCHAR *key,
const QString &call, const QString &call,
RegistryAccess::AccessMode access,
QString *errorMessage) QString *errorMessage)
{ {
HKEY handle = 0; HKEY handle = 0;
bool success = false; bool success = false;
do { do {
if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage)) if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, access, errorMessage))
break; break;
// Save old key, which might be missing // Save old key, which might be missing
QString oldDebugger; QString oldDebugger;
@@ -401,11 +420,16 @@ static bool registerDebuggerKey(const WCHAR *key,
bool install(QString *errorMessage) bool install(QString *errorMessage)
{ {
if (!registerDebuggerKey(debuggerRegistryKeyC, debuggerCall(), errorMessage)) if (!registerDebuggerKey(debuggerRegistryKeyC, debuggerCall(), RegistryAccess::DefaultAccessMode, errorMessage))
return false; return false;
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
if (!registerDebuggerKey(debuggerWow32RegistryKeyC, debuggerCall(QLatin1String("-wow")), errorMessage)) if (!registerDebuggerKey(debuggerRegistryKeyC, debuggerCall(QLatin1String("-wow")), RegistryAccess::Registry32Mode, errorMessage))
return false; return false;
#else
if (is64BitWindowsSystem()) {
if (!registerDebuggerKey(debuggerRegistryKeyC, debuggerCall(QLatin1String("-wow")), RegistryAccess::Registry64Mode, errorMessage))
return false;
}
#endif #endif
return true; return true;
} }
@@ -413,12 +437,13 @@ bool install(QString *errorMessage)
// Unregister helper: Restore the original debugger key // Unregister helper: Restore the original debugger key
static bool unregisterDebuggerKey(const WCHAR *key, static bool unregisterDebuggerKey(const WCHAR *key,
const QString &call, const QString &call,
RegistryAccess::AccessMode access,
QString *errorMessage) QString *errorMessage)
{ {
HKEY handle = 0; HKEY handle = 0;
bool success = false; bool success = false;
do { do {
if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, errorMessage)) if (!openRegistryKey(HKEY_LOCAL_MACHINE, key, true, &handle, access, errorMessage))
break; break;
QString debugger; QString debugger;
if (!isRegistered(handle, call, errorMessage, &debugger) && !debugger.isEmpty()) { if (!isRegistered(handle, call, errorMessage, &debugger) && !debugger.isEmpty()) {
@@ -448,12 +473,18 @@ static bool unregisterDebuggerKey(const WCHAR *key,
bool uninstall(QString *errorMessage) bool uninstall(QString *errorMessage)
{ {
if (!unregisterDebuggerKey(debuggerRegistryKeyC, debuggerCall(), errorMessage)) if (!unregisterDebuggerKey(debuggerRegistryKeyC, debuggerCall(), RegistryAccess::DefaultAccessMode, errorMessage))
return false; return false;
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
if (!unregisterDebuggerKey(debuggerWow32RegistryKeyC, debuggerCall(QLatin1String("-wow")), errorMessage)) if (!unregisterDebuggerKey(debuggerRegistryKeyC, debuggerCall(QLatin1String("-wow")), RegistryAccess::Registry32Mode, errorMessage))
return false; return false;
#else
if (is64BitWindowsSystem()) {
if (!unregisterDebuggerKey(debuggerRegistryKeyC, debuggerCall(QLatin1String("-wow")), RegistryAccess::Registry64Mode, errorMessage))
return false;
}
#endif #endif
return true; return true;
} }