You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
5.2 KiB
239 lines
5.2 KiB
#!/usr/bin/perl
|
|
#
|
|
# Copyright (c) 2004
|
|
# Author: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
|
|
#
|
|
# op2calltree is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public
|
|
# License as published by the Free Software Foundation, version 2.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; see the file COPYING. If not, write to
|
|
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
# Boston, MA 02110-1301, USA.
|
|
#
|
|
#
|
|
# Converter from OProfile's output of "opreport -gdf" (v 0.8)
|
|
# into callgrind format.
|
|
#
|
|
# Generate a OProfile report with opreport and flags -gdf
|
|
# and pipe this as standard input into this script.
|
|
# This will generate separate cachegrind files for every application.
|
|
#
|
|
|
|
|
|
# parse symbol line. example (with 1 event type, $has_image==0):
|
|
# 308 0.1491 /path/source.c:6 /path/app main
|
|
sub parseSymSpec {
|
|
$e = 0;
|
|
while($e < $eventCount) {
|
|
($line) = ($line =~ /\d+\s+\S+\s+(.*)/);
|
|
$e++;
|
|
}
|
|
if ($line =~ s/^\(no location information\)\s+//) {
|
|
$file = "???";
|
|
$linenr = 0;
|
|
}
|
|
else {
|
|
($file,$linenr) = ($line =~ s/(\S+?):(\d+)\s+//);
|
|
}
|
|
if ($has_image) {
|
|
if ($line =~ s/^(\S+)\s+//) { $img = $1; }
|
|
}
|
|
if ($has_app) {
|
|
if ($line =~ s/^(\S+)\s+//) { $app = $1; }
|
|
if (!$has_image) { $img = $app; }
|
|
}
|
|
$sym = $line;
|
|
|
|
$app =~ s/^.*\///;
|
|
if ($sym eq "(no symbols)") { $sym = "???"; }
|
|
$file{$sym} = $file;
|
|
$linenr{$sym} = $linenr;
|
|
$app{$sym} = $app;
|
|
$img{$app,$sym} = $img;
|
|
$syms{$app}++;
|
|
|
|
if ($app ne $oldApp) {
|
|
$oldApp = $app;
|
|
print "\n\nApp $app\n";
|
|
}
|
|
print " Symbol $sym (Image $img)\n";
|
|
}
|
|
|
|
|
|
|
|
$eventCount = 0;
|
|
$descCount = 0;
|
|
$lnr = 0;
|
|
$has_image = 0;
|
|
$has_app = 0;
|
|
$app = "unnamed";
|
|
$img = "???";
|
|
|
|
# first loop till first symbol specification
|
|
while(<>) {
|
|
$lnr++;
|
|
chomp;
|
|
if (/^CPU:/) {
|
|
$desc[$descCount++] = $_;
|
|
next;
|
|
}
|
|
if (/^Counted\s*(\S+)/) {
|
|
$desc[$descCount++] = $_;
|
|
$eventCount++;
|
|
$events[$eventCount] = $1;
|
|
next;
|
|
}
|
|
if (/^(Profiling through timer.*)/) {
|
|
$desc[$descCount++] = $_;
|
|
$eventCount++;
|
|
$events[$eventCount] = "Timer";
|
|
next;
|
|
}
|
|
if (/^vma/) {
|
|
# title row: adapt to separation options of OProfile
|
|
if (/image/) { $has_image = 1; }
|
|
if (/app/) { $has_app = 1; }
|
|
next;
|
|
}
|
|
if (/^([0-9a-fA-F]+)\s*(.*)$/) {
|
|
$vmaSym = $1;
|
|
$line = $2;
|
|
last;
|
|
}
|
|
}
|
|
|
|
if ($eventCount == 0) {
|
|
die "No Events found";
|
|
}
|
|
|
|
print "Description:\n";
|
|
foreach $d (@desc) { print " $d\n"; }
|
|
print "\n";
|
|
|
|
print "Events:";
|
|
foreach $e (@events) { print " $e"; }
|
|
print "\n";
|
|
|
|
parseSymSpec;
|
|
|
|
while(<>) {
|
|
$lnr++;
|
|
if (/^([0-9a-fA-F]+)\s*(.*)$/) {
|
|
$vmaSym = $1;
|
|
$line = $2;
|
|
|
|
parseSymSpec;
|
|
next;
|
|
}
|
|
if (/^\s+([0-9a-fA-F]+)\s*(.*)$/) {
|
|
|
|
$sampleCount{$app,$sym}++;
|
|
$sc = $sampleCount{$app,$sym};
|
|
|
|
$vma{$app,$sym,$sc} = $1;
|
|
$line = $2;
|
|
|
|
$e = 1;
|
|
while($e <= $eventCount) {
|
|
($cost, $line) = ($line =~ /(\d+)\s+\S+\s+(.*)/);
|
|
$summary{$app,$e} += $cost;
|
|
$cost{"$app,$sym,$sc,$e"} = $cost;
|
|
$e++;
|
|
}
|
|
if ($line =~ /\(no location information\)/) {
|
|
$file = "???";
|
|
$linenr = 0;
|
|
}
|
|
else {
|
|
($file,$linenr) = ($line =~ /(\S+?):(\d+)/);
|
|
}
|
|
$sFile{$app,$sym,$sc} = $file;
|
|
$linenr{$app,$sym,$sc} = $linenr;
|
|
|
|
$file =~ s/^.*\///;
|
|
print " Sample $sc: $vma{$app,$sym,$sc} ($file:$linenr):";
|
|
foreach $e (1 .. $eventCount) { $c = $cost{"$app,$sym,$sc,$e"} ; print " $c"; }
|
|
print "\n";
|
|
next;
|
|
}
|
|
die "ERROR: Reading line $lnr '$_'\n";
|
|
}
|
|
|
|
foreach $app (keys %syms) {
|
|
if ($app eq "") { next; }
|
|
print "Generating dump for App '$app'...\n";
|
|
|
|
$out = "# Generated by op2cg, using OProfile with opreport -gdf\n";
|
|
$out .= "positions: instr line\n";
|
|
|
|
$out .= "events:";
|
|
foreach $e (@events) { $out .= " $e"; }
|
|
$out .= "\n";
|
|
|
|
$out .= "summary:";
|
|
foreach $e (1 .. $eventCount) { $out .= " $summary{$app,$e}"; }
|
|
$out .= "\n\n";
|
|
|
|
%fileNum = ();
|
|
$fileNum = 1;
|
|
$sf = "";
|
|
|
|
$img = "";
|
|
|
|
foreach $sym (keys %file) {
|
|
if ($sampleCount{$app,$sym} eq "") { next; }
|
|
|
|
if ($img{$app,$sym} ne $img) {
|
|
$img = $img{$app,$sym};
|
|
$out .= "ob=$img\n";
|
|
}
|
|
|
|
$file = $file{$sym};
|
|
if ($sf ne $file) {
|
|
if ($fileNum{$file} eq "") {
|
|
$fileNum{$file} = $fileNum;
|
|
$out .= "fl=($fileNum) $file\n";
|
|
$fileNum++;
|
|
}
|
|
else {
|
|
$out .= "fl=($fileNum{$file})\n";
|
|
}
|
|
$sf = $file;
|
|
}
|
|
|
|
$out .= "fn=$sym\n";
|
|
foreach $sc (1 .. $sampleCount{$app,$sym}) {
|
|
if ($sf ne $sFile{$app,$sym,$sc}) {
|
|
$sf = $sFile{$app,$sym,$sc};
|
|
if ($sf eq $file) {
|
|
$out .= "fe=($fileNum{$file})\n";
|
|
}
|
|
else {
|
|
if ($fileNum{$sf} eq "") {
|
|
$fileNum{$sf} = $fileNum;
|
|
$out .= "fi=($fileNum) $sf\n";
|
|
$fileNum++;
|
|
}
|
|
else {
|
|
$out .= "fi=($fileNum{$sf})\n";
|
|
}
|
|
}
|
|
}
|
|
$out .= "0x$vma{$app,$sym,$sc} $linenr{$app,$sym,$sc}";
|
|
foreach $e (1 .. $eventCount) { $c = $cost{"$app,$sym,$sc,$e"} ; $out .= " $c"; }
|
|
$out .= "\n";
|
|
}
|
|
}
|
|
|
|
open OUT, ">oprof.out.$app";
|
|
print OUT $out;
|
|
close OUT;
|
|
}
|