~ubuntu-branches/ubuntu/intrepid/kdesdk/intrepid-updates

« back to all changes in this revision

Viewing changes to kmtrace/kmtrace.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2008-05-28 10:11:43 UTC
  • mto: This revision was merged to the branch mainline in revision 37.
  • Revision ID: james.westby@ubuntu.com-20080528101143-gzc3styjz1b70zxu
Tags: upstream-4.0.80
ImportĀ upstreamĀ versionĀ 4.0.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <qintdict.h>
 
1
#include <q3intdict.h>
 
2
//Added by qt3to4:
2
3
#include <stdio.h>
3
4
#include <qstringlist.h>
4
 
#include <qstrlist.h>
 
5
#include <q3strlist.h>
5
6
#include <qtextstream.h>
6
 
#include <qsortedlist.h>
 
7
#include <q3sortedlist.h>
7
8
#include <qfile.h>
8
 
#include <qtl.h>
9
 
#include <qvaluelist.h>
 
9
#include <q3tl.h>
 
10
#include <q3valuelist.h>
 
11
#include <Q3CString>
10
12
#include <stdlib.h>
11
 
#include <ktempfile.h>
12
 
#include <kinstance.h>
 
13
#include <ktemporaryfile.h>
 
14
#include <kcomponentdata.h>
13
15
#include <kstandarddirs.h>
14
16
#include <kcmdlineargs.h>
15
 
#include <kprocess.h>
 
17
#include <kshell.h>
16
18
 
17
19
extern "C" {
18
20
/* Options passed to cplus_demangle (in 2nd parameter). */
48
50
  bool operator<(const Entry &e) { return total_size > e.total_size; }
49
51
};
50
52
 
51
 
QIntDict<Entry> *entryDict = 0;
52
 
QIntDict<char> *symbolDict = 0;
53
 
QIntDict<char> *formatDict = 0;
54
 
QSortedList<Entry> *entryList = 0;
55
 
QStrList *excludes = 0;
 
53
Q3IntDict<Entry> *entryDict = 0;
 
54
Q3IntDict<char> *symbolDict = 0;
 
55
Q3IntDict<char> *formatDict = 0;
 
56
Q3SortedList<Entry> *entryList = 0;
 
57
Q3StrList *excludes = 0;
56
58
 
57
59
const char * const unknown = "<unknown>";
58
60
const char * const excluded = "<excluded>";
66
68
int maxBytes;
67
69
 
68
70
int fromHex(const char *str);
69
 
void parseLine(const QCString &_line, char operation);
 
71
void parseLine(const QString &_line, char operation);
70
72
void dumpBlocks();
71
73
 
72
74
int fromHex(const char *str)
77
79
}
78
80
 
79
81
// [address0][address1] .... [address] + base size
80
 
void parseLine(const QCString &_line, char operation)
 
82
void parseLine(const QString &_line, char operation)
81
83
{
82
84
  char *line= (char *) _line.data();
83
85
  const char *cols[200];
147
149
 
148
150
void sortBlocks()
149
151
{
150
 
   QIntDictIterator<Entry> it(*entryDict);
 
152
   Q3IntDictIterator<Entry> it(*entryDict);
151
153
   for(;it.current(); ++it)
152
154
   {
153
155
      Entry *entry = it.current();
164
166
 
165
167
void collectDupes()
166
168
{
167
 
   QIntDict<Entry> dupeDict;
168
 
   QIntDictIterator<Entry> it(*entryDict);
 
169
   Q3IntDict<Entry> dupeDict;
 
170
   Q3IntDictIterator<Entry> it(*entryDict);
169
171
   for(;it.current();)
170
172
   {
171
173
      Entry *entry = it.current();
244
246
 
245
247
void lookupUnknownSymbols(const char *appname)
246
248
{
247
 
   KTempFile inputFile;
248
 
   KTempFile outputFile;
249
 
   inputFile.setAutoDelete(true);
250
 
   outputFile.setAutoDelete(true);
251
 
   FILE *fInputFile = inputFile.fstream();
252
 
   QIntDict<char> oldDict = *symbolDict;
253
 
   QIntDictIterator<char> it(oldDict);
 
249
   KTemporaryFile inputFile;
 
250
   KTemporaryFile outputFile;
 
251
   inputFile.open();
 
252
   outputFile.open();
 
253
   QTextStream str ( &inputFile );
 
254
   Q3IntDict<char> oldDict = *symbolDict;
 
255
   Q3IntDictIterator<char> it(oldDict);
254
256
   for(;it.current(); ++it)
255
257
   {
256
 
       fprintf(fInputFile, "%08lx\n", it.currentKey());
 
258
       QString temp;
 
259
       temp.sprintf("%08lx\n", it.currentKey());
 
260
       str << temp;
257
261
   }
258
 
   inputFile.close();
259
 
   QCString command;
 
262
   str.flush();
 
263
   Q3CString command;
260
264
   command.sprintf("addr2line -e %s -f -C -s < %s > %s", appname,
261
 
        QFile::encodeName(KProcess::quote(inputFile.name())).data(),
262
 
        QFile::encodeName(KProcess::quote(outputFile.name())).data());
 
265
        QFile::encodeName(KShell::quoteArg(inputFile.fileName())).data(),
 
266
        QFile::encodeName(KShell::quoteArg(outputFile.fileName())).data());
263
267
   system(command.data());
264
 
   fInputFile = fopen(QFile::encodeName(outputFile.name()), "r");
 
268
   FILE *fInputFile = fopen(QFile::encodeName(outputFile.fileName()), "r");
265
269
   if (!fInputFile)
266
270
   {
267
271
      fprintf(stderr, "Error opening temp file.\n");
268
272
      return;
269
273
   }
270
 
   QIntDictIterator<char> it2(oldDict);
 
274
   Q3IntDictIterator<char> it2(oldDict);
271
275
   char buffer1[1024];
272
276
   char buffer2[1024];
273
277
   for(;it2.current(); ++it2)
282
286
      if (!fgets(buffer2, 1023, fInputFile)) continue;
283
287
      buffer1[strlen(buffer1)-1]=0;
284
288
      buffer2[strlen(buffer2)-1]=0;
285
 
      QCString symbol;
 
289
      Q3CString symbol;
286
290
      symbol.sprintf("%s(%s)", buffer2, buffer1);
287
291
      if(*buffer1 != '?')
288
292
          symbolDict->replace(it2.currentKey(),qstrdup(symbol.data()));
310
314
{
311
315
   char *str = formatDict->find(addr);
312
316
   if (str) return str;
313
 
   QCString s = symbolDict->find(addr);
 
317
   QByteArray s = symbolDict->find(addr);
314
318
   if (s.isEmpty())
315
319
   {
316
320
fprintf(stderr, "Error!\n");
324
328
        end = s.findRev(')');
325
329
     if ((start > 0) && (end > start))
326
330
     {
327
 
       QCString symbol = s.mid(start+1, end-start-1);
 
331
       QByteArray symbol = s.mid(start+1, end-start-1);
328
332
       char *res = 0;
329
333
       if (symbol.find(')') == -1)
330
334
           res = cplus_demangle(symbol.data(), DMGL_PARAMS | DMGL_AUTO | DMGL_ANSI );
390
394
   int address;                 // backtrace
391
395
   int total_size;
392
396
   int total_count;
393
 
   typedef QValueList < TreeEntry > TreeList;
 
397
   typedef Q3ValueList < TreeEntry > TreeList;
394
398
   TreeList *subentries () const;
395
399
   mutable TreeList *_subentries;
396
400
   TreeEntry (int adr = 0, int size = 0, int count = 0, TreeList * sub = NULL );
398
402
   bool operator < (const TreeEntry &) const;
399
403
};
400
404
 
401
 
typedef QValueList < TreeEntry > TreeList;
 
405
typedef Q3ValueList < TreeEntry > TreeList;
402
406
 
403
407
inline TreeEntry::TreeEntry (int adr, int size, int count, TreeList * sub)
404
408
 : address (adr), total_size (size), total_count (count), _subentries (sub)
523
527
      dumpTree (*it, 0, indent, file);
524
528
}
525
529
 
526
 
void createTree (const QCString & treefile, int threshold, int maxdepth)
 
530
void createTree (const QString & treefile, int threshold, int maxdepth)
527
531
{
528
 
   FILE * file = fopen (treefile, "w");
 
532
   FILE * file = fopen (treefile.toLocal8Bit(), "w");
529
533
   if (file == NULL)
530
534
   {
531
535
      fprintf (stderr, "Can't write tree file.\n");
558
562
   excludes->sort();
559
563
}
560
564
 
561
 
static KCmdLineOptions options[] =
562
 
{
563
 
  { "x", 0, 0 },
564
 
  { "exclude <file>", "File containing symbols to exclude from output", 0},
565
 
  { "e", 0, 0 },
566
 
  { "exe <file>", "Executable to use for looking up unknown symbols", 0},
567
 
  { "+<trace-log>", "Log file to investigate", 0},
568
 
  {"t", 0, 0},
569
 
  {"tree <file>", "File to write allocations tree", 0},
570
 
  {"th", 0, 0},
571
 
  {"treethreshold <value>",
572
 
    "Don't print subtrees which allocated less than <value> memory", 0},
573
 
  {"td", 0, 0},
574
 
  {"treedepth <value>",
575
 
    "Don't print subtrees that are deeper than <value>", 0},
576
 
  KCmdLineLastOption
577
 
};
578
 
 
579
565
int main(int argc, char *argv[])
580
566
{
581
 
  KInstance instance("kmtrace");
582
 
 
583
 
  KCmdLineArgs::init(argc, argv, "kmtrace", "KDE Memory leak tracer", "v1.0");
 
567
  KComponentData componentData("kmtrace");
 
568
 
 
569
  KCmdLineArgs::init(argc, argv, "kmtrace", 0, ki18n("kmtrace"), "v1.0", ki18n("KDE Memory leak tracer"));
 
570
 
 
571
 
 
572
  KCmdLineOptions options;
 
573
 
 
574
  options.add("x");
 
575
 
 
576
  options.add("exclude <file>", ki18n("File containing symbols to exclude from output"));
 
577
 
 
578
  options.add("e");
 
579
 
 
580
  options.add("exe <file>", ki18n("Executable to use for looking up unknown symbols"));
 
581
 
 
582
  options.add("+<trace-log>", ki18n("Log file to investigate"));
 
583
 
 
584
  options.add("t");
 
585
 
 
586
  options.add("tree <file>", ki18n("File to write allocations tree"));
 
587
 
 
588
  options.add("th");
 
589
 
 
590
  options.add("treethreshold <value>", ki18n("Do not print subtrees which allocated less than <value> memory"));
 
591
 
 
592
  options.add("td");
 
593
 
 
594
  options.add("treedepth <value>", ki18n("Do not print subtrees that are deeper than <value>"));
584
595
 
585
596
  KCmdLineArgs::addCmdLineOptions(options);
586
597
 
589
600
  (void) args->count();
590
601
  const char *logfile;
591
602
  if(args->count())
592
 
    logfile = args->arg(0);
 
603
    logfile = args->arg(0).toLocal8Bit();
593
604
  else
594
605
    logfile = "ktrace.out";
595
606
 
596
 
  QCString exe = args->getOption("exe");
597
 
  QCString exclude;
598
 
 
599
 
  excludes = new QStrList;
600
 
 
601
 
  exclude = QFile::encodeName(locate("data", "kmtrace/kde.excludes"));
 
607
  QString exe = args->getOption("exe");
 
608
  QByteArray exclude;
 
609
 
 
610
  excludes = new Q3StrList;
 
611
 
 
612
  exclude = QFile::encodeName(KStandardDirs::locate("data", "kmtrace/kde.excludes"));
602
613
  if(!exclude.isEmpty())
603
614
      readExcludeFile(exclude);
604
615
 
605
 
  exclude = args->getOption("exclude");
 
616
  exclude = args->getOption("exclude").toLocal8Bit().data();
606
617
  if (!exclude.isEmpty())
607
618
  {
608
619
     fprintf(stderr, "Reading %s\n", exclude.data());
616
627
     exit(1);
617
628
  }
618
629
 
619
 
  entryDict = new QIntDict<Entry>(9973);
620
 
  symbolDict = new QIntDict<char>(9973);
621
 
  formatDict = new QIntDict<char>(9973);
622
 
  entryList = new QSortedList<Entry>;
 
630
  entryDict = new Q3IntDict<Entry>(9973);
 
631
  symbolDict = new Q3IntDict<char>(9973);
 
632
  formatDict = new Q3IntDict<char>(9973);
 
633
  entryList = new Q3SortedList<Entry>;
623
634
 
624
635
  fprintf(stderr, "Running\n");
625
 
  QCString line;
 
636
  QString line;
626
637
  char line2[1024];
627
638
  while(!feof(stream))
628
639
  {
636
647
     }
637
648
     else if (line2[0] == '#')
638
649
     {
639
 
       QCString app(line2+1);
 
650
       QByteArray app(line2+1);
640
651
       if(exe.isEmpty())
641
652
       {
642
 
         exe = app.stripWhiteSpace();
 
653
         exe = app.trimmed();
643
654
         fprintf(stderr, "ktrace.out: malloc trace of %s\n", exe.data());
644
655
       }
645
 
       else if(!app.contains(exe.data()))
 
656
       else if(!app.contains(exe.toLocal8Bit().data()))
646
657
       {
647
658
         fprintf(stderr, "trace file was for application '%s', not '%s'\n", app.data(), exe.data());
648
659
         exit(1);
649
660
       }
650
661
     }
651
662
     else if (line2[0] == '@')
652
 
        line = 0;
 
663
        line = QString();
653
664
     else if (line2[0] == '[')
654
665
        line = line + ' ' + line2;
655
666
     else if (line2[0] == '+')
657
668
        allocCount++;
658
669
        line = line + ' ' + line2;
659
670
        parseLine(line, '+');
660
 
        line = 0;
 
671
        line = QString();
661
672
        if (allocCount & 128)
662
673
        {
663
674
           fprintf(stderr, "\rTotal long term allocs: %d still allocated: %d   ", allocCount, entryDict->count());
667
678
     {
668
679
        line = line + ' ' + line2;
669
680
        parseLine(line, '-');
670
 
        line = 0;
 
681
        line = QString();
671
682
     }
672
683
     else if (line2[0] == '<')
673
684
     {
674
685
        line2[0] = '-';
675
686
        // First part of realloc (free)
676
 
        QCString reline = line + ' ' + line2;
 
687
        QString reline = line + ' ' + line2;
677
688
        parseLine(reline, '-');
678
689
     }
679
690
     else if (line2[0] == '>')
682
693
        // Second part of realloc (alloc)
683
694
        line = line + ' ' + line2;
684
695
        parseLine(line, '+');
685
 
        line = 0;
 
696
        line = QString();
686
697
     }
687
698
     else
688
699
     {
689
 
        char *addr = index(line2,'[');
 
700
        const char *addr = index(line2,'[');
690
701
        if (addr)
691
702
        {
692
 
           line = line + ' ' + addr;
 
703
           line = line + QChar(' ') + addr;
693
704
        }
694
705
     }
695
706
  }
706
717
  rewind(stream);
707
718
  lookupSymbols(stream);
708
719
  fprintf(stderr, "Looking up unknown symbols...\n");
709
 
  lookupUnknownSymbols(exe);
 
720
  lookupUnknownSymbols(exe.toLocal8Bit());
710
721
  fprintf(stderr, "Printing...\n");
711
722
  dumpBlocks();
712
 
  QCString treeFile = args->getOption ("tree");
 
723
  QString treeFile = args->getOption ("tree");
713
724
  if (!treeFile.isEmpty ())
714
725
  {
715
726
      fprintf (stderr, "Creating allocation tree...\n");