summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosef Weidendorfer <[email protected]>2014-11-06 01:33:14 +0100
committerJosef Weidendorfer <[email protected]>2015-06-12 18:50:40 +0200
commit9c40aeb55a64e7e3958386dae4033afe36dec73b (patch)
tree14d670977e1cc118b67cec0850193647ea21a77f
parenta5b6f4f928c1536ec155c77da0a31c262563b92f (diff)
Better support for ARM
When calling objdump on an file to get machine code, (1) use $OBJDUMP as command instead of "objdump" if set, (2) prepend $SYSROOT to an absolute file name if set. Further, if "arch: arm" is found in header of a profile dump, set bit0 of all addresses in InstrView to 0. Bit0 is used in Arm32 to specify encoding, but instructions always start at even addresses. If bit0 is 1, this is Thumb encoding, but objdump detects this automatically and wants real addresses of instructions.
-rw-r--r--libcore/addr.h3
-rw-r--r--libcore/cachegrindloader.cpp13
-rw-r--r--libcore/tracedata.cpp2
-rw-r--r--libcore/tracedata.h6
-rw-r--r--libviews/instrview.cpp64
5 files changed, 82 insertions, 6 deletions
diff --git a/libcore/addr.h b/libcore/addr.h
index 7b5d671..df0728c 100644
--- a/libcore/addr.h
+++ b/libcore/addr.h
@@ -55,6 +55,9 @@ class Addr
Addr operator+(int d) const { return Addr(_v + d); }
Addr operator-(int d) const { return Addr(_v - d); }
+ // return decremented address until it is a multiple of <a>, a power of 2
+ Addr alignedDown(int a) { return Addr(_v & ~( ((uint64)a) -1)); }
+
private:
uint64 _v;
};
diff --git a/libcore/cachegrindloader.cpp b/libcore/cachegrindloader.cpp
index d114946..2da8eeb 100644
--- a/libcore/cachegrindloader.cpp
+++ b/libcore/cachegrindloader.cpp
@@ -944,6 +944,19 @@ int CachegrindLoader::loadInternal(TraceData* data,
case '#':
continue;
+ case 'a':
+ // "arch: arm"
+ if (line.stripPrefix("rch: arm")) {
+ TraceData::Arch a = _data->architecture();
+ if ((a != TraceData::ArchUnknown) &&
+ (a != TraceData::ArchARM)) {
+ error(QString("Redefined architecture!"));
+ }
+ _data->setArchitecture(TraceData::ArchARM);
+ continue;
+ }
+ break;
+
case 't':
// totals:
diff --git a/libcore/tracedata.cpp b/libcore/tracedata.cpp
index b38e65b..9bef71c 100644
--- a/libcore/tracedata.cpp
+++ b/libcore/tracedata.cpp
@@ -3080,6 +3080,8 @@ void TraceData::init()
_maxPartNumber = 0;
_fixPool = 0;
_dynPool = 0;
+
+ _arch = ArchUnknown;
}
TraceData::~TraceData()
diff --git a/libcore/tracedata.h b/libcore/tracedata.h
index 4a362ee..a1ce0c9 100644
--- a/libcore/tracedata.h
+++ b/libcore/tracedata.h
@@ -1363,6 +1363,9 @@ class TraceObject: public TraceCostItem
class TraceData: public ProfileCostArray
{
public:
+ // profiled architecture (must be same for every part)
+ enum Arch { ArchUnknown, ArchARM };
+
TraceData(Logger* l = 0);
virtual ~TraceData();
@@ -1446,6 +1449,8 @@ class TraceData: public ProfileCostArray
void setCommand(const QString& command) { _command = command; }
QString command() const { return _command; }
+ void setArchitecture(Arch a) { _arch = a; }
+ Arch architecture() const { return _arch; }
ProfileCostArray* totals() { return &_totals; }
void setMaxThreadID(int tid) { _maxThreadID = tid; }
int maxThreadID() const { return _maxThreadID; }
@@ -1493,6 +1498,7 @@ class TraceData: public ProfileCostArray
TraceFileMap _fileMap;
TraceFunctionMap _functionMap;
QString _command;
+ Arch _arch;
QString _traceName;
// Max of all costs of calls: This allows to see if the incl. cost can
diff --git a/libviews/instrview.cpp b/libviews/instrview.cpp
index da0def5..5a91763 100644
--- a/libviews/instrview.cpp
+++ b/libviews/instrview.cpp
@@ -34,6 +34,7 @@
#include <QScrollBar>
#include <QHeaderView>
#include <QKeyEvent>
+#include <QProcessEnvironment>
#include "config.h"
#include "globalconfig.h"
@@ -45,7 +46,31 @@
#define DEFAULT_SHOWHEXCODE true
-// Helpers for parsing output of 'objdump'
+// Helpers
+
+// check environment variables
+
+QProcessEnvironment env;
+
+static
+QString getSysRoot()
+{
+ if (env.isEmpty())
+ env = QProcessEnvironment::systemEnvironment();
+
+ return env.value("SYSROOT");
+}
+
+static
+QString getObjDump()
+{
+ if (env.isEmpty())
+ env = QProcessEnvironment::systemEnvironment();
+
+ return env.value("OBJDUMP", "objdump");
+}
+
+// parsing output of 'objdump'
static Addr parseAddr(char* buf)
{
@@ -728,7 +753,17 @@ bool InstrView::searchFile(QString& dir, TraceObject* o)
QString filename = o->shortName();
if (QDir::isAbsolutePath(dir)) {
- return QFile::exists(dir + '/' + filename);
+ if (QFile::exists(dir + '/' + filename))
+ return true;
+
+ QString sysRoot = getSysRoot();
+ if (!sysRoot.isEmpty()) {
+ if (!dir.startsWith('/') && !sysRoot.endsWith('/'))
+ sysRoot += '/';
+ dir = sysRoot + dir;
+ return QFile::exists(dir + '/' + filename);
+ }
+ return false;
}
QFileInfo fi(dir, filename);
@@ -759,6 +794,7 @@ bool InstrView::fillInstrRange(TraceFunction* function,
Addr costAddr, nextCostAddr, objAddr, addr;
Addr dumpStartAddr, dumpEndAddr;
TraceInstrMap::Iterator costIt;
+ bool isArm = (function->data()->architecture() == TraceData::ArchARM);
// should not happen
if (it == itEnd) return false;
@@ -767,9 +803,16 @@ bool InstrView::fillInstrRange(TraceFunction* function,
TraceInstrMap::Iterator tmpIt = itEnd;
--tmpIt;
nextCostAddr = (*it).addr();
+
+ if (isArm) {
+ // for Arm: address always even (even for Thumb encoding)
+ nextCostAddr = nextCostAddr.alignedDown(2);
+ }
+
dumpStartAddr = (nextCostAddr<20) ? Addr(0) : nextCostAddr -20;
dumpEndAddr = (*tmpIt).addr() +20;
+
QString dir = function->object()->directory();
if (!searchFile(dir, function->object())) {
new InstrItem(this, this, 1,
@@ -779,6 +822,9 @@ bool InstrView::fillInstrRange(TraceFunction* function,
QString(" '%1'").arg(function->object()->name()));
new InstrItem(this, this, 3,
tr("This file can not be found."));
+ if (isArm)
+ new InstrItem(this, this, 4,
+ tr("If cross-compiled, set SYSROOT variable."));
return false;
}
function->object()->setDirectory(dir);
@@ -790,13 +836,17 @@ bool InstrView::fillInstrRange(TraceFunction* function,
<< QString("--start-address=0x%1").arg(dumpStartAddr.toString())
<< QString("--stop-address=0x%1").arg(dumpEndAddr.toString())
<< objfile;
- QString objdumpCmd = "objdump " + objdumpArgs.join(" ");
- if (1) qDebug("Running '%s'...", qPrintable(objdumpCmd));
+ QProcess objdump;
+ objdump.setArguments(objdumpArgs);
+ objdump.setProgram(getObjDump());
+
+ QString objdumpCmd;
+ objdumpCmd = objdump.program() + " " + objdump.arguments().join(" ");
+ qDebug("Running '%s'...", qPrintable(objdumpCmd));
// and run...
- QProcess objdump;
- objdump.start("objdump", objdumpArgs);
+ objdump.start();
if (!objdump.waitForStarted() ||
!objdump.waitForFinished()) {
@@ -873,6 +923,8 @@ bool InstrView::fillInstrRange(TraceFunction* function,
}
costAddr = nextCostAddr;
nextCostAddr = (it == itEnd) ? Addr(0) : (*it).addr();
+ if (isArm)
+ nextCostAddr = nextCostAddr.alignedDown(2);
if (0) qDebug() << "Got nextCostAddr: 0x" << nextCostAddr.toString()
<< ", costAddr 0x" << costAddr.toString();