📄 anngen
字号:
#!/powderkeg/local/bin/perl5 -w## Copyright (C) 1996-1998 by the Board of Trustees# of Leland Stanford Junior University.# # This file is part of the SimOS distribution. # See LICENSE file for terms of the license. ####### anngen unix annote.def###### Source file annotations:### /*!anote [B|A] [{cond-expr}] <builtin> */### /*!count [B|A] [{cond-expr}] <label> */### /*!begin [B|A] [{cond-expr}] <label> */### /*!end [B|A] [{cond-expr}] <label> */###### Definition file structure:### file: <source file>### func: <function in current srcfile> [{cond-expr}]### fbegin: <function in current srcfile> [{cond-expr}] <builtin>### fend: <function in current srcfile> [{cond-expr}] <builtin>### global: <global symbol> [{cond-expr}] <builtin>######### Defaults:### B|A = B######### Global variables:### $fileinfo : (filename) -> [filenum, PC, seen, inst2line[], funcinfo{}, datainfo{}]### $globalinfo : (global variable) -> PC### $numAnn : number of annotations emitted###%fileinfo = ();%globalinfo = ();## commands that can appear in def file%defCommands = ('file', => ['doFile'], 'global' => ['doGlobal'], 'func' => ['doFunc'], 'fbegin' => ['doFWrapper', 0], 'fend' => ['doFWrapper', 1], ); ## commands that can appear in the source file%srcCommands = ('annote' => ['doGeneral', ''], 'count' => ['doGeneral', 'timing diff '], 'begin' => ['doGeneral', 'timing beg '], 'end' => ['doGeneral', 'timing end '], );$unix = ($ARGV[0]) ? $ARGV[0] : "$ENV{'ROOT'}/usr/sysgen/SIMMPboot/unix.kdebug";$deffile = ($ARGV[1]) ? $ARGV[1] : "annote.def";# $deffile = ($ARGV[1]) ? $ARGV[1] : "$ENV{'ROOT'}/kern/annote.def";###### Initialize symbol information### need a slow one if we miss a function name&initGlobalSymbolInfo;###### For each file search for annotations and process them.###open(DEF, "$deffile") || die "Could not find def file, exiting.";$srcfile = 0;while (<DEF>) { if (/^(\w+):\s*/) { $cmd = $1; $rest = $'; chop($rest); if ($op = $defCommands{$cmd}[0]) { &$op($cmd, $rest); } else { print STDERR "WARNING: possible typo in def file line $., ignored\n$_"; } } elsif (!/^#/ && !/^-/ && /\S/) { print STDERR "WARNING: possible typo in def file line $., ignored\n$_"; }}close(DEF);print STDERR "$numAnn annotations found.\n";exit;###### annotation ops###sub doFile { my($cmd, $rest) = @_; ### ### Change current source file. ### ($rest =~ /(\S+)/) || die "bad file name in def file on line $.\n"; $srcfile = $1; my(@t) = split("/", $srcfile); $fname = pop(@t); ### ### If we have already seen this file, all we need to do is look ### at possible annotations in the def file. ### if ($fileinfo{$fname}[2]) { print STDERR "processing file $srcfile again\n"; return; } print STDERR "processing file $srcfile\n"; ### ### Analyze symbol table info for current source file ### &initSourceSymbolInfo($fname); ### ### Scan the source file for annotations ### open(SRCFILE, "$srcfile") || die "ERROR: Bad file $srcfile\n"; while (<SRCFILE>) { if (m%/\*\!(\w+)\s*([AB]?)\s+({([^}]*)})?\s*(\w+)\s*([^\*]*)\*/%) { $cmd = $1; $beforeOrAfter = $2 || "B"; $cond = $4; $label = $5; $optionalArgs = $6; $linenum = $.; if ($cmd eq "annote") { print STDERR "found annote in source on line $., $label\n"; } ($op = $srcCommands{$cmd}[0]) || die "$srcfile:$linenum, bad command\n$_\n"; &$op($cmd, $beforeOrAfter, $cond, $label, $optionalArgs, $linenum); } elsif (/\/\*(\w+) ([^*]*)\*\//) { print STDERR "WARNING: $srcfile:$., possible typo, ignored\n$_"; } } close(SRCFILE); $fileinfo{$fname}[2] = 1;}sub doGlobal { my($cmd, $rest) = @_; my($symb, $cond, $PC, $builtin); ($rest =~ /(\S+)\s*({([^}]*)})?\s*([^%]*)[%]?/) || die "ERROR: bad line in def file on line $.\n"; $symb = $1; $cond = $3; $builtin = $4; $percentOf = $'; ($PC = $globalinfo{$symb}) || die "ERROR: symbol not found on line $.\n"; emitAnn($PC, $symb, $cond, $builtin, $percentOf);}sub doFunc { my($cmd, $rest) = @_; my($func, $cond, $PC, $offset, $funcinfo); ($rest =~ /(\S+)\s*({([^}]*)})?/) || die "ERROR: bad line in def file on line $.\n"; $func = $1; $cond = $3; $fname || die "ERROR: file must be first command in def file.\n$_"; ($funcinfo = $fileinfo{$fname}[4]{$func}) || die "ERROR: bad function in def file on line $., $func\n"; ## do begining of function stuff first $PC = $fileinfo{$fname}[1] + ($$funcinfo[0]*4); emitAnn($PC, "$func+0", $cond, "timing beg $func", 0); ## now do end of function stuff $offset = 4*($$funcinfo[1] - $$funcinfo[0]); $PC = $fileinfo{$fname}[1] + ($$funcinfo[1]*4); emitAnn($PC, "$func+$offset", $cond, "timing end $func", 0);}sub doFWrapper { my($cmd, $rest) = @_; my($func, $cond, $builtin, $PC, $offset, $begend, $funcinfo); ($rest =~ /(\S+)\s*({([^}]*)})?/) || die "ERROR: bad line in def file on line $.\n"; $func = $1; $cond = $3; $builtin = $'; $fname || die "ERROR: file must be first command in def file.\n$_"; $begend = $defCommands{$cmd}[1]; ($funcinfo = $fileinfo{$fname}[4]{$func}) || die "ERROR: bad function in def file on line $., $func\n"; $offset = 4*($$funcinfo[$begend] - $$funcinfo[0]); $PC = $fileinfo{$fname}[1] + ($$funcinfo[$begend]*4); emitAnn($PC, "$func+$offset", $cond, $builtin, 0);}sub doGeneral { my($cmd, $beforeOrAfter, $cond, $label, $optArgs, $linenum) = @_; my($func, $offset, $PC); if ($beforeOrAfter eq "B") { $offset = &findOffsetBeforeBelowLine($fname, $linenum); } else { $offset = &findOffsetAfterAboveLine($fname, $linenum); } $func = &offset2Function($fname, $offset); $PC = $fileinfo{$fname}[1] + ($offset*4); $offset = 4*($offset - $fileinfo{$fname}[4]{$func}[0]); emitAnn($PC, "$func+$offset", $cond, "$srcCommands{$cmd}[1]"."$label", $optArgs);}sub emitAnn { my($PC, $symb, $cond, $function, $optArgs) = @_; printf("PC %-18s 0x%8x %s%s%s\n", $symb, $PC, $cond ? "{$cond} " : "", $function, $optArgs ? " $optArgs" : ""); $numAnn++;}###### symbol table subroutines###sub initGlobalSymbolInfo { my($file, $PC, $i); print STDERR "Analyzing kernel symbol table.\n"; ## ## First get filename -> filenum ## open(STINFO, "odump -p -F $unix |"); $i = 0; while (<STINFO>) { if (m%([\w\.]+\.[sch])\s*(0x\w+)%) { $file = $1; $PC = oct($2); $fileinfo{$file} = [$i, $PC, 0, [], {}, {}]; $i++; <STINFO>; } elsif ($i==0) { # must be using odump vers 3.18, # it prints a header, just keep going } else { die "BAD read from odump\n$_"; } } close(STINFO); ## ## Now get global variable info ## open(GLOBINFO, "stdump -b $unix |"); while (<GLOBINFO>) { if (/\s*\d+\.\s*\(file\s*\d+\)\s\((\d+)\)\s(\S+)/) { $PC = $1; $symb = $2; $globalinfo{$symb} = $PC; } } close(GLOBINFO);}sub initSourceSymbolInfo { my($fname) = @_; my($startPC, $offset, $symbol, $type, $fnum, $i); $fnum = $fileinfo{$fname}[0]; $startPC = $fileinfo{$fname}[1]; open(SRCINFO, "stdump -chn $fnum $unix |"); ## Phase 1: Parse the symbol information. while (<SRCINFO>) { if (/\s*\d+\.\s*\(\s*\d+\)\(\s*(\S+)\)\s(\S+)\s*(\w+)/) { $offset = $1; $symbol = $2; $type = $3; if (($type eq "Proc") || ($type eq "StaticProc")) { # $offset is function start PC $fileinfo{$fname}[4]{$symbol} = [($offset-$startPC)/4, 0]; } elsif ($type eq "End") { if ($fileinfo{$fname}[4]{$symbol}) { # offset is function length in bytes $fileinfo{$fname}[4]{$symbol}[1] = $fileinfo{$fname}[4]{$symbol}[0] + ($offset/4) - 1; } } elsif ($type eq "Static") { # offset is variable PC $fileinfo{$fname}[5]{$symbol} = $offset; } } elsif (/^Lines:/) { # goto phase 2 last; } } ## Phase 2: Parse the linenum info. my($inst2line, $instnum) = ($fileinfo{$fname}[3], 0); while (<SRCINFO>) { my(@t) = split; $i = 1; while ($i <= $#t) { $$inst2line[$instnum] = $t[$i]; $i += 2; $instnum++; } } close(SRCINFO);}# Find the offset of the first instruction before all instructions# below src linenum have executed.sub findOffsetBeforeBelowLine { my($fname, $linenum) = @_; my($inst2line, $found); $inst2line = $fileinfo{$fname}[3]; for ($i = 0; $i < @$inst2line; $i++) { if ($$inst2line[$i] >= $linenum) { $found = $i; last; } } $found;}# Find the offset of the first instruction after all instructions# above src linenum have executed.sub findOffsetAfterAboveLine { my($fname, $linenum) = @_; my($inst2line, $found); $inst2line = $fileinfo{$fname}[3]; for ($i = $#$inst2line; $i >= 0; $i--) { if ($$inst2line[$i-1] < $linenum) { $found = $i; last; } } $found;}sub offset2Function { my($fname, $offset) = @_; my($funcinfo, $key); $funcinfo = $fileinfo{$fname}[4]; foreach $key (keys(%$funcinfo)) { if (($offset >= $$funcinfo{$key}[0]) && ($offset <= $$funcinfo{$key}[1])) { return $key; } } die "ERROR: bad annotation, line to function.\n";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -