forked from qt-creator/qt-creator
determine gdb target ABI by parsing 'gdb --configuration'
Currently, the gdb target ABI is determined by running `gdb -version`, which for recent gdb's does not reproduce the target ABI string -- yet this string is searched in the output. This obviously fails, and qtcreator uses a fallback behavior, that is not suitable when using gdb for debugging on targets (like avr microcontrollers). With this change, QtCreator calls `gdb --configuration` if that is supported by gdb and extracts `<string> from `--target=<string>` in the output. For older versions of gdb (which do not support the `--configuration` flag, but still have the target information in the output of `--version`, the output of `--version` is parsed. If both methods fail, no ABI is set for gdb. Change-Id: Ib406f6700b63e2cedb46bd4ec8cc0d215677ecdc Reviewed-by: Michael Kopp <kopp.michael@yahoo.de> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/macroexpander.h>
|
||||
@@ -61,6 +62,35 @@ const char DEBUGGER_INFORMATION_ABIS[] = "Abis";
|
||||
const char DEBUGGER_INFORMATION_LASTMODIFIED[] = "LastModified";
|
||||
const char DEBUGGER_INFORMATION_WORKINGDIRECTORY[] = "WorkingDirectory";
|
||||
|
||||
|
||||
//! Return the configuration of gdb as a list of --key=value
|
||||
//! \note That the list will also contain some output not in this format.
|
||||
static QString getConfigurationOfGdbCommand(const QString &command)
|
||||
{
|
||||
// run gdb with the --configuration opion
|
||||
Utils::SynchronousProcess gdbConfigurationCall;
|
||||
Utils::SynchronousProcessResponse output =
|
||||
gdbConfigurationCall.runBlocking(command, {QString("--configuration")});
|
||||
return output.allOutput();
|
||||
}
|
||||
|
||||
//! Extract the target ABI identifier from GDB output
|
||||
//! \return QString() (aka Null) if unable to find something
|
||||
static QString extractGdbTargetAbiStringFromGdbOutput(const QString &gdbOutput)
|
||||
{
|
||||
const auto outputLines = gdbOutput.split('\n');
|
||||
const auto whitespaceSeparatedTokens = outputLines.join(' ').split(' ', QString::SkipEmptyParts);
|
||||
|
||||
const QString targetKey{"--target="};
|
||||
const QString targetValue = Utils::findOrDefault(whitespaceSeparatedTokens,
|
||||
[&targetKey](const QString &token) { return token.startsWith(targetKey); });
|
||||
if (!targetValue.isEmpty())
|
||||
return targetValue.mid(targetKey.size());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -130,22 +160,6 @@ void DebuggerItem::reinitializeFromFile()
|
||||
const QString output = response.allOutput().trimmed();
|
||||
if (output.contains("gdb")) {
|
||||
m_engineType = GdbEngineType;
|
||||
const char needle[] = "This GDB was configured as \"";
|
||||
// E.g. "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0".
|
||||
// or "i686-linux-gnu"
|
||||
int pos1 = output.indexOf(needle);
|
||||
if (pos1 != -1) {
|
||||
pos1 += int(strlen(needle));
|
||||
int pos2 = output.indexOf('"', pos1 + 1);
|
||||
QString target = output.mid(pos1, pos2 - pos1);
|
||||
int pos3 = target.indexOf("--target=");
|
||||
if (pos3 >= 0)
|
||||
target = target.mid(pos3 + 9);
|
||||
m_abis.append(Abi::abiFromTargetTriplet(target));
|
||||
} else {
|
||||
// Fallback.
|
||||
m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong.
|
||||
}
|
||||
|
||||
// Version
|
||||
bool isMacGdb, isQnxGdb;
|
||||
@@ -155,6 +169,33 @@ void DebuggerItem::reinitializeFromFile()
|
||||
if (version)
|
||||
m_version = QString::fromLatin1("%1.%2.%3")
|
||||
.arg(version / 10000).arg((version / 100) % 100).arg(version % 100);
|
||||
|
||||
// ABI
|
||||
const bool unableToFindAVersion = (0 == version);
|
||||
const bool gdbSupportsConfigurationFlag = (version >= 70700);
|
||||
if (gdbSupportsConfigurationFlag || unableToFindAVersion) {
|
||||
const auto gdbConfiguration = getConfigurationOfGdbCommand(m_command.toString());
|
||||
const auto gdbTargetAbiString =
|
||||
extractGdbTargetAbiStringFromGdbOutput(gdbConfiguration);
|
||||
if (!gdbTargetAbiString.isEmpty()) {
|
||||
m_abis.append(Abi::abiFromTargetTriplet(gdbTargetAbiString));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ABI: legacy: the target was removed from the output of --version with
|
||||
// https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=c61b06a19a34baab66e3809c7b41b0c31009ed9f
|
||||
auto legacyGdbTargetAbiString = extractGdbTargetAbiStringFromGdbOutput(output);
|
||||
if (!legacyGdbTargetAbiString.isEmpty()) {
|
||||
// remove trailing "
|
||||
legacyGdbTargetAbiString =
|
||||
legacyGdbTargetAbiString.left(legacyGdbTargetAbiString.length() - 1);
|
||||
m_abis.append(Abi::abiFromTargetTriplet(legacyGdbTargetAbiString));
|
||||
return;
|
||||
}
|
||||
|
||||
qWarning() << "Unable to determine gdb target ABI";
|
||||
//! \note If unable to determine the GDB ABI, no ABI is appended to m_abis here.
|
||||
return;
|
||||
}
|
||||
if (output.startsWith("lldb") || output.startsWith("LLDB")) {
|
||||
|
@@ -436,6 +436,11 @@ QString DebuggerResponse::toString() const
|
||||
|
||||
// Tested in tests/auto/debugger/tst_gdb.cpp
|
||||
|
||||
//! Extract the GDB version number from the output of 'gdb --version'.
|
||||
//! \param[out] gdbVersion GDB version "hash" with major*10000 + minor*100 + patch
|
||||
//! e.g. version GDB 3.7.14 will set this to 30714
|
||||
//! \param[out] gdbBuildVersion distribution dependent value
|
||||
//! \note See the file tests/auto/debugger/tst_gdb.cpp for example conversions.
|
||||
void extractGdbVersion(const QString &msg,
|
||||
int *gdbVersion, int *gdbBuildVersion, bool *isMacGdb, bool *isQnxGdb)
|
||||
{
|
||||
|
@@ -958,6 +958,7 @@ Abi Abi::hostAbi()
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Extract available ABIs from a binary using heuristics.
|
||||
QList<Abi> Abi::abisOfBinary(const Utils::FileName &path)
|
||||
{
|
||||
QList<Abi> tmp;
|
||||
|
Reference in New Issue
Block a user