Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Unified Diff: third_party/tcmalloc/chromium/src/pprof

Issue 576001: Merged third_party/tcmalloc/vendor/src(google-perftools r87) into... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removed the unnecessary printf and ASSERT(0) Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/tcmalloc/chromium/src/pagemap.h ('k') | third_party/tcmalloc/chromium/src/profile-handler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/tcmalloc/chromium/src/pprof
===================================================================
--- third_party/tcmalloc/chromium/src/pprof (revision 41942)
+++ third_party/tcmalloc/chromium/src/pprof (working copy)
@@ -72,7 +72,7 @@
use warnings;
use Getopt::Long;
-my $PPROF_VERSION = "1.4";
+my $PPROF_VERSION = "1.5";
# These are the object tools we use which can come from a
# user-specified location using --tools, from the PPROF_TOOLS
@@ -92,6 +92,7 @@
my $PS2PDF = "ps2pdf";
# These are used for dynamic profiles
my $WGET = "wget";
+my $WGET_FLAGS = "--no-http-keep-alive"; # only supported by some wgets
my $CURL = "curl";
# These are the web pages that servers need to support for dynamic profiles
@@ -117,6 +118,11 @@
# A list of paths to search for shared object files
my @prefix_list = ();
+# Special routine name that should not have any symbols.
+# Used as separator to parse "addr2line -i" output.
+my $sep_symbol = '_fini';
+my $sep_address = undef;
+
##### Argument parsing #####
sub usage_string {
@@ -504,6 +510,20 @@
ConfigureObjTools($main::prog)
}
+ # Check what flags our commandline utilities support
+ if (open(TFILE, "$WGET $WGET_FLAGS -V 2>&1 |")) {
+ my @lines = <TFILE>;
+ if (grep(/unrecognized/, @lines) > 0) {
+ # grep found 'unrecognized' token from WGET, clear WGET flags
+ $WGET_FLAGS = "";
+ }
+ close(TFILE);
+ }
+ # TODO(csilvers): check all the other binaries and objtools to see
+ # if they are installed and what flags they support, and store that
+ # in a data structure here, rather than scattering these tests about.
+ # Then, ideally, rewrite code to use wget OR curl OR GET or ...
+
# Break the opt_list_prefix into the prefix_list array
@prefix_list = split (',', $main::opt_lib_prefix);
@@ -952,22 +972,31 @@
print 'binary=', $prog, "\n";
}
while (my ($pc, $name) = each(%{$symbols})) {
- my $fullname = $name->[2];
- print '0x', $pc, ' ', $fullname, "\n";
+ my $sep = ' ';
+ print '0x', $pc;
+ # We have a list of function names, which include the inlined
+ # calls. They are separated (and terminated) by --, which is
+ # illegal in function names.
+ for (my $j = 2; $j <= $#{$name}; $j += 3) {
+ print $sep, $name->[$j];
+ $sep = '--';
+ }
+ print "\n";
}
print '---', "\n";
+ $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $profile_marker = $&;
+ print '--- ', $profile_marker, "\n";
if (defined($main::collected_profile)) {
# if used with remote fetch, simply dump the collected profile to output.
open(SRC, "<$main::collected_profile");
while (<SRC>) {
print $_;
}
+ close(SRC);
} else {
# dump a cpu-format profile to standard out
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
- print '--- ', $profile_marker, "\n";
PrintProfileData($profile);
}
}
@@ -1069,9 +1098,9 @@
}
# Return reference to array of tuples of the form:
-# [address, filename, linenumber, instruction]
+# [start_address, filename, linenumber, instruction, limit_address]
# E.g.,
-# ["0x806c43d", "/foo/bar.cc", 131, "ret"]
+# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"]
sub Disassemble {
my $prog = shift;
my $offset = shift;
@@ -1086,6 +1115,7 @@
my @result = ();
my $filename = "";
my $linenumber = -1;
+ my $last = ["", "", "", ""];
while (<OBJDUMP>) {
s/\r//g; # turn windows-looking lines into unix-looking lines
chop;
@@ -1098,7 +1128,9 @@
# Disassembly line -- zero-extend address to full length
my $addr = HexExtend($1);
my $k = AddressAdd($addr, $offset);
- push(@result, [$k, $filename, $linenumber, $2]);
+ $last->[4] = $k; # Store ending address for previous instruction
+ $last = [$k, $filename, $linenumber, $2, $end_addr];
+ push(@result, $last);
}
}
close(OBJDUMP);
@@ -1274,8 +1306,13 @@
my $total1 = 0; # Total flat counts
my $total2 = 0; # Total cumulative counts
foreach my $e (@instructions) {
- my $c1 = GetEntry($flat, $e->[0]);
- my $c2 = GetEntry($cumulative, $e->[0]);
+ # Add up counts for all address that fall inside this instruction
+ my $c1 = 0;
+ my $c2 = 0;
+ for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
+ $c1 += GetEntry($flat, $a);
+ $c2 += GetEntry($cumulative, $a);
+ }
$running1 += $c1;
$running2 += $c2;
$total1 += $c1;
@@ -1386,8 +1423,13 @@
my $flat_total = 0;
my $cum_total = 0;
foreach my $e (@instructions) {
- my $c1 = GetEntry($flat, $e->[0]);
- my $c2 = GetEntry($cumulative, $e->[0]);
+ # Add up counts for all address that fall inside this instruction
+ my $c1 = 0;
+ my $c2 = 0;
+ for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
+ $c1 += GetEntry($flat, $a);
+ $c2 += GetEntry($cumulative, $a);
+ }
push(@flat_count, $c1);
push(@cum_count, $c2);
$flat_total += $c1;
@@ -1615,10 +1657,10 @@
foreach my $k (keys(%{$raw})) {
# TODO: omit low %age edges
$n = $raw->{$k};
- my @addrs = split(/\n/, $k);
- for (my $i = 1; $i <= $#addrs; $i++) {
- my $src = OutputKey($symbols, $addrs[$i]);
- my $dst = OutputKey($symbols, $addrs[$i-1]);
+ my @translated = TranslateStack($symbols, $k);
+ for (my $i = 1; $i <= $#translated; $i++) {
+ my $src = $translated[$i];
+ my $dst = $translated[$i-1];
#next if ($src eq $dst); # Avoid self-edges?
if (exists($node{$src}) && exists($node{$dst})) {
my $edge_label = "$src\001$dst";
@@ -1648,14 +1690,18 @@
if ($edgeweight > 100000) { $edgeweight = 100000; }
$edgeweight = int($edgeweight);
+ my $style = sprintf("setlinewidth(%f)", $w);
+ if ($x[1] =~ m/\(inline\)/) {
+ $style .= ",dashed";
+ }
+
# Use a slightly squashed function of the edge count as the weight
- printf DOT ("N%s -> N%s [label=%s, weight=%d, " .
- "style=\"setlinewidth(%f)\"];\n",
+ printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n",
$node{$x[0]},
$node{$x[1]},
Unparse($n),
$edgeweight,
- $w);
+ $style);
}
}
@@ -1665,42 +1711,74 @@
return 1;
}
-# Generate the key under which a given address should be counted
-# based on the user-specified output granularity.
-sub OutputKey {
+# Translate a stack of addresses into a stack of symbols
+sub TranslateStack {
my $symbols = shift;
- my $a = shift;
+ my $k = shift;
- # Skip large addresses since they sometimes show up as fake entries on RH9
- if (length($a) > 8) {
- if ($a gt "7fffffffffffffff") { return ''; }
- }
+ my @addrs = split(/\n/, $k);
+ my @result = ();
+ for (my $i = 0; $i <= $#addrs; $i++) {
+ my $a = $addrs[$i];
- # Extract symbolic info for address
- my $func = $a;
- my $fullfunc = $a;
- my $fileline = "";
- if (exists($symbols->{$a})) {
- $func = $symbols->{$a}->[0];
- $fullfunc = $symbols->{$a}->[2];
- $fileline = $symbols->{$a}->[1];
+ # Skip large addresses since they sometimes show up as fake entries on RH9
+ if (length($a) > 8 && $a gt "7fffffffffffffff") {
+ next;
+ }
+
+ if ($main::opt_disasm || $main::opt_list) {
+ # We want just the address for the key
+ push(@result, $a);
+ next;
+ }
+
+ my $symlist = $symbols->{$a};
+ if (!defined($symlist)) {
+ $symlist = [$a, "", $a];
+ }
+
+ # We can have a sequence of symbols for a particular entry
+ # (more than one symbol in the case of inlining). Callers
+ # come before callees in symlist, so walk backwards since
+ # the translated stack should contain callees before callers.
+ for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {
+ my $func = $symlist->[$j-2];
+ my $fileline = $symlist->[$j-1];
+ my $fullfunc = $symlist->[$j];
+ if ($j > 2) {
+ $func = "$func (inline)";
+ }
+ if ($main::opt_addresses) {
+ push(@result, "$a $func $fileline");
+ } elsif ($main::opt_lines) {
+ if ($func eq '??' && $fileline eq '??:0') {
+ push(@result, "$a");
+ } else {
+ push(@result, "$func $fileline");
+ }
+ } elsif ($main::opt_functions) {
+ if ($func eq '??') {
+ push(@result, "$a");
+ } else {
+ push(@result, $func);
+ }
+ } elsif ($main::opt_files) {
+ if ($fileline eq '??:0' || $fileline eq '') {
+ push(@result, "$a");
+ } else {
+ my $f = $fileline;
+ $f =~ s/:\d+$//;
+ push(@result, $f);
+ }
+ } else {
+ push(@result, $a);
+ last; # Do not print inlined info
+ }
+ }
}
- if ($main::opt_disasm || $main::opt_list) {
- return $a; # We want just the address for the key
- } elsif ($main::opt_addresses) {
- return "$a $func $fileline";
- } elsif ($main::opt_lines) {
- return "$func $fileline";
- } elsif ($main::opt_functions) {
- return $func;
- } elsif ($main::opt_files) {
- my $f = ($fileline eq '') ? $a : $fileline;
- $f =~ s/:\d+$//;
- return $f;
- } else {
- return $a;
- }
+ # print join(",", @addrs), " => ", join(",", @result), "\n";
+ return @result;
}
# Generate percent string for a number and a total
@@ -1890,6 +1968,7 @@
'tc_newarray_nothrow',
'do_malloc',
'::do_malloc', # new name -- got moved to an unnamed ns
+ '::do_malloc_or_cpp_alloc',
'DoSampledAllocation',
'simple_alloc::allocate',
'__malloc_alloc_template::allocate',
@@ -1898,7 +1977,12 @@
'__builtin_vec_delete',
'__builtin_vec_new',
'operator new',
- 'operator new[]') {
+ 'operator new[]',
+ # These mark the beginning/end of our custom sections
+ '__start_google_malloc',
+ '__stop_google_malloc',
+ '__start_malloc_hook',
+ '__stop_malloc_hook') {
$skip{$name} = 1;
$skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything
}
@@ -1978,17 +2062,16 @@
my $result = {};
foreach my $k (keys(%{$profile})) {
my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
+ my @translated = TranslateStack($symbols, $k);
my @path = ();
my %seen = ();
$seen{''} = 1; # So that empty keys are skipped
- foreach my $a (@addrs) {
+ foreach my $e (@translated) {
# To avoid double-counting due to recursion, skip a stack-trace
# entry if it has already been seen
- my $key = OutputKey($symbols, $a);
- if (!$seen{$key}) {
- $seen{$key} = 1;
- push(@path, $key);
+ if (!$seen{$e}) {
+ $seen{$e} = 1;
+ push(@path, $e);
}
}
my $reduced_path = join("\n", @path);
@@ -1997,6 +2080,20 @@
return $result;
}
+# Does the specified symbol array match the regexp?
+sub SymbolMatches {
+ my $sym = shift;
+ my $re = shift;
+ if (defined($sym)) {
+ for (my $i = 0; $i < $#{$sym}; $i += 3) {
+ if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
# Focus only on paths involving specified regexps
sub FocusProfile {
my $symbols = shift;
@@ -2008,10 +2105,7 @@
my @addrs = split(/\n/, $k);
foreach my $a (@addrs) {
# Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$focus/) ||
- (exists($symbols->{$a}) &&
- (($symbols->{$a}->[0] =~ m/$focus/) ||
- ($symbols->{$a}->[1] =~ m/$focus/)))) {
+ if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {
AddEntry($result, $k, $count);
last;
}
@@ -2032,10 +2126,7 @@
my $matched = 0;
foreach my $a (@addrs) {
# Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$ignore/) ||
- (exists($symbols->{$a}) &&
- (($symbols->{$a}->[0] =~ m/$ignore/) ||
- ($symbols->{$a}->[1] =~ m/$ignore/)))) {
+ if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {
$matched = 1;
last;
}
@@ -2195,7 +2286,7 @@
sub CheckSymbolPage {
my $url = SymbolPageURL();
- open(SYMBOL, "$WGET -qO- '$url' |");
+ open(SYMBOL, "$WGET $WGET_FLAGS -qO- '$url' |");
my $line = <SYMBOL>;
$line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
close(SYMBOL);
@@ -2240,7 +2331,7 @@
sub FetchProgramName() {
my ($host, $port, $path) = ParseProfileURL($main::pfile_args[0]);
my $url = "http://$host:$port$PROGRAM_NAME_PAGE";
- my $command_line = "$WGET -qO- '$url'";
+ my $command_line = "$WGET $WGET_FLAGS -qO- '$url'";
open(CMDLINE, "$command_line |") or error($command_line);
my $cmdline = <CMDLINE>;
$cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines
@@ -2346,13 +2437,21 @@
# /symbol, the symbols match and are retrievable from the map.
my $shortpc = $pc;
$shortpc =~ s/^0*//;
+ # Each line may have a list of names, which includes the function
+ # and also other functions it has inlined. They are separated
+ # (in PrintSymbolizedFile), by --, which is illegal in function names.
+ my $fullnames;
if (defined($symbol_map->{$shortpc})) {
- $fullname = $symbol_map->{$shortpc};
+ $fullnames = $symbol_map->{$shortpc};
} else {
- $fullname = "0x" . $pc; # Just use addresses
+ $fullnames = "0x" . $pc; # Just use addresses
}
- my $name = ShortFunctionName($fullname);
- $symbols->{$pc} = [$name, "?", $fullname];
+ my $sym = [];
+ $symbols->{$pc} = $sym;
+ foreach my $fullname (split("--", $fullnames)) {
+ my $name = ShortFunctionName($fullname);
+ push(@{$sym}, $name, "?", $fullname);
+ }
}
return $symbols;
}
@@ -2392,7 +2491,7 @@
my $wget_timeout;
if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)) {
if ($path =~ m/$PROFILE_PAGE/) {
- $url = sprintf("http://$host:$port$PROFILE_PAGE?seconds=%d",
+ $url = sprintf("http://$host:$port$path?seconds=%d",
$main::opt_seconds);
} else {
if ($profile_name =~ m/[?]/) {
@@ -2427,7 +2526,7 @@
return $real_profile;
}
- my $cmd = "$WGET $wget_timeout -q -O $tmp_profile '$url'";
+ my $cmd = "$WGET $WGET_FLAGS $wget_timeout -q -O $tmp_profile '$url'";
if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)){
print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n";
if ($encourage_patience) {
@@ -2752,12 +2851,26 @@
# Make key out of the stack entries
my @k = ();
- for (my $j = $d; $j--; ) {
+ for (my $j = 0; $j < $d; $j++) {
my $pclo = $slots->get($i++);
my $pchi = $slots->get($i++);
if ($pclo == -1 || $pchi == -1) {
error("$fname: Unexpected EOF when reading stack of depth $d\n");
}
+
+ # Subtract one from caller pc so we map back to call instr.
+ # However, don't do this if we're reading a symbolized profile
+ # file, in which case the subtract-one was done when the file
+ # was written.
+ if ($j > 0 && !$main::use_symbolized_profile) {
+ if ($pclo == 0) {
+ $pchi--;
+ $pclo = 0xffffffff;
+ } else {
+ $pclo--;
+ }
+ }
+
my $pc = sprintf("%08x%08x", $pchi, $pclo);
$pcs->{$pc} = 1;
push @k, $pc;
@@ -3256,7 +3369,7 @@
my $finish;
my $offset;
my $lib;
- if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib)((\.\d+)+\w*)?)$/i) {
+ if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib|bundle)((\.\d+)+\w*)?)$/i) {
# Full line from /proc/self/maps. Example:
# 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so
$start = HexExtend($1);
@@ -3516,87 +3629,111 @@
my $pclist = shift;
my $symbols = shift;
+ my $debug = 0;
+
# Ignore empty binaries
if ($#{$pclist} < 0) { return; }
- my $got_symbols = MapSymbolsWithNM($image, $offset, $pclist, $symbols);
- if ($main::opt_interactive ||
- $main::opt_addresses ||
- $main::opt_lines ||
- $main::opt_files ||
- $main::opt_list ||
- $main::opt_callgrind ||
- !$got_symbols) {
- GetLineNumbers($image, $offset, $pclist, $symbols);
+ # Figure out the addr2line command to use
+ my $addr2line = $obj_tool_map{"addr2line"};
+ my $cmd = "$addr2line -f -C -e $image";
+ if (exists $obj_tool_map{"addr2line_pdb"}) {
+ $addr2line = $obj_tool_map{"addr2line_pdb"};
+ $cmd = "$addr2line --demangle -f -C -e $image";
}
-}
-# The file $tmpfile_sym must already have been created before calling this.
-sub GetLineNumbersViaAddr2Line {
- my $addr2line_command = shift;
- my $pclist = shift;
- my $symbols = shift;
+ # If "addr2line" isn't installed on the system at all, just use
+ # nm to get what info we can (function names, but not line numbers).
+ if (system("$addr2line --help >/dev/null 2>&1") != 0) {
+ MapSymbolsWithNM($image, $offset, $pclist, $symbols);
+ return;
+ }
- open(SYMBOLS, "$addr2line_command <$main::tmpfile_sym |")
- || error("$addr2line_command: $!\n");
- my $count = 0;
+ # "addr2line -i" can produce a variable number of lines per input
+ # address, with no separator that allows us to tell when data for
+ # the next address starts. So we find the address for a special
+ # symbol (_fini) and interleave this address between all real
+ # addresses passed to addr2line. The name of this special symbol
+ # can then be used as a separator.
+ $sep_address = undef; # May be filled in by MapSymbolsWithNM()
+ my $nm_symbols = {};
+ MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);
+ # TODO(csilvers): only add '-i' if addr2line supports it.
+ if (defined($sep_address)) {
+ # Only add " -i" to addr2line if the binary supports it.
+ # addr2line --help returns 0, but not if it sees an unknown flag first.
+ if (system("$cmd -i --help >/dev/null 2>&1") == 0) {
+ $cmd .= " -i";
+ } else {
+ $sep_address = undef; # no need for sep_address if we don't support -i
+ }
+ }
+
+ # Make file with all PC values with intervening 'sep_address' so
+ # that we can reliably detect the end of inlined function list
+ open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n");
+ if ($debug) { print("---- $image ---\n"); }
+ for (my $i = 0; $i <= $#{$pclist}; $i++) {
+ # addr2line always reads hex addresses, and does not need '0x' prefix.
+ if ($debug) { printf("%s\n", $pclist->[$i]); }
+ printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset));
+ if (defined($sep_address)) {
+ printf ADDRESSES ("%s\n", $sep_address);
+ }
+ }
+ close(ADDRESSES);
+ if ($debug) {
+ print("----\n");
+ system("cat $main::tmpfile_sym");
+ print("----\n");
+ system("$cmd <$main::tmpfile_sym");
+ print("----\n");
+ }
+
+ open(SYMBOLS, "$cmd <$main::tmpfile_sym |") || error("$cmd: $!\n");
+ my $count = 0; # Index in pclist
while (<SYMBOLS>) {
+ # Read fullfunction and filelineinfo from next pair of lines
s/\r?\n$//g;
my $fullfunction = $_;
-
$_ = <SYMBOLS>;
s/\r?\n$//g;
my $filelinenum = $_;
- $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths
- if (!$main::opt_list) {
- $filelinenum =~ s|^.*/([^/]+:\d+)$|$1|; # Remove directory name
+
+ if (defined($sep_address) && $fullfunction eq $sep_symbol) {
+ # Terminating marker for data for this address
+ $count++;
+ next;
}
+ $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths
+
my $pcstr = $pclist->[$count];
- if (defined($symbols->{$pcstr})) {
- # Override just the line-number portion. The function name portion
- # is less buggy when computed using nm instead of addr2line. But
- # don't override if addr2line is giving ??'s and nm didn't. (This
- # may be seen mostly/entirely on cygwin's addr2line/nm.)
- if (($filelinenum ne "??:0") || ($symbols->{$pcstr}->[1] eq "?")) {
- $symbols->{$pcstr}->[1] = $filelinenum;
+ my $function = ShortFunctionName($fullfunction);
+ if ($fullfunction eq '??') {
+ # See if nm found a symbol
+ my $nms = $nm_symbols->{$pcstr};
+ if (defined($nms)) {
+ $function = $nms->[0];
+ $fullfunction = $nms->[2];
}
- } else {
- my $function = ShortFunctionName($fullfunction);
- $symbols->{$pcstr} = [$function, $filelinenum, $fullfunction];
}
- $count++;
- }
- close(SYMBOLS);
- return $count;
-}
-sub GetLineNumbers {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- # Make file with all PC values
- open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n");
- for (my $i = 0; $i <= $#{$pclist}; $i++) {
- # addr2line always reads hex addresses, and does not need '0x' prefix.
- printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset));
- }
- close(ADDRESSES);
-
- # Pass to addr2line
- my $addr2line = $obj_tool_map{"addr2line"};
- my @addr2line_commands = ("$addr2line -f -C -e $image");
- if (exists $obj_tool_map{"addr2line_pdb"}) {
- my $addr2line_pdb = $obj_tool_map{"addr2line_pdb"};
- push(@addr2line_commands, "$addr2line_pdb --demangle -f -C -e $image");
- }
- foreach my $addr2line_command (@addr2line_commands) {
- if (GetLineNumbersViaAddr2Line("$addr2line_command", $pclist, $symbols)) {
- last;
+ # Prepend to accumulated symbols for pcstr
+ # (so that caller comes before callee)
+ my $sym = $symbols->{$pcstr};
+ if (!defined($sym)) {
+ $sym = [];
+ $symbols->{$pcstr} = $sym;
}
+ unshift(@{$sym}, $function, $filelinenum, $fullfunction);
+ if ($debug) { printf("%s => [%s]\n", $pcstr, join(" ", @{$sym})); }
+ if (!defined($sep_address)) {
+ # Inlining is off, se this entry ends immediately
+ $count++;
+ }
}
+ close(SYMBOLS);
}
# Use nm to map the list of referenced PCs to symbols. Return true iff we
@@ -3646,7 +3783,7 @@
}
return 1;
}
-
+
sub ShortFunctionName {
my $function = shift;
while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types
@@ -3813,6 +3950,10 @@
next;
}
+ if ($this_routine eq $sep_symbol) {
+ $sep_address = HexExtend($start_val);
+ }
+
# Tag this routine with the starting address in case the image
# has multiple occurrences of this routine. We use a syntax
# that resembles template paramters that are automatically
« no previous file with comments | « third_party/tcmalloc/chromium/src/pagemap.h ('k') | third_party/tcmalloc/chromium/src/profile-handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698