📄 vglog.cpp
字号:
/* --------------------------------------------------------------------- * Implementation of VgLog vglog.cpp * VgLog: QDomDocument based representation of a valgrind xml log. * --------------------------------------------------------------------- * This file is part of Valkyrie, a front-end for Valgrind * Copyright (c) 2000-2006, OpenWorks LLP <info@open-works.co.uk> * This program is released under the terms of the GNU GPL v.2 * See the file LICENSE.GPL for the full license details. */#include "vglog.h"#include <qtextstream.h>#include <assert.h>/* different implementations for valkyrie/vk_logmerge */extern void vklmPrint( int verb, const char* msg, ... ) __attribute__((format (printf, 2, 3)));extern void vklmPrintErr( const char* msg, ... ) __attribute__((format (printf, 1, 2)));/**********************************************************************//* setup static class maps - avoids setting up map in class cons, but keeps map where it belongs*/VgElement::ElemTypeMap setupElemTypeMap() { VgElement::ElemTypeMap etmap; etmap["valgrindoutput"] = VgElement::ROOT; etmap["protocolversion"] = VgElement::PROTOCOL; etmap["preamble"] = VgElement::PREAMBLE; etmap["pid"] = VgElement::PID; etmap["ppid"] = VgElement::PPID; etmap["tool"] = VgElement::TOOL; etmap["logfilequalifier"] = VgElement::LOGQUAL; etmap["var"] = VgElement::VAR; etmap["value"] = VgElement::VALUE; etmap["usercomment"] = VgElement::COMMENT; etmap["args"] = VgElement::ARGS; etmap["vargv"] = VgElement::VARGV; etmap["argv"] = VgElement::ARGV; etmap["exe"] = VgElement::EXE; etmap["arg"] = VgElement::ARG; etmap["status"] = VgElement::STATUS; etmap["state"] = VgElement::STATE; etmap["time"] = VgElement::TIME; etmap["error"] = VgElement::ERROR; etmap["unique"] = VgElement::UNIQUE; etmap["tid"] = VgElement::TID; etmap["kind"] = VgElement::KIND; etmap["what"] = VgElement::WHAT; etmap["stack"] = VgElement::STACK; etmap["frame"] = VgElement::FRAME; etmap["ip"] = VgElement::IP; etmap["obj"] = VgElement::OBJ; etmap["fn"] = VgElement::FN; etmap["dir"] = VgElement::SRCDIR; etmap["file"] = VgElement::SRCFILE; etmap["line"] = VgElement::LINE; etmap["auxwhat"] = VgElement::AUXWHAT; etmap["errorcounts"] = VgElement::ERRORCOUNTS; etmap["pair"] = VgElement::PAIR; etmap["count"] = VgElement::COUNT; etmap["suppcounts"] = VgElement::SUPPCOUNTS; etmap["name"] = VgElement::NAME; etmap["leakedbytes"] = VgElement::LEAKEDBYTES; etmap["leakedblocks"] = VgElement::LEAKEDBLOCKS; return etmap;}VgElement::ElemTypeMap VgElement::elemtypeMap = setupElemTypeMap();VgError::LeakKindMap setupLeakKindMap() { VgError::LeakKindMap lkmap; lkmap["Leak_DefinitelyLost"] = VgError::UNREACHED; lkmap["Leak_IndirectlyLost"] = VgError::INDIRECT; lkmap["Leak_PossiblyLost"] = VgError::INTERIOR; lkmap["Leak_StillReachable"] = VgError::PROPER; return lkmap;}VgError::LeakKindMap VgError::leakKindMap = setupLeakKindMap();/**********************************************************************//* Search direct children for first/last element of 'tagname'*/VgElement VgElement::getFirstElem( QString tagname ) const{ // vklmPrintErr("getFirstElem(): %s", tagname.latin1()); QDomElement e; for ( e = firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() ) { // vklmPrintErr(" - %s",e.tagName().latin1()); if (e.tagName() == tagname) return (VgElement&)e; } return VgElement();}VgElement VgElement::getLastElem( QString tagname ) const{ QDomElement e; for ( e = lastChild().toElement(); !e.isNull(); e = e.previousSibling().toElement() ) { if (e.tagName() == tagname) return (VgElement&)e; } return VgElement();}VgElement::ElemType VgElement::elemType(){ ElemTypeMap::Iterator it = elemtypeMap.find( tagName() ); if ( it == elemtypeMap.end() ) return VgElement::NUM_ELEMS; return it.data(); }/* Convert leaf element content to integer. Returns 0 if conversion fails*/unsigned long VgElement::toULong( bool* ok ){ if (!isLeaf()) { *ok = false; return 0; } QDomText textNode = firstChild().toText(); if (textNode.isNull()) { *ok = false; return 0; } QString numStr = textNode.data(); unsigned long num = numStr.toULong(ok); if (!ok) { *ok = false; return 0; } return num;}/* Sets content for a leaf element*/bool VgElement::setContent( QString content ){ if (!isLeaf()) return false; QDomText textNode = firstChild().toText(); if (textNode.isNull()) return false; textNode.setData( content ); return true;}/* Gets content for a leaf element*/QString VgElement::getContent(){ if (!isLeaf()) return ""; QDomText textNode = firstChild().toText(); if (textNode.isNull()) return ""; return textNode.data();}/* add slave elem count to this count*/bool VgElement::updateCount( VgElement sElemNum ){ if (!isLeaf()) return false; bool ok; unsigned long mNum = toULong( &ok ); if (!ok) return false; unsigned long sNum = sElemNum.toULong( &ok ); if (!ok) return false; if (!setContent( QString::number( mNum + sNum ) ) ) return false; return true;}bool VgElement::isLeaf(){ return ( (childNodes().count() == 1) && (firstChild().childNodes().count() == 0) );}/**********************************************************************/QString VgPreamble::toPlainTxt(){ QString output_str; for ( QDomNode n=firstChild(); !n.isNull(); n=n.nextSibling() ) { output_str += n.toElement().text() + "\n"; } return output_str;}/**********************************************************************//* "", "RUNNING", "FINISHED" */VgStatus::StateType VgStatus::state(){ QDomElement n_state = firstChild().toElement(); if (n_state.isNull()) return INIT; if (n_state.text() == "RUNNING") return RUNNING; return FINISHED;}/**********************************************************************/bool VgFrame::operator==( const VgFrame& frame2 ) const{ QDomNodeList frame_details1 = childNodes(); assert( frame_details1.count() >= 1 ); /* only ip guaranteed */ QDomElement iptr1 = frame_details1.item( 0 ).toElement(); QDomElement objt1 = frame_details1.item( 1 ).toElement(); QDomElement func1 = frame_details1.item( 2 ).toElement(); QDomElement diry1 = frame_details1.item( 3 ).toElement(); QDomElement file1 = frame_details1.item( 4 ).toElement(); QDomElement line1 = frame_details1.item( 5 ).toElement(); QDomNodeList frame_details2 = frame2.childNodes(); assert( frame_details2.count() >= 1 ); /* only ip guaranteed */ QDomElement iptr2 = frame_details2.item( 0 ).toElement(); QDomElement objt2 = frame_details2.item( 1 ).toElement(); QDomElement func2 = frame_details2.item( 2 ).toElement(); QDomElement diry2 = frame_details2.item( 3 ).toElement(); QDomElement file2 = frame_details2.item( 4 ).toElement(); QDomElement line2 = frame_details2.item( 5 ).toElement(); /* a frame may be the 'same' as another even if it is missing some data - do the best comparison we can */ /* only field guaranteed to be present is 'ip'. comparing 'ip' is dodgy, so we try our hardest not to. */ /* A: test fields: 'dir', 'file', 'line' */ if ( !diry1.isNull() && !diry2.isNull() && !file1.isNull() && !file2.isNull() && !line1.isNull() && !line2.isNull() ) { vklmPrint( 3, "frame test A: dir, file, line" ); if (diry1.text() != diry2.text() || file1.text() != file2.text() || line1.text() != line2.text()) return false; return true; } /* B: test fields: 'file', 'line' */ if ( !file1.isNull() && !file2.isNull() && !line1.isNull() && !line2.isNull() ) { vklmPrint( 3, "frame test B: file, line" ); if (file1.text() != file2.text() || line1.text() != line2.text()) return false; return true; } /* C: test fields: 'fn', 'ip' */ if ( !func1.isNull() && !func2.isNull() ) { vklmPrint( 3, "frame test C: func, ip" ); if (func1.text() != func2.text() || iptr1.text() != iptr2.text()) return false; return true; } /* D: test field: 'ip' */ vklmPrint( 3, "frame test D: ip only" ); if (iptr1.text() != iptr2.text()) return false; return true;}bool VgFrame::operator!=( const VgFrame& frame2 ) const{ return !operator==(frame2);}/* ref: coregrind/m_debuginfo/symtab.c :: VG_(describe_IP) *//* CAB: why don't print dirname for non-xml ? */QString VgFrame::describe_IP( bool withPath/*=false*/ ){ QDomNodeList frame_details = childNodes(); assert( frame_details.count() >= 1 ); /* only ip guaranteed */ QDomElement ip = frame_details.item( 0 ).toElement(); QDomElement obj = frame_details.item( 1 ).toElement(); QDomElement fn = frame_details.item( 2 ).toElement(); QDomElement dir = frame_details.item( 3 ).toElement(); QDomElement srcloc = frame_details.item( 4 ).toElement(); QDomElement line = frame_details.item( 5 ).toElement(); bool know_fnname = !fn.isNull(); bool know_objname = !obj.isNull(); bool know_srcloc = !srcloc.isNull() && !line.isNull(); bool know_dirinfo = !dir.isNull(); QString str = ip.text() + ": "; if (know_fnname) { str += fn.text(); if (!know_srcloc && know_objname) str += " (in " + obj.text() + ")"; } else if (know_objname && !know_srcloc) { str += "(within " + obj.text() + ")"; } else { str += "???"; } if (know_srcloc) { QString path; if ( withPath && know_dirinfo ) path = dir.text() + "/"; path += srcloc.text(); str += " (" + path + ":" + line.text() + ")"; } return str;}/**********************************************************************/bool VgError::isLeak(){ QString kind = getFirstElem( "kind" ).text(); return kind.startsWith( "Leak_" );}QString VgError::toPlainTxt(){ if (firstChild().isNull()) return ""; QString output_str; QDomNode n = firstChild(); for ( QDomNode n=firstChild(); !n.isNull(); n=n.nextSibling() ) { QDomElement e = n.toElement(); if (e.tagName() == "what") { output_str += e.text() + "\n"; } else if (e.tagName() == "stack") { QDomNode frame = e.firstChild(); for ( ; !frame.isNull(); frame=frame.nextSibling() ) { QString ip_desc = ((VgFrame&)frame).describe_IP(); QString pre = (frame == e.firstChild()) ? " at " : " by "; output_str += pre + ip_desc + "\n"; } } else if (e.tagName() == "auxwhat") { output_str += " " + e.text() + "\n"; } } output_str += "\n"; return output_str;}bool VgError::operator==( const VgError& err2 ) const{#define MAX_FRAMES_COMPARE 4 QDomElement kind1 = getFirstElem( "kind" ); QDomElement kind2 = err2.getFirstElem( "kind" ); /* test #1: is the 'kind' the same */ if (kind1.text() != kind2.text()) { vklmPrint( 3, "=> different error kind" ); return false; } /* - one stack per error */ QDomElement stack1 = getFirstElem( "stack" ); QDomElement stack2 = err2.getFirstElem( "stack" ); /* - one or more frames per stack */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -