forked from qt-creator/qt-creator
debugger: make elfreader also report offset and size of sections
Change-Id: I8dd3d20ddc4652dc490d87558f46474f79300389 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -48,6 +48,21 @@
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
|
|
||||||
|
typedef quint16 qelfhalf_t;
|
||||||
|
typedef quint32 qelfword_t;
|
||||||
|
typedef quintptr qelfoff_t;
|
||||||
|
typedef quintptr qelfaddr_t;
|
||||||
|
|
||||||
|
class ElfSectionHeader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
qelfword_t name;
|
||||||
|
qelfword_t type;
|
||||||
|
qelfoff_t offset;
|
||||||
|
qelfoff_t size;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T read(const char *s, ElfReader::ElfEndian endian)
|
T read(const char *s, ElfReader::ElfEndian endian)
|
||||||
{
|
{
|
||||||
@@ -78,7 +93,7 @@ const char *ElfReader::parseSectionHeader(const char *data, ElfSectionHeader *sh
|
|||||||
}
|
}
|
||||||
|
|
||||||
ElfReader::Result ElfReader::parse(const char *dataStart, quint64 fdlen,
|
ElfReader::Result ElfReader::parse(const char *dataStart, quint64 fdlen,
|
||||||
QList<QByteArray> *sectionNames)
|
ElfSections *sections)
|
||||||
{
|
{
|
||||||
if (fdlen < 64) {
|
if (fdlen < 64) {
|
||||||
m_errorString = QLibrary::tr("'%1' is not an ELF object (%2)")
|
m_errorString = QLibrary::tr("'%1' is not an ELF object (%2)")
|
||||||
@@ -204,17 +219,22 @@ ElfReader::Result ElfReader::parse(const char *dataStart, quint64 fdlen,
|
|||||||
return Corrupt;
|
return Corrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sectionNames)
|
if (sections) {
|
||||||
sectionNames->append(shnam);
|
ElfSection section;
|
||||||
|
section.name = shnam;
|
||||||
|
section.index = strtab.name;
|
||||||
|
section.offset = strtab.offset;
|
||||||
|
section.size = strtab.size;
|
||||||
|
}
|
||||||
|
|
||||||
s += e_shentsize;
|
s += e_shentsize;
|
||||||
}
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QByteArray> ElfReader::sectionNames()
|
ElfSections ElfReader::sections()
|
||||||
{
|
{
|
||||||
QList<QByteArray> names;
|
ElfSections names;
|
||||||
|
|
||||||
QFile file(m_binary);
|
QFile file(m_binary);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
|||||||
@@ -52,33 +52,34 @@
|
|||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
typedef quint16 qelfhalf_t;
|
class ElfSectionHeader;
|
||||||
typedef quint32 qelfword_t;
|
|
||||||
typedef quintptr qelfoff_t;
|
class QTCREATOR_UTILS_EXPORT ElfSection
|
||||||
typedef quintptr qelfaddr_t;
|
{
|
||||||
|
public:
|
||||||
|
QByteArray name;
|
||||||
|
quint32 index;
|
||||||
|
quint32 type;
|
||||||
|
quint64 offset;
|
||||||
|
quint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QList<ElfSection> ElfSections;
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT ElfReader
|
class QTCREATOR_UTILS_EXPORT ElfReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ElfReader(const QString &binary);
|
explicit ElfReader(const QString &binary);
|
||||||
|
|
||||||
struct ElfSectionHeader
|
|
||||||
{
|
|
||||||
qelfword_t name;
|
|
||||||
qelfword_t type;
|
|
||||||
qelfoff_t offset;
|
|
||||||
qelfoff_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ElfEndian { ElfLittleEndian = 0, ElfBigEndian = 1 };
|
enum ElfEndian { ElfLittleEndian = 0, ElfBigEndian = 1 };
|
||||||
QList<QByteArray> sectionNames();
|
ElfSections sections();
|
||||||
QString errorString() const { return m_errorString; }
|
QString errorString() const { return m_errorString; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Result { Ok, NotElf, Corrupt };
|
enum Result { Ok, NotElf, Corrupt };
|
||||||
|
|
||||||
const char *parseSectionHeader(const char *s, ElfSectionHeader *sh);
|
const char *parseSectionHeader(const char *s, ElfSectionHeader *sh);
|
||||||
Result parse(const char *dataStart, quint64 fdlen, QList<QByteArray> *sectionNames);
|
Result parse(const char *dataStart, quint64 fdlen, ElfSections *sections);
|
||||||
|
|
||||||
QString m_binary;
|
QString m_binary;
|
||||||
QString m_errorString;
|
QString m_errorString;
|
||||||
|
|||||||
@@ -3519,16 +3519,25 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
|||||||
|
|
||||||
void GdbEngine::examineModule(Module *module)
|
void GdbEngine::examineModule(Module *module)
|
||||||
{
|
{
|
||||||
Utils::ElfReader reader(module->modulePath);
|
using namespace Utils;
|
||||||
QList<QByteArray> names = reader.sectionNames();
|
ElfReader reader(module->modulePath);
|
||||||
if (names.contains(".gdb_index"))
|
ElfSections sections = reader.sections();
|
||||||
module->symbolsType = Module::FastSymbols;
|
module->symbolsType = Module::NoSymbols;
|
||||||
else if (names.contains(".debug_inf"))
|
for (int i = 0, n = sections.size(); i != n; ++i) {
|
||||||
module->symbolsType = Module::PlainSymbols;
|
const QByteArray &name = sections.at(i).name;
|
||||||
else if (names.contains(".gnu_debuglink"))
|
if (name == ".gdb_index") {
|
||||||
module->symbolsType = Module::SeparateSymbols;
|
module->symbolsType = Module::FastSymbols;
|
||||||
else
|
break;
|
||||||
module->symbolsType = Module::NoSymbols;
|
}
|
||||||
|
if (name == ".debug_info") {
|
||||||
|
module->symbolsType = Module::PlainSymbols;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (name == ".gnu_debuglink") {
|
||||||
|
module->symbolsType = Module::SeparateSymbols;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::examineModules()
|
void GdbEngine::examineModules()
|
||||||
@@ -5371,9 +5380,10 @@ bool GdbEngine::attemptQuickStart() const
|
|||||||
|
|
||||||
void GdbEngine::checkForReleaseBuild()
|
void GdbEngine::checkForReleaseBuild()
|
||||||
{
|
{
|
||||||
|
using namespace Utils;
|
||||||
QString binary = startParameters().executable;
|
QString binary = startParameters().executable;
|
||||||
Utils::ElfReader reader(binary);
|
ElfReader reader(binary);
|
||||||
QList<QByteArray> names = reader.sectionNames();
|
ElfSections sections = reader.sections();
|
||||||
QString error = reader.errorString();
|
QString error = reader.errorString();
|
||||||
|
|
||||||
showMessage(_("EXAMINING ") + binary);
|
showMessage(_("EXAMINING ") + binary);
|
||||||
@@ -5394,11 +5404,11 @@ void GdbEngine::checkForReleaseBuild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSet<QByteArray> seen;
|
QSet<QByteArray> seen;
|
||||||
foreach (const QByteArray &name, names) {
|
foreach (const ElfSection §ion, sections) {
|
||||||
msg.append(name);
|
msg.append(section.name);
|
||||||
msg.append(' ');
|
msg.append(' ');
|
||||||
if (interesting.contains(name))
|
if (interesting.contains(section.name))
|
||||||
seen.insert(name);
|
seen.insert(section.name);
|
||||||
}
|
}
|
||||||
showMessage(_(msg));
|
showMessage(_(msg));
|
||||||
|
|
||||||
@@ -5406,13 +5416,16 @@ void GdbEngine::checkForReleaseBuild()
|
|||||||
showMessage(_("ERROR WHILE READING ELF SECTIONS: ") + error);
|
showMessage(_("ERROR WHILE READING ELF SECTIONS: ") + error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (names.isEmpty()) {
|
|
||||||
showMessage(_("NO SECTION HEADERS FOUND"));
|
if (sections.isEmpty()) {
|
||||||
|
showMessage(_("NO SECTION HEADERS FOUND. IS THIS AN EXECUTABLE?"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (names.contains(".debug_info"))
|
foreach (const ElfSection §ion, sections) {
|
||||||
return;
|
if (section.name == ".debug_info")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString warning;
|
QString warning;
|
||||||
warning = tr("This does not seem to be a \"Debug\" build.\n"
|
warning = tr("This does not seem to be a \"Debug\" build.\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user