• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

kcachegrind

  • sources
  • kde-4.14
  • kdesdk
  • kcachegrind
  • libviews
instrview.cpp
Go to the documentation of this file.
1 /* This file is part of KCachegrind.
2  Copyright (C) 2003-2011 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
3 
4  KCachegrind is free software; you can redistribute it and/or
5  modify it under the terms of the GNU General Public
6  License as published by the Free Software Foundation, version 2.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 /*
20  * Instruction View
21  */
22 
23 #include "instrview.h"
24 
25 #include <assert.h>
26 
27 #include <QDebug>
28 #include <QDir>
29 #include <QFile>
30 #include <QFileInfo>
31 #include <QProcess>
32 #include <QAction>
33 #include <QMenu>
34 #include <QScrollBar>
35 #include <QHeaderView>
36 #include <QKeyEvent>
37 
38 #include "config.h"
39 #include "globalconfig.h"
40 #include "instritem.h"
41 
42 
43 // InstrView defaults
44 
45 #define DEFAULT_SHOWHEXCODE true
46 
47 
48 // Helpers for parsing output of 'objdump'
49 
50 static Addr parseAddr(char* buf)
51 {
52  Addr addr;
53  uint pos = 0;
54 
55  // check for instruction line: <space>* <hex address> ":" <space>*
56  while(buf[pos]==' ' || buf[pos]=='\t') pos++;
57 
58  int digits = addr.set(buf + pos);
59  if ((digits==0) || (buf[pos+digits] != ':')) return Addr(0);
60 
61  return addr;
62 }
63 
64 static bool isHexDigit(char c)
65 {
66  return (c >='0' && c <='9') || (c >='a' && c <='f');
67 }
68 
74 static bool parseLine(const char* buf, Addr& addr,
75  QString& code, QString& mnemonic, QString& operands)
76 {
77  uint pos, start;
78 
79  // check for instruction line: <space>* <hex address> ":" <space>*
80 
81  pos = 0;
82  while(buf[pos]==' ' || buf[pos]=='\t') pos++;
83 
84  int digits = addr.set(buf + pos);
85  pos += digits;
86  if ((digits==0) || (buf[pos] != ':')) return false;
87 
88  // further parsing of objdump output...
89  pos++;
90  while(buf[pos]==' ' || buf[pos]=='\t') pos++;
91 
92  // check for hex code, patterns "xx "* / "xxxx "* / "xxxxxxxx"
93  // (with "x" being a lower case hex digit)
94  start = pos;
95  while(1) {
96  if (! isHexDigit(buf[pos])) break;
97  if (! isHexDigit(buf[pos+1])) break;
98  if (buf[pos+2] == ' ') {
99  pos += 3;
100  continue;
101  }
102  if (! isHexDigit(buf[pos+2])) break;
103  if (! isHexDigit(buf[pos+3])) break;
104  if (buf[pos+4] == ' ') {
105  pos += 5;
106  continue;
107  }
108  if (! isHexDigit(buf[pos+4])) break;
109  if (! isHexDigit(buf[pos+5])) break;
110  if (! isHexDigit(buf[pos+6])) break;
111  if (! isHexDigit(buf[pos+7])) break;
112  if (buf[pos+8] != ' ') break;
113  pos += 9;
114  }
115  if (pos <= start) return false;
116  code = QString::fromLatin1(buf + start, pos - start - 1);
117 
118  // skip whitespace
119  while(buf[pos]==' ' || buf[pos]=='\t') pos++;
120 
121  // check for mnemonic
122  start = pos;
123  while(buf[pos] && buf[pos]!=' ' && buf[pos]!='\t') pos++;
124  mnemonic = QString::fromLatin1(buf + start, pos - start);
125 
126  // skip whitespace
127  while(buf[pos]==' '|| buf[pos]=='\t') pos++;
128 
129  // last part are the operands
130  int operandsLen = strlen(buf + pos);
131 
132  // ignore a newline at end
133  if ((operandsLen>0) && (buf[pos + operandsLen - 1] == '\n'))
134  operandsLen--;
135 
136  // maximal 50 chars
137  if (operandsLen > 50)
138  operands = QString::fromLatin1(buf + pos, 47) + QString("...");
139  else
140  operands = QString::fromLatin1(buf+pos, operandsLen);
141 
142  if (0) qDebug("For 0x%s: Code '%s', Mnemonic '%s', Operands '%s'",
143  qPrintable(addr.toString()), qPrintable(code),
144  qPrintable(mnemonic), qPrintable(operands));
145 
146  return true;
147 }
148 
149 
150 
151 
152 //
153 // InstrView
154 //
155 
156 
157 InstrView::InstrView(TraceItemView* parentView,
158  QWidget* parent)
159  : QTreeWidget(parent), TraceItemView(parentView)
160 {
161  _showHexCode = DEFAULT_SHOWHEXCODE;
162  _lastHexCodeWidth = 50;
163 
164  _inSelectionUpdate = false;
165  _arrowLevels = 0;
166 
167  QStringList headerLabels;
168  headerLabels << tr( "#" )
169  << tr( "Cost" )
170  << tr( "Cost 2" )
171  << ""
172  << tr( "Hex" )
173  << "" // Mnenomic
174  << tr( "Assembly Instructions" )
175  << tr( "Source Position" );
176  setHeaderLabels(headerLabels);
177  setRootIsDecorated(false);
178  setAllColumnsShowFocus(true);
179  setUniformRowHeights(true);
180  // collapsing call/jump lines by double-click is confusing
181  setExpandsOnDoubleClick(false);
182 
183  // sorting will be enabled after refresh()
184  sortByColumn(0, Qt::AscendingOrder);
185  header()->setSortIndicatorShown(false);
186  setItemDelegate(new InstrItemDelegate(this));
187  setWhatsThis( whatsThis() );
188 
189  connect( this,
190  SIGNAL( currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
191  SLOT( selectedSlot(QTreeWidgetItem*,QTreeWidgetItem*) ) );
192 
193  setContextMenuPolicy(Qt::CustomContextMenu);
194  connect( this,
195  SIGNAL(customContextMenuRequested(const QPoint &) ),
196  SLOT(context(const QPoint &)));
197 
198  connect(this,
199  SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
200  SLOT(activatedSlot(QTreeWidgetItem*,int)));
201 
202  connect(header(), SIGNAL(sectionClicked(int)),
203  this, SLOT(headerClicked(int)));
204 
205  this->setWhatsThis( whatsThis());
206 }
207 
208 
209 QString InstrView::whatsThis() const
210 {
211  return tr( "<b>Annotated Machine Code</b>"
212  "<p>The annotated machine code list shows the "
213  "assembly instructions of the current selected "
214  "function together with (self) cost spent while "
215  "executing an instruction. If this is a call "
216  "instruction, lines with details on the "
217  "call happening are inserted into the source: "
218  "the cost spent inside of the call, the "
219  "number of calls happening, and the call destination.</p>"
220  "<p>The machine code shown is generated with "
221  "the 'objdump' utility from the 'binutils' package.</p>"
222  "<p>Select a line with call information to "
223  "make the destination function of this call current.</p>");
224 }
225 
226 void InstrView::context(const QPoint & p)
227 {
228  QMenu popup;
229  int c = columnAt(p.x());
230  QTreeWidgetItem* i = itemAt(p);
231 
232  TraceInstrCall* ic = i ? ((InstrItem*) i)->instrCall() : 0;
233  TraceInstrJump* ij = i ? ((InstrItem*) i)->instrJump() : 0;
234  TraceFunction* f = ic ? ic->call()->called() : 0;
235  TraceInstr* instr = ij ? ij->instrTo() : 0;
236 
237  QAction* activateFunctionAction = 0;
238  QAction* activateInstrAction = 0;
239  if (f) {
240  QString menuText = tr("Go to '%1'").arg(GlobalConfig::shortenSymbol(f->prettyName()));
241  activateFunctionAction = popup.addAction(menuText);
242  popup.addSeparator();
243  }
244  else if (instr) {
245  QString menuText = tr("Go to Address %1").arg(instr->name());
246  activateInstrAction = popup.addAction(menuText);
247  popup.addSeparator();
248  }
249 
250  if ((c == 1) || (c == 2)) {
251  addEventTypeMenu(&popup);
252  popup.addSeparator();
253  }
254  addGoMenu(&popup);
255  popup.addSeparator();
256 
257  QAction* toggleHexAction = new QAction(tr("Hex Code"), &popup);
258  toggleHexAction->setCheckable(true);
259  toggleHexAction->setChecked(_showHexCode);
260  popup.addAction(toggleHexAction);
261 
262  QAction* a = popup.exec(mapToGlobal(p + QPoint(0,header()->height())));
263  if (a == activateFunctionAction)
264  TraceItemView::activated(f);
265  else if (a == activateInstrAction)
266  TraceItemView::activated(instr);
267  else if (a == toggleHexAction) {
268  _showHexCode = !_showHexCode;
269  // remember width when hiding
270  if (!_showHexCode)
271  _lastHexCodeWidth = columnWidth(4);
272  setColumnWidths();
273  }
274 }
275 
276 
277 void InstrView::selectedSlot(QTreeWidgetItem *i, QTreeWidgetItem *)
278 {
279  if (!i) return;
280  // programatically selected items are not signalled
281  if (_inSelectionUpdate) return;
282 
283  TraceInstrCall* ic = ((InstrItem*) i)->instrCall();
284  TraceInstrJump* ij = ((InstrItem*) i)->instrJump();
285 
286  if (!ic && !ij) {
287  TraceInstr* instr = ((InstrItem*) i)->instr();
288  if (instr) {
289  _selectedItem = instr;
290  selected(instr);
291  }
292  return;
293  }
294 
295  if (ic) {
296  _selectedItem = ic;
297  selected(ic);
298  }
299  else if (ij) {
300  _selectedItem = ij;
301  selected(ij);
302  }
303 }
304 
305 void InstrView::activatedSlot(QTreeWidgetItem* i, int)
306 {
307  if (!i) return;
308  TraceInstrCall* ic = ((InstrItem*) i)->instrCall();
309  TraceInstrJump* ij = ((InstrItem*) i)->instrJump();
310 
311  if (!ic && !ij) {
312  TraceInstr* instr = ((InstrItem*) i)->instr();
313  if (instr) TraceItemView::activated(instr);
314  return;
315  }
316 
317  if (ic) {
318  TraceFunction* f = ic->call()->called();
319  if (f) TraceItemView::activated(f);
320  }
321  else if (ij) {
322  TraceInstr* instr = ij->instrTo();
323  if (instr) TraceItemView::activated(instr);
324  }
325 }
326 
327 void InstrView::keyPressEvent(QKeyEvent* event)
328 {
329  QTreeWidgetItem *item = currentItem();
330  if (item && ((event->key() == Qt::Key_Return) ||
331  (event->key() == Qt::Key_Space)))
332  {
333  activatedSlot(item, 0);
334  }
335  QTreeView::keyPressEvent(event);
336 }
337 
338 CostItem* InstrView::canShow(CostItem* i)
339 {
340  ProfileContext::Type t = i ? i->type() : ProfileContext::InvalidType;
341 
342  switch(t) {
343  case ProfileContext::Function:
344  case ProfileContext::Instr:
345  case ProfileContext::InstrJump:
346  case ProfileContext::Line:
347  return i;
348 
349  default:
350  break;
351  }
352 
353  return 0;
354 }
355 
356 
357 void InstrView::doUpdate(int changeType, bool)
358 {
359  // Special case ?
360  if (changeType == selectedItemChanged) {
361 
362  if (!_selectedItem) {
363  clearSelection();
364  return;
365  }
366 
367  QList<QTreeWidgetItem*> items = selectedItems();
368  InstrItem* ii = (items.count() > 0) ? (InstrItem*)items[0] : 0;
369  if (ii) {
370  if ((ii->instr() == _selectedItem) ||
371  (ii->instr() && (ii->instr()->line() == _selectedItem))) return;
372  if (ii->instrCall() &&
373  (ii->instrCall()->call()->called() == _selectedItem)) return;
374  }
375 
376  TraceInstrJump* ij = 0;
377  if (_selectedItem->type() == ProfileContext::InstrJump)
378  ij = (TraceInstrJump*) _selectedItem;
379 
380  QTreeWidgetItem *item, *item2;
381  for (int i=0; i<topLevelItemCount(); i++) {
382  item = topLevelItem(i);
383  ii = (InstrItem*)item;
384  if ((ii->instr() == _selectedItem) ||
385  (ii->instr() && (ii->instr()->line() == _selectedItem)) ||
386  (ij && (ij->instrTo() == ii->instr())) ) {
387  scrollToItem(item);
388  _inSelectionUpdate = true;
389  setCurrentItem(item);
390  _inSelectionUpdate = false;
391  break;
392  }
393  item2 = 0;
394  for (int j=0; i<item->childCount(); j++) {
395  item2 = item->child(j);
396  ii = (InstrItem*)item2;
397  if (!ii->instrCall()) continue;
398  if (ii->instrCall()->call()->called() == _selectedItem) {
399  scrollToItem(item2);
400  _inSelectionUpdate = true;
401  setCurrentItem(item2);
402  _inSelectionUpdate = false;
403  break;
404  }
405  }
406  if (item2) break;
407  }
408  return;
409  }
410 
411  if (changeType == groupTypeChanged) {
412  // update group colors for call lines
413  QTreeWidgetItem *item, *item2;
414  for (int i=0; i<topLevelItemCount(); i++) {
415  item = topLevelItem(i);
416  for (int j=0; i<item->childCount(); i++) {
417  item2 = item->child(j);
418  ((InstrItem*)item2)->updateGroup();
419  }
420  }
421  return;
422  }
423 
424  // On eventTypeChanged, we can not just change the costs shown in
425  // already existing items, as costs of 0 should make the line to not
426  // be shown at all. So we do a full refresh.
427 
428  refresh();
429 }
430 
431 void InstrView::setColumnWidths()
432 {
433 #if QT_VERSION >= 0x050000
434  header()->setSectionResizeMode(4, QHeaderView::Interactive);
435 #else
436  header()->setResizeMode(4, QHeaderView::Interactive);
437 #endif
438  if (_showHexCode) {
439  setColumnWidth(4, _lastHexCodeWidth);
440  }
441  else {
442  setColumnWidth(4, 0);
443  }
444 }
445 
446 // compare functions for jump arrow drawing
447 
448 // helper for compare
449 void getInstrJumpAddresses(const TraceInstrJump* ij, Addr& low, Addr& high)
450 {
451  low = ij->instrFrom()->addr();
452  high = ij->instrTo()->addr();
453 
454  if (low > high) {
455  Addr t = low;
456  low = high;
457  high = t;
458  }
459 }
460 
461 // sort jumps according to lower instruction address
462 bool instrJumpLowLessThan(const TraceInstrJump* ij1,
463  const TraceInstrJump* ij2)
464 {
465  Addr addr1Low, addr1High, addr2Low, addr2High;
466 
467  getInstrJumpAddresses(ij1, addr1Low, addr1High);
468  getInstrJumpAddresses(ij2, addr2Low, addr2High);
469 
470  if (addr1Low != addr2Low) return (addr1Low < addr2Low);
471  // jump ends come before jump starts
472  if (addr1Low == ij1->instrTo()->addr()) return true;
473  if (addr2Low == ij2->instrTo()->addr()) return false;
474  return (addr1High < addr2High);
475 }
476 
477 // sort jumps according to higher instruction address
478 bool instrJumpHighLessThan(const TraceInstrJump* ij1,
479  const TraceInstrJump* ij2)
480 {
481  Addr addr1Low, addr1High, addr2Low, addr2High;
482 
483  getInstrJumpAddresses(ij1, addr1Low, addr1High);
484  getInstrJumpAddresses(ij2, addr2Low, addr2High);
485 
486  if (addr1High != addr2High) return (addr1High < addr2High);
487  // jump ends come before jump starts
488  if (addr1High == ij1->instrTo()->addr()) return true;
489  if (addr2High == ij2->instrTo()->addr()) return false;
490  return (addr1Low < addr2Low);
491 }
492 
493 void InstrView::refresh()
494 {
495  int originalPosition = verticalScrollBar()->value();
496 
497  clear();
498  setColumnWidth(0, 20);
499  setColumnWidth(1, 50);
500  setColumnWidth(2, _eventType2 ? 50:0);
501  setColumnWidth(3, 0); // arrows, defaults to invisible
502  setColumnWidth(4, 0); // hex code column
503  setColumnWidth(5, 50); // command column
504  setColumnWidth(6, 250); // arg column
505 
506  // reset to automatic sizing to get column width
507 #if QT_VERSION >= 0x050000
508  header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
509 #else
510  header()->setResizeMode(4, QHeaderView::ResizeToContents);
511 #endif
512 
513 
514  if (_eventType)
515  headerItem()->setText(1, _eventType->name());
516  if (_eventType2)
517  headerItem()->setText(2, _eventType2->name());
518 
519  _arrowLevels = 0;
520  if (!_data || !_activeItem) return;
521 
522  ProfileContext::Type t = _activeItem->type();
523  TraceFunction* f = 0;
524  if (t == ProfileContext::Function) f = (TraceFunction*) _activeItem;
525  if (t == ProfileContext::Instr) {
526  f = ((TraceInstr*)_activeItem)->function();
527  if (!_selectedItem) _selectedItem = _activeItem;
528  }
529  if (t == ProfileContext::Line) {
530  f = ((TraceLine*)_activeItem)->functionSource()->function();
531  if (!_selectedItem) _selectedItem = _activeItem;
532  }
533 
534  if (!f) return;
535 
536  // check for instruction map
537  TraceInstrMap::Iterator itStart, it, tmpIt, itEnd;
538  TraceInstrMap* instrMap = f->instrMap();
539  if (instrMap) {
540  it = instrMap->begin();
541  itEnd = instrMap->end();
542  // get first instruction with cost of selected type
543  while(it != itEnd) {
544  if ((*it).hasCost(_eventType)) break;
545  if (_eventType2 && (*it).hasCost(_eventType2)) break;
546  ++it;
547  }
548  }
549  if (!instrMap || (it == itEnd)) {
550  new InstrItem(this, this, 1,
551  tr("There is no instruction info in the profile data file."));
552  new InstrItem(this, this, 2,
553  tr("Tip: For Callgrind, rerun with option"));
554  new InstrItem(this, this, 3, tr(" --dump-instr=yes"));
555  new InstrItem(this, this, 4, tr("To see (conditional) jumps, additionally specify"));
556  new InstrItem(this, this, 5, tr(" --collect-jumps=yes"));
557  return;
558  }
559 
560  // initialisation for arrow drawing
561  // create sorted list of jumps (for jump arrows)
562  _lowList.clear();
563  _highList.clear();
564  itStart = it;
565  while(1) {
566  TraceInstrJumpList jlist = (*it).instrJumps();
567  foreach(TraceInstrJump* ij, jlist) {
568  if (ij->executedCount()==0) continue;
569  _lowList.append(ij);
570  _highList.append(ij);
571  }
572  ++it;
573  while(it != itEnd) {
574  if ((*it).hasCost(_eventType)) break;
575  if (_eventType2 && (*it).hasCost(_eventType2)) break;
576  ++it;
577  }
578  if (it == itEnd) break;
579  }
580  qSort(_lowList.begin(), _lowList.end(), instrJumpLowLessThan);
581  qSort(_highList.begin(), _highList.end(), instrJumpHighLessThan);
582  _lowListIter = _lowList.begin(); // iterators to list start
583  _highListIter = _highList.begin();
584  _arrowLevels = 0;
585  _jump.resize(0);
586 
587 
588  // do multiple calls to 'objdump' if there are large gaps in addresses
589  it = itStart;
590  while(1) {
591  itStart = it;
592  while(1) {
593  tmpIt = it;
594  ++it;
595  while(it != itEnd) {
596  if ((*it).hasCost(_eventType)) break;
597  if (_eventType2 && (*it).hasCost(_eventType2)) break;
598  ++it;
599  }
600  if (it == itEnd) break;
601  if (!(*it).addr().isInRange( (*tmpIt).addr(),10000) ) break;
602  }
603 
604  // tmpIt is always last instruction with cost
605  if (!fillInstrRange(f, itStart, ++tmpIt)) break;
606  if (it == itEnd) break;
607  }
608 
609  _lastHexCodeWidth = columnWidth(4);
610  setColumnWidths();
611 
612  if (!_eventType2) {
613 #if QT_VERSION >= 0x050000
614  header()->setSectionResizeMode(2, QHeaderView::Interactive);
615 #else
616  header()->setResizeMode(2, QHeaderView::Interactive);
617 #endif
618  setColumnWidth(2, 0);
619  }
620 
621  // reset to the original position - this is useful when the view
622  // is refreshed just because we change between relative/absolute
623  verticalScrollBar()->setValue(originalPosition);
624 }
625 
626 /* This is called after adding instrItems, for each of them in
627  * address order. _jump is the global array of valid jumps
628  * for a line while we iterate downwards.
629  * The existing jumps, sorted in lowList according lower address,
630  * is iterated in the same way.
631  */
632 void InstrView::updateJumpArray(Addr addr, InstrItem* ii,
633  bool ignoreFrom, bool ignoreTo)
634 {
635  Addr lowAddr, highAddr;
636  int iEnd = -1, iStart = -1;
637 
638  if (0) qDebug("updateJumpArray(addr 0x%s, jump to %s)",
639  qPrintable(addr.toString()),
640  ii->instrJump()
641  ? qPrintable(ii->instrJump()->instrTo()->name()) : "?" );
642 
643  // check for new arrows starting from here downwards
644  while(_lowListIter != _lowList.end()) {
645  TraceInstrJump* ij= *_lowListIter;
646  lowAddr = ij->instrFrom()->addr();
647  if (ij->instrTo()->addr() < lowAddr)
648  lowAddr = ij->instrTo()->addr();
649 
650  if (lowAddr > addr) break;
651 
652  // if target is downwards but we draw no source, break
653  if (ignoreFrom && (lowAddr < ij->instrTo()->addr())) break;
654  // if source is downward but we draw no target, break
655  if (ignoreTo && (lowAddr < ij->instrFrom()->addr())) break;
656  // if this is another jump start, break
657  if (ii->instrJump() && (ij != ii->instrJump())) break;
658 
659 #if 0
660  for(iStart=0;iStart<_arrowLevels;iStart++)
661  if (_jump[iStart] &&
662  (_jump[iStart]->instrTo() == ij->instrTo())) break;
663 #else
664  iStart = _arrowLevels;
665 #endif
666 
667  if (iStart==_arrowLevels) {
668  for(iStart=0;iStart<_arrowLevels;iStart++)
669  if (_jump[iStart] == 0) break;
670  if (iStart==_arrowLevels) {
671  _arrowLevels++;
672  _jump.resize(_arrowLevels);
673  }
674  if (0) qDebug(" new start at %d for %s",
675  iStart, qPrintable(ij->name()));
676  _jump[iStart] = ij;
677  }
678  _lowListIter++;
679  }
680 
681  ii->setJumpArray(_jump);
682 
683  // check for active arrows ending here
684  while(_highListIter != _highList.end()) {
685  TraceInstrJump* ij= *_highListIter;
686  highAddr = ij->instrFrom()->addr();
687  if (ij->instrTo()->addr() > highAddr) {
688  highAddr = ij->instrTo()->addr();
689  if (ignoreTo) break;
690  }
691  else if (ignoreFrom) break;
692 
693  if (highAddr > addr) break;
694 
695  for(iEnd=0;iEnd<_arrowLevels;iEnd++)
696  if (_jump[iEnd] == ij) break;
697  if (iEnd==_arrowLevels) {
698  qDebug() << "InstrView: no jump start for end at 0x"
699  << highAddr.toString() << " ?";
700  iEnd = -1;
701  }
702 
703  if (0 && (iEnd>=0))
704  qDebug(" end %d (%s to %s)",
705  iEnd,
706  qPrintable(_jump[iEnd]->instrFrom()->name()),
707  qPrintable(_jump[iEnd]->instrTo()->name()));
708 
709  if (0 && ij) qDebug("next end: %s to %s",
710  qPrintable(ij->instrFrom()->name()),
711  qPrintable(ij->instrTo()->name()));
712 
713  _highListIter++;
714 
715  if (highAddr > addr)
716  break;
717  else {
718  if (iEnd>=0) _jump[iEnd] = 0;
719  iEnd = -1;
720  }
721  }
722  if (iEnd>=0) _jump[iEnd] = 0;
723 }
724 
725 
726 bool InstrView::searchFile(QString& dir, TraceObject* o)
727 {
728  QString filename = o->shortName();
729 
730  if (QDir::isAbsolutePath(dir)) {
731  return QFile::exists(dir + '/' + filename);
732  }
733 
734  QFileInfo fi(dir, filename);
735  if (fi.exists()) {
736  dir = fi.absolutePath();
737  return true;
738  }
739 
740  TracePart* firstPart = _data->parts().first();
741  if (firstPart) {
742  QFileInfo partFile(firstPart->name());
743  if (QFileInfo(partFile.absolutePath(), filename).exists()) {
744  dir = partFile.absolutePath();
745  return true;
746  }
747  }
748 
749  return false;
750 }
751 
755 bool InstrView::fillInstrRange(TraceFunction* function,
756  TraceInstrMap::Iterator it,
757  TraceInstrMap::Iterator itEnd)
758 {
759  Addr costAddr, nextCostAddr, objAddr, addr;
760  Addr dumpStartAddr, dumpEndAddr;
761  TraceInstrMap::Iterator costIt;
762 
763  // should not happen
764  if (it == itEnd) return false;
765 
766  // calculate address range for call to objdump
767  TraceInstrMap::Iterator tmpIt = itEnd;
768  --tmpIt;
769  nextCostAddr = (*it).addr();
770  dumpStartAddr = (nextCostAddr<20) ? Addr(0) : nextCostAddr -20;
771  dumpEndAddr = (*tmpIt).addr() +20;
772 
773  QString dir = function->object()->directory();
774  if (!searchFile(dir, function->object())) {
775  new InstrItem(this, this, 1,
776  tr("For annotated machine code, "
777  "the following object file is needed:"));
778  new InstrItem(this, this, 2,
779  QString(" '%1'").arg(function->object()->name()));
780  new InstrItem(this, this, 3,
781  tr("This file can not be found."));
782  return false;
783  }
784  function->object()->setDirectory(dir);
785 
786  // call objdump synchronously
787  QString objfile = dir + '/' + function->object()->shortName();
788  QStringList objdumpArgs = QStringList()
789  << "-C" << "-d"
790  << QString("--start-address=0x%1").arg(dumpStartAddr.toString())
791  << QString("--stop-address=0x%1").arg(dumpEndAddr.toString())
792  << objfile;
793  QString objdumpCmd = "objdump " + objdumpArgs.join(" ");
794 
795  if (1) qDebug("Running '%s'...", qPrintable(objdumpCmd));
796 
797  // and run...
798  QProcess objdump;
799  objdump.start("objdump", objdumpArgs);
800  if (!objdump.waitForStarted() ||
801  !objdump.waitForFinished()) {
802 
803  new InstrItem(this, this, 1,
804  tr("There is an error trying to execute the command"));
805  new InstrItem(this, this, 2,
806  QString(" '%1'").arg(objdumpCmd));
807  new InstrItem(this, this, 3,
808  tr("Check that you have installed 'objdump'."));
809  new InstrItem(this, this, 4,
810  tr("This utility can be found in the 'binutils' package."));
811  return false;
812  }
813 
814 
815 #define BUF_SIZE 256
816 
817  char buf[BUF_SIZE];
818  bool inside = false, skipLineWritten = true;
819  int readBytes = -1;
820  int objdumpLineno = 0, dumpedLines = 0, noAssLines = 0;
821  SubCost most = 0;
822  TraceInstr* currInstr;
823  InstrItem *ii, *ii2, *item = 0, *first = 0, *selected = 0;
824  QString code, cmd, args;
825  bool needObjAddr = true, needCostAddr = true;
826 
827  costAddr = 0;
828  objAddr = 0;
829 
830  QList<QTreeWidgetItem*> items;
831  while (1) {
832 
833  if (needObjAddr) {
834  needObjAddr = false;
835 
836  // read next objdump line
837  while (1) {
838  readBytes=objdump.readLine(buf, BUF_SIZE);
839  if (readBytes<=0) {
840  objAddr = 0;
841  break;
842  }
843 
844  objdumpLineno++;
845  if (readBytes == BUF_SIZE) {
846  qDebug("ERROR: Line %d of '%s' too long\n",
847  objdumpLineno, qPrintable(objdumpCmd));
848  }
849  else if ((readBytes>0) && (buf[readBytes-1] == '\n'))
850  buf[readBytes-1] = 0;
851 
852  objAddr = parseAddr(buf);
853  if ((objAddr<dumpStartAddr) || (objAddr>dumpEndAddr))
854  objAddr = 0;
855  if (objAddr != 0) break;
856  }
857 
858  if (0) qDebug() << "Got ObjAddr: 0x" << objAddr.toString();
859  }
860 
861  // try to keep objAddr in [costAddr;nextCostAddr]
862  if (needCostAddr &&
863  (nextCostAddr > 0) &&
864  ((objAddr == Addr(0)) || (objAddr >= nextCostAddr)) ) {
865  needCostAddr = false;
866 
867  costIt = it;
868  ++it;
869  while(it != itEnd) {
870  if ((*it).hasCost(_eventType)) break;
871  if (_eventType2 && (*it).hasCost(_eventType2)) break;
872  ++it;
873  }
874  costAddr = nextCostAddr;
875  nextCostAddr = (it == itEnd) ? Addr(0) : (*it).addr();
876 
877  if (0) qDebug() << "Got nextCostAddr: 0x" << nextCostAddr.toString()
878  << ", costAddr 0x" << costAddr.toString();
879  }
880 
881  // if we have no more address from objdump, stop
882  if (objAddr == 0) break;
883 
884  if ((nextCostAddr==0) || (costAddr == 0) ||
885  (objAddr < nextCostAddr)) {
886  // next line is objAddr
887 
888  // this sets addr, code, cmd, args
889  bool isAssemblyInstr = parseLine(buf, addr, code, cmd, args);
890  Q_UNUSED(isAssemblyInstr);
891  assert(isAssemblyInstr && (objAddr == addr));
892 
893  if (costAddr == objAddr) {
894  currInstr = &(*costIt);
895  needCostAddr = true;
896  }
897  else
898  currInstr = 0;
899 
900  needObjAddr = true;
901 
902  if (0) qDebug() << "Dump Obj Addr: 0x" << addr.toString()
903  << " [" << cmd << " " << args << "], cost (0x"
904  << costAddr.toString() << ", next 0x"
905  << nextCostAddr.toString() << ")";
906  }
907  else {
908  addr = costAddr;
909  code = cmd = QString();
910  args = tr("(No Instruction)");
911 
912  currInstr = &(*costIt);
913  needCostAddr = true;
914 
915  noAssLines++;
916  if (0) qDebug() << "Dump Cost Addr: 0x" << addr.toString()
917  << " (no ass), objAddr 0x" << objAddr.toString();
918  }
919 
920  // update inside
921  if (!inside) {
922  if (currInstr) inside = true;
923  }
924  else {
925  if (0) qDebug() << "Check if 0x" << addr.toString() << " is in ]0x"
926  << costAddr.toString() << ",0x"
927  << (nextCostAddr - 3*GlobalConfig::noCostInside()).toString()
928  << "[" << endl;
929 
930  // Suppose a average instruction len of 3 bytes
931  if ( (addr > costAddr) &&
932  ((nextCostAddr==0) ||
933  (addr < nextCostAddr - 3*GlobalConfig::noCostInside()) ))
934  inside = false;
935  }
936 
937  int context = GlobalConfig::context();
938 
939  if ( ((costAddr==0) || (addr > costAddr + 3*context)) &&
940  ((nextCostAddr==0) || (addr < nextCostAddr - 3*context)) ) {
941 
942  // the very last skipLine can be ommitted
943  if ((it == itEnd) &&
944  (itEnd == function->instrMap()->end())) skipLineWritten=true;
945 
946  if (!skipLineWritten) {
947  skipLineWritten = true;
948  // a "skipping" line: print "..." instead of a line number
949  code = cmd = QString();
950  args = QString("...");
951  }
952  else
953  continue;
954  }
955  else
956  skipLineWritten = false;
957 
958 
959  ii = new InstrItem(this, 0, addr, inside,
960  code, cmd, args, currInstr);
961  items.append(ii);
962 
963  dumpedLines++;
964  if (0) qDebug() << "Dumped 0x" << addr.toString() << " "
965  << (inside ? "Inside " : "Outside")
966  << (currInstr ? "Cost" : "");
967 
968  // no calls/jumps if we have no cost for this line
969  if (!currInstr) continue;
970 
971  if (!selected &&
972  ((currInstr == _selectedItem) ||
973  (currInstr->line() == _selectedItem))) selected = ii;
974 
975  if (!first) first = ii;
976 
977  if (currInstr->subCost(_eventType) > most) {
978  item = ii;
979  most = currInstr->subCost(_eventType);
980  }
981 
982  ii->setExpanded(true);
983  foreach(TraceInstrCall* ic, currInstr->instrCalls()) {
984  if ((ic->subCost(_eventType)==0) &&
985  (ic->subCost(_eventType2)==0)) continue;
986 
987  if (ic->subCost(_eventType) > most) {
988  item = ii;
989  most = ic->subCost(_eventType);
990  }
991 
992  ii2 = new InstrItem(this, ii, addr, currInstr, ic);
993 
994  if (!selected && (ic->call()->called() == _selectedItem))
995  selected = ii2;
996  }
997 
998  foreach(TraceInstrJump* ij, currInstr->instrJumps()) {
999  if (ij->executedCount()==0) continue;
1000 
1001  new InstrItem(this, ii, addr, currInstr, ij);
1002  }
1003  }
1004 
1005  // Resize columns with address/counts/opcode to contents
1006 #if QT_VERSION >= 0x050000
1007  header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
1008  header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
1009  header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
1010  header()->setSectionResizeMode(5, QHeaderView::ResizeToContents);
1011 #else
1012  header()->setResizeMode(0, QHeaderView::ResizeToContents);
1013  header()->setResizeMode(1, QHeaderView::ResizeToContents);
1014  header()->setResizeMode(2, QHeaderView::ResizeToContents);
1015  header()->setResizeMode(5, QHeaderView::ResizeToContents);
1016 #endif
1017 
1018  setSortingEnabled(false);
1019  addTopLevelItems(items);
1020  expandAll();
1021  setSortingEnabled(true);
1022  // always reset to line number sort
1023  sortByColumn(0, Qt::AscendingOrder);
1024  header()->setSortIndicatorShown(false);
1025 
1026  // Reallow interactive column size change after resizing to content
1027 #if QT_VERSION >= 0x050000
1028  header()->setSectionResizeMode(0, QHeaderView::Interactive);
1029  header()->setSectionResizeMode(1, QHeaderView::Interactive);
1030  header()->setSectionResizeMode(2, QHeaderView::Interactive);
1031  header()->setSectionResizeMode(5, QHeaderView::Interactive);
1032 #else
1033  header()->setResizeMode(0, QHeaderView::Interactive);
1034  header()->setResizeMode(1, QHeaderView::Interactive);
1035  header()->setResizeMode(2, QHeaderView::Interactive);
1036  header()->setResizeMode(5, QHeaderView::Interactive);
1037 #endif
1038 
1039  if (selected) item = selected;
1040  if (item) first = item;
1041  if (first) {
1042  scrollToItem(first);
1043  _inSelectionUpdate = true;
1044  setCurrentItem(first);
1045  _inSelectionUpdate = false;
1046  }
1047 
1048  // for arrows: go down the list according to list sorting
1049  QTreeWidgetItem *item1, *item2;
1050  for (int i=0; i<topLevelItemCount(); i++) {
1051  item1 = topLevelItem(i);
1052  ii = (InstrItem*)item1;
1053  updateJumpArray(ii->addr(), ii, true, false);
1054 
1055  for (int j=0; j<item1->childCount(); j++) {
1056  item2 = item1->child(j);
1057  ii2 = (InstrItem*)item2;
1058  if (ii2->instrJump())
1059  updateJumpArray(ii->addr(), ii2, false, true);
1060  else
1061  ii2->setJumpArray(_jump);
1062  }
1063  }
1064 
1065  if (arrowLevels())
1066  setColumnWidth(3, 10 + 6*arrowLevels() + 2);
1067  else
1068  setColumnWidth(3, 0);
1069 
1070  if (noAssLines > 1) {
1071  // trace cost not matching code
1072 
1073  new InstrItem(this, this, 1,
1074  tr("There are %n cost line(s) without machine code.", "", noAssLines));
1075  new InstrItem(this, this, 2,
1076  tr("This happens because the code of"));
1077  new InstrItem(this, this, 3, QString(" %1").arg(objfile));
1078  new InstrItem(this, this, 4,
1079  tr("does not seem to match the profile data file."));
1080  new InstrItem(this, this, 5, "");
1081  new InstrItem(this, this, 6,
1082  tr("Are you using an old profile data file or is the above mentioned"));
1083  new InstrItem(this, this, 7,
1084  tr("ELF object from an updated installation/another machine?"));
1085  new InstrItem(this, this, 8, "");
1086  return false;
1087  }
1088 
1089  if (dumpedLines == 0) {
1090  // no matching line read from popen
1091  new InstrItem(this, this, 1,
1092  tr("There seems to be an error trying to execute the command"));
1093  new InstrItem(this, this, 2,
1094  QString(" '%1'").arg(objdumpCmd));
1095  new InstrItem(this, this, 3,
1096  tr("Check that the ELF object used in the command exists."));
1097  new InstrItem(this, this, 4,
1098  tr("Check that you have installed 'objdump'."));
1099  new InstrItem(this, this, 5,
1100  tr("This utility can be found in the 'binutils' package."));
1101  return false;
1102  }
1103 
1104  return true;
1105 }
1106 
1107 void InstrView::headerClicked(int col)
1108 {
1109  if (col == 0) {
1110  sortByColumn(col, Qt::AscendingOrder);
1111  }
1112  //All others but Source Text column Descending
1113  else if (col <4) {
1114  sortByColumn(col, Qt::DescendingOrder);
1115  }
1116 }
1117 
1118 void InstrView::restoreOptions(const QString& prefix, const QString& postfix)
1119 {
1120  ConfigGroup* g = ConfigStorage::group(prefix, postfix);
1121 
1122  _showHexCode = g->value("ShowHexCode", DEFAULT_SHOWHEXCODE).toBool();
1123  delete g;
1124 }
1125 
1126 void InstrView::saveOptions(const QString& prefix, const QString& postfix)
1127 {
1128  ConfigGroup* g = ConfigStorage::group(prefix + postfix);
1129 
1130  g->setValue("ShowHexCode", _showHexCode, DEFAULT_SHOWHEXCODE);
1131  delete g;
1132 }
1133 
1134 #include "instrview.moc"
QWidget::customContextMenuRequested
void customContextMenuRequested(const QPoint &pos)
TraceItemView::selectedItemChanged
Definition: traceitemview.h:86
QList::clear
void clear()
QWidget
TraceItemView::_selectedItem
CostItem * _selectedItem
Definition: traceitemview.h:211
parseLine
static bool parseLine(const char *buf, Addr &addr, QString &code, QString &mnemonic, QString &operands)
Parses a line from objdump assembly output, returning false for a line without an assembly instructio...
Definition: instrview.cpp:74
InstrView::activatedSlot
void activatedSlot(QTreeWidgetItem *, int)
Definition: instrview.cpp:305
InstrView::whatsThis
QString whatsThis() const
Definition: instrview.cpp:209
instrJumpHighLessThan
bool instrJumpHighLessThan(const TraceInstrJump *ij1, const TraceInstrJump *ij2)
Definition: instrview.cpp:478
TracePart::name
QString name() const
Definition: tracedata.h:667
ProfileCostArray::subCost
SubCost subCost(EventType *)
Returns a sub cost.
Definition: costitem.cpp:591
InstrItem::instr
TraceInstr * instr() const
Definition: instritem.h:58
InstrView::InstrView
InstrView(TraceItemView *parentView, QWidget *parent=0)
Definition: instrview.cpp:157
globalconfig.h
ProfileContext::Line
Definition: context.h:39
InstrView::headerClicked
void headerClicked(int)
Definition: instrview.cpp:1107
isHexDigit
static bool isHexDigit(char c)
Definition: instrview.cpp:64
QTreeWidgetItem::child
QTreeWidgetItem * child(int index) const
QTreeWidget::currentItemChanged
void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
QTreeWidget::scrollToItem
void scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
TraceItemView::addEventTypeMenu
void addEventTypeMenu(QMenu *, bool withCost2=true)
Definition: traceitemview.cpp:466
TraceInstrJump::instrTo
TraceInstr * instrTo() const
Definition: tracedata.h:737
TraceInstr::instrJumps
const TraceInstrJumpList & instrJumps() const
Definition: tracedata.h:908
QAction::setChecked
void setChecked(bool)
CostItem::type
ProfileContext::Type type() const
Definition: costitem.h:45
InstrItem::setJumpArray
void setJumpArray(const QVector< TraceInstrJump * > &a)
Definition: instritem.cpp:298
getInstrJumpAddresses
void getInstrJumpAddresses(const TraceInstrJump *ij, Addr &low, Addr &high)
Definition: instrview.cpp:449
QMap
TraceFunction
A traced function.
Definition: tracedata.h:1122
TraceItemView::_data
TraceData * _data
Definition: traceitemview.h:209
QMenu::addAction
void addAction(QAction *action)
TraceJumpCost::executedCount
SubCost executedCount()
Definition: tracedata.cpp:55
TraceItemView::addGoMenu
void addGoMenu(QMenu *)
Definition: traceitemview.cpp:471
QWidget::mapToGlobal
QPoint mapToGlobal(const QPoint &pos) const
ConfigGroup::setValue
virtual void setValue(const QString &key, const QVariant &value, const QVariant &defaultValue=QVariant())
Definition: config.cpp:57
InstrView::restoreOptions
void restoreOptions(const QString &prefix, const QString &postfix)
Definition: instrview.cpp:1118
QTreeWidget::items
QList< QTreeWidgetItem * > items(const QMimeData *data) const
QTreeView::setUniformRowHeights
void setUniformRowHeights(bool uniform)
CostItem
Base class for cost items.
Definition: costitem.h:37
InstrView::InstrItem
friend class InstrItem
Definition: instrview.h:34
config.h
TraceInstrCall
A call from an instruction of one function to another function.
Definition: tracedata.h:782
QHeaderView::setSortIndicatorShown
void setSortIndicatorShown(bool show)
ProfileContext::Instr
Definition: context.h:38
QPoint
QStringList::join
QString join(const QString &separator) const
QTreeView::sortByColumn
void sortByColumn(int column, Qt::SortOrder order)
QFile::exists
bool exists() const
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
Addr
Addresses are 64bit values like costs to be able to always load profile data produced on 64bit archit...
Definition: addr.h:31
QPoint::x
int x() const
TraceItemView::_eventType2
EventType * _eventType2
Definition: traceitemview.h:212
QTreeWidget::clear
void clear()
ConfigStorage::group
static ConfigGroup * group(const QString &group, const QString &optSuffix=QString())
Definition: config.cpp:80
TraceItemView
Abstract Base Class for KCachegrind Views.
Definition: traceitemview.h:70
TraceObject
A object containing a text segment (shared lib/executable) with defined functions.
Definition: tracedata.h:1331
InstrItemDelegate
Definition: instritem.h:85
TraceData::parts
TracePartList parts() const
Definition: tracedata.h:1397
Addr::toString
QString toString() const
Definition: addr.cpp:50
QTreeWidget
TraceItemView::_eventType
EventType * _eventType
Definition: traceitemview.h:212
QObject::name
const char * name() const
QTreeView::columnWidth
int columnWidth(int column) const
QTreeView::setColumnWidth
void setColumnWidth(int column, int width)
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
TraceInstrJump::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.cpp:990
InstrView::context
void context(const QPoint &)
Definition: instrview.cpp:226
QVector::resize
void resize(int size)
InstrView::keyPressEvent
void keyPressEvent(QKeyEvent *event)
Definition: instrview.cpp:327
TraceInstr
A code instruction address of the program.
Definition: tracedata.h:887
QTreeWidget::addTopLevelItems
void addTopLevelItems(const QList< QTreeWidgetItem * > &items)
QProcess
QAbstractItemView::setItemDelegate
void setItemDelegate(QAbstractItemDelegate *delegate)
QTreeWidget::itemAt
QTreeWidgetItem * itemAt(const QPoint &p) const
GlobalConfig::context
static int context()
Definition: globalconfig.cpp:412
TraceFunction::prettyName
QString prettyName() const
Similar to name, but prettyfied = more descriptive to humans.
Definition: tracedata.cpp:1889
InstrView::saveOptions
void saveOptions(const QString &prefix, const QString &postfix)
Definition: instrview.cpp:1126
QList::first
T & first()
TraceItemView::_activeItem
CostItem * _activeItem
Definition: traceitemview.h:211
QTreeView::setAllColumnsShowFocus
void setAllColumnsShowFocus(bool enable)
QMenu::addSeparator
QAction * addSeparator()
QTreeWidget::currentItem
QTreeWidgetItem * currentItem() const
QString
QList
QMap::end
iterator end()
TraceInstr::instrCalls
const TraceInstrCallList & instrCalls() const
Definition: tracedata.h:909
TraceLine
A source line of the program.
Definition: tracedata.h:935
QAbstractScrollArea::verticalScrollBar
QScrollBar * verticalScrollBar() const
GlobalConfig::shortenSymbol
static QString shortenSymbol(const QString &)
Definition: globalconfig.cpp:395
QMenu::exec
QAction * exec()
ConfigGroup
A group of configuration settings.
Definition: config.h:35
Addr::set
int set(const char *s)
Definition: addr.cpp:29
QMap::begin
iterator begin()
QStringList
InstrView::arrowLevels
int arrowLevels()
Definition: instrview.h:44
QFileInfo
QList::end
iterator end()
TraceItemView::selected
virtual void selected(TraceItemView *sender, CostItem *)
Notification from child views.
Definition: traceitemview.cpp:319
QKeyEvent::key
int key() const
QMenu
QProcess::waitForStarted
bool waitForStarted(int msecs)
TraceItemView::activated
virtual void activated(TraceItemView *sender, CostItem *)
Definition: traceitemview.cpp:347
QWidget::setContextMenuPolicy
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
QAbstractSlider::value
value
QTreeView::expandAll
void expandAll()
QAction::setCheckable
void setCheckable(bool)
instrview.h
QTreeWidget::selectedItems
QList< QTreeWidgetItem * > selectedItems() const
TraceInstr::line
TraceLine * line() const
Definition: tracedata.h:907
QTreeWidget::setCurrentItem
void setCurrentItem(QTreeWidgetItem *item)
QTreeWidget::setHeaderLabels
void setHeaderLabels(const QStringList &labels)
TraceFunction::instrMap
TraceInstrMap * instrMap()
Definition: tracedata.cpp:2521
QKeyEvent
QTreeView::setExpandsOnDoubleClick
void setExpandsOnDoubleClick(bool enable)
QTreeWidget::headerItem
QTreeWidgetItem * headerItem() const
QTreeView::setSortingEnabled
void setSortingEnabled(bool enable)
QTreeWidgetItem::setExpanded
void setExpanded(bool expand)
TracePart
A Trace Part: All data read from a trace file, containing all costs that happened in a specified time...
Definition: tracedata.h:655
QWidget::setWhatsThis
void setWhatsThis(const QString &)
QDir::isAbsolutePath
bool isAbsolutePath(const QString &path)
TraceInstrJump
A jump from an instruction to another inside of a function.
Definition: tracedata.h:725
QTest::toString
char * toString(const T &value)
QTreeWidgetItem
TraceInstr::name
virtual QString name() const
Returns dynamic name info (without type)
Definition: tracedata.cpp:1366
ProfileContext::Type
Type
Definition: context.h:36
InstrItem::addr
Addr addr() const
Definition: instritem.h:56
SubCost
Cost event counter, simple wrapper around a 64bit entity.
Definition: subcost.h:32
QHeaderView::setResizeMode
void setResizeMode(ResizeMode mode)
QAction
TraceCall::called
TraceFunction * called(bool skipCycle=false) const
Definition: tracedata.cpp:1235
BUF_SIZE
#define BUF_SIZE
QTreeWidgetItem::setText
void setText(int column, const QString &text)
TraceItemView::groupTypeChanged
Definition: traceitemview.h:83
QVariant::toBool
bool toBool() const
instritem.h
QString::fromLatin1
QString fromLatin1(const char *str, int size)
DEFAULT_SHOWHEXCODE
#define DEFAULT_SHOWHEXCODE
Definition: instrview.cpp:45
QTreeView::header
QHeaderView * header() const
instrJumpLowLessThan
bool instrJumpLowLessThan(const TraceInstrJump *ij1, const TraceInstrJump *ij2)
Definition: instrview.cpp:462
InstrItem
Definition: instritem.h:34
TraceInstrJump::instrFrom
TraceInstr * instrFrom() const
Definition: tracedata.h:736
QMap::Iterator
typedef Iterator
QTreeWidget::topLevelItem
QTreeWidgetItem * topLevelItem(int index) const
InstrView::selectedSlot
void selectedSlot(QTreeWidgetItem *, QTreeWidgetItem *)
Definition: instrview.cpp:277
parseAddr
static Addr parseAddr(char *buf)
Definition: instrview.cpp:50
QTreeView::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
InstrItem::instrCall
TraceInstrCall * instrCall() const
Definition: instritem.h:59
QTreeView::setRootIsDecorated
void setRootIsDecorated(bool show)
GlobalConfig::noCostInside
static int noCostInside()
Definition: globalconfig.cpp:417
QTreeWidget::topLevelItemCount
int topLevelItemCount() const
QAbstractItemView::clearSelection
void clearSelection()
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
InstrItem::instrJump
TraceInstrJump * instrJump() const
Definition: instritem.h:60
TraceInstrCall::call
TraceCall * call() const
Definition: tracedata.h:791
ProfileContext::InstrJump
Definition: context.h:40
QTreeWidgetItem::childCount
int childCount() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QTreeWidget::itemDoubleClicked
void itemDoubleClicked(QTreeWidgetItem *item, int column)
QList::begin
iterator begin()
QProcess::start
void start(const QString &program, const QStringList &arguments, QFlags< QIODevice::OpenModeFlag > mode)
QTreeView::columnAt
int columnAt(int x) const
QWidget::height
int height() const
EventType::name
const QString & name()
Definition: eventtype.h:65
TraceInstr::addr
Addr addr() const
Definition: tracedata.h:905
TraceObject::shortName
QString shortName() const
Definition: tracedata.cpp:2950
ProfileContext::Function
Definition: context.h:46
QIODevice::readLine
qint64 readLine(char *data, qint64 maxSize)
ProfileContext::InvalidType
Definition: context.h:37
ConfigGroup::value
virtual QVariant value(const QString &key, const QVariant &defaultValue) const
Definition: config.cpp:60
QProcess::waitForFinished
bool waitForFinished(int msecs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:39:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kcachegrind

Skip menu "kcachegrind"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal