debugger: make elfreader also report offset and size of sections

Change-Id: I8dd3d20ddc4652dc490d87558f46474f79300389
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2012-06-04 17:23:16 +02:00
committed by hjk
parent a452db5055
commit 1b1dbf1b8b
3 changed files with 73 additions and 39 deletions

View File

@@ -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)) {

View File

@@ -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;

View File

@@ -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;
else if (names.contains(".debug_inf"))
module->symbolsType = Module::PlainSymbols;
else if (names.contains(".gnu_debuglink"))
module->symbolsType = Module::SeparateSymbols;
else
module->symbolsType = Module::NoSymbols; module->symbolsType = Module::NoSymbols;
for (int i = 0, n = sections.size(); i != n; ++i) {
const QByteArray &name = sections.at(i).name;
if (name == ".gdb_index") {
module->symbolsType = Module::FastSymbols;
break;
}
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 &section, 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 &section, sections) {
if (section.name == ".debug_info")
return; 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"