#!/usr/bin/perl # # Copyright (c) 2004 # Author: Josef Weidendorfer # # 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; }