Cdbext: Optimize Qt detection.

Now supporting fast look up of linbinfix builds and
adding support for static namespace builds.

Change-Id: Iea234902e915b9a9d08ccf804ea4a37810aaa0d8
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
David Schulz
2015-03-06 09:13:36 +01:00
parent 22b0a061b0
commit bc124ff97f
2 changed files with 98 additions and 60 deletions

View File

@@ -652,45 +652,47 @@ const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx)
typedef std::list<std::string> StringList;
typedef StringList::const_iterator StringListConstIt;
// Lookup qstrdup() to hopefully get module (potential libinfix) and namespace
// Typically, this resolves to 'QtGuid4!qstrdup' and 'QtCored4!qstrdup'...
const char* qstrdupSymbol = "qstrdup";
StringList modulePatterns;
modulePatterns.push_back("Qt5Cored!");
modulePatterns.push_back("QtCored4!");
modulePatterns.push_back("*");
std::string qualifiedSymbol;
std::string::size_type exclPos;
std::string::size_type libPos;
for (StringListConstIt modulePattern = modulePatterns.begin(), total = modulePatterns.end();
modulePattern != total; ++modulePattern) {
const std::string pattern = *modulePattern + qstrdupSymbol;
const StringList &allMatches = SymbolGroupValue::resolveSymbolName(pattern.c_str(), ctx);
const bool wildcardPattern = *modulePattern == "*";
const StringListConstIt match = wildcardPattern
? std::find_if(allMatches.begin(), allMatches.end(), SubStringPredicate("Core"))
: std::find_if(allMatches.begin(), allMatches.end(), SubStringPredicate(modulePattern->c_str()));
std::string moduleName;
std::string::size_type exclPos = std::string::npos;
std::string::size_type libPos = std::string::npos;
if (match != allMatches.end()) {
qualifiedSymbol = *match;
} else if (wildcardPattern && !allMatches.empty()) {
// Use the first qstrdup symbol if there is no Core in all available qstrdup symbols
// This is useful when qt is statically linked.
qualifiedSymbol = *allMatches.begin();
} else {
// If we haven't found a match and this isn't the wildcard pattern we continue
// we could still find a dynamic qt library with a libinfix
continue;
}
exclPos = qualifiedSymbol.find('!'); // Resolved: 'QtCored4!qstrdup'
libPos = qualifiedSymbol.find("Core");
if (exclPos != std::string::npos && libPos != std::string::npos)
const StringList &modules = SymbolGroupValue::getAllModuleNames(ctx);
for (StringListConstIt module = modules.begin(), total = modules.end();
module != total; ++module) {
moduleName = *module;
if (moduleName.find("Qt") != std::string::npos) {
libPos = moduleName.find("Core");
if (libPos != std::string::npos)
break;
}
}
if (libPos == std::string::npos)
moduleName.clear();
else
moduleName += '!';
const char* qstrdupSymbol = "*qstrdup";
std::string qualifiedSymbol;
do {
// Lookup qstrdup() to get the core module
const std::string pattern = moduleName + qstrdupSymbol;
const StringList &allMatches = SymbolGroupValue::resolveSymbolName(pattern.c_str(), ctx);
if (!allMatches.empty()) {
qualifiedSymbol = allMatches.front();
} else {
if (!moduleName.empty()) {
// If there is no qstrdup symbol in the module fall back to a global lookup.
moduleName.clear();
continue;
}
}
exclPos = qualifiedSymbol.find('!');
libPos = qualifiedSymbol.find("Core");
if (exclPos != std::string::npos) {
if (libPos != std::string::npos) {
if (!moduleName.empty()) {
// found the core module
// determine the qt version from the module name
if (isdigit(qualifiedSymbol.at(2)))
@@ -705,7 +707,7 @@ const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx)
rc.libInfix = qualifiedSymbol.substr(0, exclPos);
// The Qt version cannot be determined by the module name. Looking up
// qInstallMessageHandler which is in Qt since 5.0 to determine the version.
const std::string pattern = rc.libInfix + "!qInstallMessageHandler";
const std::string pattern = rc.libInfix + "!*qInstallMessageHandler";
const StringList &allMatches = SymbolGroupValue::resolveSymbolName(pattern.c_str(), ctx);
const StringListConstIt match = std::find_if(allMatches.begin(), allMatches.end(),
SubStringPredicate(rc.libInfix.c_str()));
@@ -721,6 +723,7 @@ const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx)
rc.libInfix = "d4";
rc.version = 4;
}
} while (false);
rc.qObjectType = rc.prependQtCoreModule("QObject");
rc.qObjectPrivateType = rc.prependQtCoreModule("QObjectPrivate");
@@ -842,6 +845,38 @@ SymbolGroupValue::SymbolList
return rc;
}
std::list<std::string> SymbolGroupValue::getAllModuleNames(const SymbolGroupValueContext &c,
std::string *errorMessage)
{
enum { bufSize = 2048 };
std::list<std::string> rc;
ULONG moduleCount = 0;
ULONG unloaded = 0;
HRESULT hr = c.symbols->GetNumberModules(&moduleCount, &unloaded);
if (FAILED(hr)) {
if (errorMessage)
*errorMessage = msgDebugEngineComFailed("GetNumberModules", hr);
return rc;
}
moduleCount += unloaded;
// lookup module names
char moduleBuffer[bufSize];
for (ULONG index = 0; index < moduleCount; ++index) {
hr = c.symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, index,
NULL, moduleBuffer, bufSize - 1, NULL);
if (FAILED(hr)) {
if (errorMessage)
*errorMessage = msgDebugEngineComFailed("GetNumberModules", hr);
return rc;
}
rc.push_back(moduleBuffer);
}
return rc;
}
// Resolve a type, that is, obtain its module name ('QString'->'QtCored4!QString')
std::string SymbolGroupValue::resolveType(const std::string &typeIn,
const SymbolGroupValueContext &ctx,

View File

@@ -139,6 +139,9 @@ public:
const SymbolGroupValueContext &c,
std::string *errorMessage = 0);
static std::list<std::string> getAllModuleNames(const SymbolGroupValueContext &c,
std::string *errorMessage = 0);
static unsigned char *readMemory(CIDebugDataSpaces *ds, ULONG64 address, ULONG length,
std::string *errorMessage = 0);
static ULONG64 readPointerValue(CIDebugDataSpaces *ds, ULONG64 address,