Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/tools/runonphone/trksignalhandler.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include <QCoreApplication>
    4444#include <QObject>
     45#include <QFile>
     46#include <QDir>
    4547#include "trksignalhandler.h"
     48#include "trkutils.h"
     49
     50class CrashState
     51{
     52public:
     53    uint pid;
     54    uint tid;
     55    QString crashReason;
     56    uint crashPC;
     57};
    4658
    4759class TrkSignalHandlerPrivate
     
    5567    QTextStream err;
    5668    int loglevel;
     69    int lastpercent;
     70    QList<trk::Library> libraries;
     71    QFile crashlogtextfile;
     72    QFile crashstackfile;
     73    QList<CrashState> queuedCrashes;
     74    QList<int> dyingThreads;
     75    QString crashlogPath;
     76    bool crashlog;
     77    bool terminateNeeded;
    5778};
    5879
     
    108129void TrkSignalHandler::applicationRunning(uint pid)
    109130{
     131    Q_UNUSED(pid)
    110132    if (d->loglevel > 0)
    111133        d->out << "Running..." << endl;
     
    132154{
    133155    if (d->loglevel > 0) {
    134         d->out << percent << "% ";
     156        if (d->lastpercent == 0)
     157            d->out << "[                                                 ]\r[" << flush;
     158        while (percent > d->lastpercent) {
     159            d->out << QLatin1Char('#');
     160            d->lastpercent+=2; //because typical console is 80 chars wide
     161        }
    135162        d->out.flush();
    136163        if (percent==100)
     
    150177}
    151178
     179void TrkSignalHandler::setCrashLogging(bool enabled)
     180{
     181    d->crashlog = enabled;
     182}
     183
     184void TrkSignalHandler::setCrashLogPath(QString path)
     185{
     186    d->crashlogPath = path;
     187}
     188
     189bool lessThanCodeBase(const trk::Library& cs1, const trk::Library& cs2)
     190{
     191    return cs1.codeseg < cs2.codeseg;
     192}
     193
    152194void TrkSignalHandler::stopped(uint pc, uint pid, uint tid, const QString& reason)
    153195{
    154196    d->err << "STOPPED: pc=" << hex << pc << " pid=" << pid
    155197           << " tid=" << tid << dec << " - " << reason << endl;
    156     // if it was a breakpoint, then we could continue with "emit resume(pid, tid);"
    157     // since we have set no breakpoints, it will be a just in time debug of a panic / exception
    158     emit terminate();
     198
     199    if (d->crashlog) {
     200        CrashState cs;
     201        cs.pid = pid;
     202        cs.tid = tid;
     203        cs.crashPC = pc;
     204        cs.crashReason = reason;
     205
     206        if (d->dyingThreads.contains(tid)) {
     207            if(d->queuedCrashes.isEmpty())
     208                emit terminate();
     209            else
     210                d->terminateNeeded = true;
     211        } else {
     212            d->queuedCrashes.append(cs);
     213            d->dyingThreads.append(tid);
     214
     215            if (d->queuedCrashes.count() == 1) {
     216                d->err << "Fetching registers and stack..." << endl;
     217                emit getRegistersAndCallStack(pid, tid);
     218            }
     219        }
     220    }
     221    else
     222        emit terminate();
     223}
     224
     225void TrkSignalHandler::registersAndCallStackReadComplete(const QList<uint>& registers, const QByteArray& stack)
     226{
     227    CrashState cs = d->queuedCrashes.first();
     228    QDir dir(d->crashlogPath);
     229    d->crashlogtextfile.setFileName(dir.filePath(QString("d_exc_%1.txt").arg(cs.tid)));
     230    d->crashstackfile.setFileName(dir.filePath(QString("d_exc_%1.stk").arg(cs.tid)));
     231    d->crashlogtextfile.open(QIODevice::WriteOnly);
     232    QTextStream crashlog(&d->crashlogtextfile);
     233
     234    crashlog << "-----------------------------------------------------------------------------" << endl;
     235    crashlog << "EKA2 USER CRASH LOG" << endl;
     236    crashlog << "Thread Name: " << QString("ProcessID-%1::ThreadID-%2").arg(cs.pid).arg(cs.tid) << endl;
     237    crashlog << "Thread ID: " << cs.tid << endl;
     238    //this is wrong, but TRK doesn't make stack limit available so we lie
     239    crashlog << QString("User Stack %1-%2").arg(registers.at(13), 8, 16, QChar('0')).arg(registers.at(13) + stack.size(), 8, 16, QChar('0')) << endl;
     240    //this is also wrong, but TRK doesn't give all information for exceptions
     241    crashlog << QString("Panic: PC=%1 ").arg(cs.crashPC, 8, 16, QChar('0')) << cs.crashReason << endl;
     242    crashlog << endl;
     243    crashlog << "USER REGISTERS:" << endl;
     244    crashlog << QString("CPSR=%1").arg(registers.at(16), 8, 16, QChar('0')) << endl;
     245    for (int i=0;i<16;i+=4) {
     246        crashlog << QString("r%1=%2 %3 %4 %5")
     247            .arg(i, 2, 10, QChar('0'))
     248            .arg(registers.at(i), 8, 16, QChar('0'))
     249            .arg(registers.at(i+1), 8, 16, QChar('0'))
     250            .arg(registers.at(i+2), 8, 16, QChar('0'))
     251            .arg(registers.at(i+3), 8, 16, QChar('0')) << endl;
     252    }
     253    crashlog << endl;
     254
     255    //emit info for post mortem debug
     256    qSort(d->libraries.begin(), d->libraries.end(), lessThanCodeBase);
     257    d->err << "Code Segments:" << endl;
     258    crashlog << "CODE SEGMENTS:" << endl;
     259    for(int i=0; i<d->libraries.count(); i++) {
     260        const trk::Library& seg = d->libraries.at(i);
     261        if(seg.pid != cs.pid)
     262            continue;
     263        if (d->loglevel > 1) {
     264            d->err << QString("Code: %1 Data: %2 Name: ")
     265                .arg(seg.codeseg, 8, 16, QChar('0'))
     266                .arg(seg.dataseg, 8, 16, QChar('0'))
     267                << seg.name << endl;
     268        }
     269
     270        //produce fake code segment end addresses since we don't get the real ones from TRK
     271        uint end;
     272        if (i+1 < d->libraries.count())
     273            end = d->libraries.at(i+1).codeseg - 1;
     274        else
     275            end = 0xFFFFFFFF;
     276
     277        crashlog << QString("%1-%2 ")
     278            .arg(seg.codeseg, 8, 16, QChar('0'))
     279            .arg(end, 8, 16, QChar('0'))
     280            << seg.name << endl;
     281    }
     282
     283    d->crashlogtextfile.close();
     284
     285    if (d->loglevel > 1) {
     286        d->err << "Registers:" << endl;
     287        for (int i=0;i<16;i++) {
     288            d->err << QString("R%1: %2 ").arg(i, 2, 10, QChar('0')).arg(registers.at(i), 8, 16, QChar('0'));
     289            if (i % 4 == 3)
     290                d->err << endl;
     291        }
     292        d->err << QString("CPSR: %1").arg(registers.at(16), 8, 16, QChar('0')) << endl;
     293
     294        d->err << "Stack:" << endl;
     295        uint sp = registers.at(13);
     296        for(int i=0; i<stack.size(); i+=16, sp+=16) {
     297            d->err << QString("%1: ").arg(sp, 8, 16, QChar('0'));
     298            d->err << trk::stringFromArray(stack.mid(i,16));
     299            d->err << endl;
     300        }
     301    }
     302    d->crashstackfile.open(QIODevice::WriteOnly);
     303    d->crashstackfile.write(stack);
     304    d->crashstackfile.close();
     305
     306    if (d->loglevel > 0)
     307        d->err << "Crash logs saved to " << d->crashlogtextfile.fileName() << " & " << d->crashstackfile.fileName() << endl;
     308
     309    // resume the thread to allow Symbian OS to handle the panic normally.
     310    // terminate when a non main thread is suspended reboots the phone (TRK bug)
     311    emit resume(cs.pid, cs.tid);
     312
     313    //fetch next crashed thread
     314    d->queuedCrashes.removeFirst();
     315    if (d->queuedCrashes.count()) {
     316        cs = d->queuedCrashes.first();
     317        d->err << "Fetching registers and stack..." << endl;
     318        emit getRegistersAndCallStack(cs.pid, cs.tid);
     319    }
     320    else if (d->terminateNeeded)
     321        emit terminate();
     322
     323}
     324
     325void TrkSignalHandler::libraryLoaded(const trk::Library &lib)
     326{
     327    d->libraries << lib;
     328}
     329
     330void TrkSignalHandler::libraryUnloaded(const trk::Library &lib)
     331{
     332    for (QList<trk::Library>::iterator i = d->libraries.begin(); i != d->libraries.end(); i++) {
     333        if((*i).name == lib.name && (*i).pid == lib.pid)
     334            i = d->libraries.erase(i);
     335    }
    159336}
    160337
     
    168345    : out(stdout),
    169346    err(stderr),
    170     loglevel(0)
     347    loglevel(0),
     348    lastpercent(0),
     349    terminateNeeded(false)
    171350{
    172351
Note: See TracChangeset for help on using the changeset viewer.