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

Side by Side Diff: third_party/tcmalloc/chromium/src/pprof

Issue 7865021: Deep-Memory-Profiler (DMP) implementation (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixed bugs Created 9 years, 2 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/tcmalloc/chromium/src/policy ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #! /usr/bin/env perl 1 #! /usr/bin/env perl
2 2
3 # Copyright (c) 1998-2007, Google Inc. 3 # Copyright (c) 1998-2007, Google Inc.
4 # All rights reserved. 4 # All rights reserved.
5 # 5 #
6 # Redistribution and use in source and binary forms, with or without 6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are 7 # modification, are permitted provided that the following conditions are
8 # met: 8 # met:
9 # 9 #
10 # * Redistributions of source code must retain the above copyright 10 # * Redistributions of source code must retain the above copyright
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 # Generates disassembly listing of all routines with at least one 65 # Generates disassembly listing of all routines with at least one
66 # sample that match the --disasm=<regexp> pattern. The listing is 66 # sample that match the --disasm=<regexp> pattern. The listing is
67 # annotated with the flat and cumulative sample counts at each PC value. 67 # annotated with the flat and cumulative sample counts at each PC value.
68 # 68 #
69 # TODO: Use color to indicate files? 69 # TODO: Use color to indicate files?
70 70
71 use strict; 71 use strict;
72 use warnings; 72 use warnings;
73 use Getopt::Long; 73 use Getopt::Long;
74 74
75 my $PPROF_VERSION = "1.7"; 75 my $PPROF_VERSION = "1.8.2";
76 76
77 # These are the object tools we use which can come from a 77 # These are the object tools we use which can come from a
78 # user-specified location using --tools, from the PPROF_TOOLS 78 # user-specified location using --tools, from the PPROF_TOOLS
79 # environment variable, or from the environment. 79 # environment variable, or from the environment.
80 my %obj_tool_map = ( 80 my %obj_tool_map = (
81 "objdump" => "objdump", 81 "objdump" => "objdump",
82 "nm" => "nm", 82 "nm" => "nm",
83 "addr2line" => "addr2line", 83 "addr2line" => "addr2line",
84 "c++filt" => "c++filt", 84 "c++filt" => "c++filt",
85 ## ConfigureObjTools may add architecture-specific entries: 85 ## ConfigureObjTools may add architecture-specific entries:
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 pprof [options] <profile> 149 pprof [options] <profile>
150 <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE 150 <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE
151 151
152 Each name can be: 152 Each name can be:
153 /path/to/profile - a path to a profile file 153 /path/to/profile - a path to a profile file
154 host:port[/<service>] - a location of a service to get profile from 154 host:port[/<service>] - a location of a service to get profile from
155 155
156 The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile, 156 The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
157 $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, 157 $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
158 $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. 158 $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
159 For instance: "pprof http://myserver.com:80$HEAP_PAGE". 159 For instance:
160 pprof http://myserver.com:80$HEAP_PAGE
160 If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profilin g). 161 If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profilin g).
161 pprof --symbols <program> 162 pprof --symbols <program>
162 Maps addresses to symbol names. In this mode, stdin should be a 163 Maps addresses to symbol names. In this mode, stdin should be a
163 list of library mappings, in the same format as is found in the heap- 164 list of library mappings, in the same format as is found in the heap-
164 and cpu-profile files (this loosely matches that of /proc/self/maps 165 and cpu-profile files (this loosely matches that of /proc/self/maps
165 on linux), followed by a list of hex addresses to map, one per line. 166 on linux), followed by a list of hex addresses to map, one per line.
166 167
167 For more help with querying remote servers, including how to add the 168 For more help with querying remote servers, including how to add the
168 necessary server-side support code, see this filename (or one like it): 169 necessary server-side support code, see this filename (or one like it):
169 170
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 if ($main::use_symbol_page) { 539 if ($main::use_symbol_page) {
539 unless (IsProfileURL($main::pfile_args[0])) { 540 unless (IsProfileURL($main::pfile_args[0])) {
540 error("The first profile should be a remote form to use $SYMBOL_PAGE\n"); 541 error("The first profile should be a remote form to use $SYMBOL_PAGE\n");
541 } 542 }
542 CheckSymbolPage(); 543 CheckSymbolPage();
543 $main::prog = FetchProgramName(); 544 $main::prog = FetchProgramName();
544 } elsif (!$main::use_symbolized_profile) { # may not need objtools! 545 } elsif (!$main::use_symbolized_profile) { # may not need objtools!
545 ConfigureObjTools($main::prog) 546 ConfigureObjTools($main::prog)
546 } 547 }
547 548
548 # Break the opt_list_prefix into the prefix_list array 549 # Break the opt_lib_prefix into the prefix_list array
549 @prefix_list = split (',', $main::opt_lib_prefix); 550 @prefix_list = split (',', $main::opt_lib_prefix);
550 551
551 # Remove trailing / from the prefixes, in the list to prevent 552 # Remove trailing / from the prefixes, in the list to prevent
552 # searching things like /my/path//lib/mylib.so 553 # searching things like /my/path//lib/mylib.so
553 foreach (@prefix_list) { 554 foreach (@prefix_list) {
554 s|/+$||; 555 s|/+$||;
555 } 556 }
556 } 557 }
557 558
558 sub Main() { 559 sub Main() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 637
637 # Get derived profiles 638 # Get derived profiles
638 my $flat = FlatProfile($reduced); 639 my $flat = FlatProfile($reduced);
639 my $cumulative = CumulativeProfile($reduced); 640 my $cumulative = CumulativeProfile($reduced);
640 641
641 # Print 642 # Print
642 if (!$main::opt_interactive) { 643 if (!$main::opt_interactive) {
643 if ($main::opt_disasm) { 644 if ($main::opt_disasm) {
644 PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm); 645 PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);
645 } elsif ($main::opt_list) { 646 } elsif ($main::opt_list) {
646 PrintListing($libs, $flat, $cumulative, $main::opt_list); 647 PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);
647 } elsif ($main::opt_text) { 648 } elsif ($main::opt_text) {
648 # Make sure the output is empty when have nothing to report 649 # Make sure the output is empty when have nothing to report
649 # (only matters when --heapcheck is given but we must be 650 # (only matters when --heapcheck is given but we must be
650 # compatible with old branches that did not pass --heapcheck always): 651 # compatible with old branches that did not pass --heapcheck always):
651 if ($total != 0) { 652 if ($total != 0) {
652 printf("Total: %s %s\n", Unparse($total), Units()); 653 printf("Total: %s %s\n", Unparse($total), Units());
653 } 654 }
654 PrintText($symbols, $flat, $cumulative, -1); 655 PrintText($symbols, $flat, $cumulative, -1);
655 } elsif ($main::opt_raw) { 656 } elsif ($main::opt_raw) {
656 PrintSymbolizedProfile($symbols, $profile, $main::prog); 657 PrintSymbolizedProfile($symbols, $profile, $main::prog);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 833
833 if (m/^\s*(text|top)(\d*)\s*(.*)/) { 834 if (m/^\s*(text|top)(\d*)\s*(.*)/) {
834 $main::opt_text = 1; 835 $main::opt_text = 1;
835 836
836 my $line_limit = ($2 ne "") ? int($2) : 10; 837 my $line_limit = ($2 ne "") ? int($2) : 10;
837 838
838 my $routine; 839 my $routine;
839 my $ignore; 840 my $ignore;
840 ($routine, $ignore) = ParseInteractiveArgs($3); 841 ($routine, $ignore) = ParseInteractiveArgs($3);
841 842
842 my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); 843 my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
843 my $reduced = ReduceProfile($symbols, $profile); 844 my $reduced = ReduceProfile($symbols, $profile);
844 845
845 # Get derived profiles 846 # Get derived profiles
846 my $flat = FlatProfile($reduced); 847 my $flat = FlatProfile($reduced);
847 my $cumulative = CumulativeProfile($reduced); 848 my $cumulative = CumulativeProfile($reduced);
848 849
849 PrintText($symbols, $flat, $cumulative, $line_limit); 850 PrintText($symbols, $flat, $cumulative, $line_limit);
850 return 1; 851 return 1;
851 } 852 }
852 if (m/^\s*callgrind\s*([^ \n]*)/) { 853 if (m/^\s*callgrind\s*([^ \n]*)/) {
853 $main::opt_callgrind = 1; 854 $main::opt_callgrind = 1;
854 855
855 # Get derived profiles 856 # Get derived profiles
856 my $calls = ExtractCalls($symbols, $orig_profile); 857 my $calls = ExtractCalls($symbols, $orig_profile);
857 my $filename = $1; 858 my $filename = $1;
858 if ( $1 eq '' ) { 859 if ( $1 eq '' ) {
859 $filename = TempName($main::next_tmpfile, "callgrind"); 860 $filename = TempName($main::next_tmpfile, "callgrind");
860 } 861 }
861 PrintCallgrind($calls, $filename); 862 PrintCallgrind($calls, $filename);
862 if ( $1 eq '' ) { 863 if ( $1 eq '' ) {
863 RunKcachegrind($filename, " & "); 864 RunKcachegrind($filename, " & ");
864 $main::next_tmpfile++; 865 $main::next_tmpfile++;
865 } 866 }
866 867
867 return 1; 868 return 1;
868 } 869 }
869 if (m/^\s*list\s*(.+)/) { 870 if (m/^\s*(web)?list\s*(.+)/) {
871 my $html = (defined($1) && ($1 eq "web"));
870 $main::opt_list = 1; 872 $main::opt_list = 1;
871 873
872 my $routine; 874 my $routine;
873 my $ignore; 875 my $ignore;
874 ($routine, $ignore) = ParseInteractiveArgs($1); 876 ($routine, $ignore) = ParseInteractiveArgs($2);
875 877
876 my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); 878 my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
877 my $reduced = ReduceProfile($symbols, $profile); 879 my $reduced = ReduceProfile($symbols, $profile);
878 880
879 # Get derived profiles 881 # Get derived profiles
880 my $flat = FlatProfile($reduced); 882 my $flat = FlatProfile($reduced);
881 my $cumulative = CumulativeProfile($reduced); 883 my $cumulative = CumulativeProfile($reduced);
882 884
883 PrintListing($libs, $flat, $cumulative, $routine); 885 PrintListing($total, $libs, $flat, $cumulative, $routine, $html);
884 return 1; 886 return 1;
885 } 887 }
886 if (m/^\s*disasm\s*(.+)/) { 888 if (m/^\s*disasm\s*(.+)/) {
887 $main::opt_disasm = 1; 889 $main::opt_disasm = 1;
888 890
889 my $routine; 891 my $routine;
890 my $ignore; 892 my $ignore;
891 ($routine, $ignore) = ParseInteractiveArgs($1); 893 ($routine, $ignore) = ParseInteractiveArgs($1);
892 894
893 # Process current profile to account for various settings 895 # Process current profile to account for various settings
894 my $profile = ProcessProfile($orig_profile, $symbols, "", $ignore); 896 my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
895 my $reduced = ReduceProfile($symbols, $profile); 897 my $reduced = ReduceProfile($symbols, $profile);
896 898
897 # Get derived profiles 899 # Get derived profiles
898 my $flat = FlatProfile($reduced); 900 my $flat = FlatProfile($reduced);
899 my $cumulative = CumulativeProfile($reduced); 901 my $cumulative = CumulativeProfile($reduced);
900 902
901 PrintDisassembly($libs, $flat, $cumulative, $routine); 903 PrintDisassembly($libs, $flat, $cumulative, $routine);
902 return 1; 904 return 1;
903 } 905 }
904 if (m/^\s*(gv|web|evince)\s*(.*)/) { 906 if (m/^\s*(gv|web|evince)\s*(.*)/) {
905 $main::opt_gv = 0; 907 $main::opt_gv = 0;
906 $main::opt_evince = 0; 908 $main::opt_evince = 0;
907 $main::opt_web = 0; 909 $main::opt_web = 0;
908 if ($1 eq "gv") { 910 if ($1 eq "gv") {
909 $main::opt_gv = 1; 911 $main::opt_gv = 1;
910 } elsif ($1 eq "evince") { 912 } elsif ($1 eq "evince") {
911 $main::opt_evince = 1; 913 $main::opt_evince = 1;
912 } elsif ($1 eq "web") { 914 } elsif ($1 eq "web") {
913 $main::opt_web = 1; 915 $main::opt_web = 1;
914 } 916 }
915 917
916 my $focus; 918 my $focus;
917 my $ignore; 919 my $ignore;
918 ($focus, $ignore) = ParseInteractiveArgs($2); 920 ($focus, $ignore) = ParseInteractiveArgs($2);
919 921
920 # Process current profile to account for various settings 922 # Process current profile to account for various settings
921 my $profile = ProcessProfile($orig_profile, $symbols, $focus, $ignore); 923 my $profile = ProcessProfile($total, $orig_profile, $symbols,
924 $focus, $ignore);
922 my $reduced = ReduceProfile($symbols, $profile); 925 my $reduced = ReduceProfile($symbols, $profile);
923 926
924 # Get derived profiles 927 # Get derived profiles
925 my $flat = FlatProfile($reduced); 928 my $flat = FlatProfile($reduced);
926 my $cumulative = CumulativeProfile($reduced); 929 my $cumulative = CumulativeProfile($reduced);
927 930
928 if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { 931 if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
929 if ($main::opt_gv) { 932 if ($main::opt_gv) {
930 RunGV(TempName($main::next_tmpfile, "ps"), " &"); 933 RunGV(TempName($main::next_tmpfile, "ps"), " &");
931 } elsif ($main::opt_evince) { 934 } elsif ($main::opt_evince) {
932 RunEvince(TempName($main::next_tmpfile, "pdf"), " &"); 935 RunEvince(TempName($main::next_tmpfile, "pdf"), " &");
933 } elsif ($main::opt_web) { 936 } elsif ($main::opt_web) {
934 RunWeb(TempName($main::next_tmpfile, "svg")); 937 RunWeb(TempName($main::next_tmpfile, "svg"));
935 } 938 }
936 $main::next_tmpfile++; 939 $main::next_tmpfile++;
937 } 940 }
938 return 1; 941 return 1;
939 } 942 }
940 if (m/^\s*$/) { 943 if (m/^\s*$/) {
941 return 1; 944 return 1;
942 } 945 }
943 print STDERR "Unknown command: try 'help'.\n"; 946 print STDERR "Unknown command: try 'help'.\n";
944 return 1; 947 return 1;
945 } 948 }
946 949
947 950
948 sub ProcessProfile { 951 sub ProcessProfile {
952 my $total_count = shift;
949 my $orig_profile = shift; 953 my $orig_profile = shift;
950 my $symbols = shift; 954 my $symbols = shift;
951 my $focus = shift; 955 my $focus = shift;
952 my $ignore = shift; 956 my $ignore = shift;
953 957
954 # Process current profile to account for various settings 958 # Process current profile to account for various settings
955 my $profile = $orig_profile; 959 my $profile = $orig_profile;
956 my $total_count = TotalProfile($profile);
957 printf("Total: %s %s\n", Unparse($total_count), Units()); 960 printf("Total: %s %s\n", Unparse($total_count), Units());
958 if ($focus ne '') { 961 if ($focus ne '') {
959 $profile = FocusProfile($symbols, $profile, $focus); 962 $profile = FocusProfile($symbols, $profile, $focus);
960 my $focus_count = TotalProfile($profile); 963 my $focus_count = TotalProfile($profile);
961 printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n", 964 printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
962 $focus, 965 $focus,
963 Unparse($focus_count), Units(), 966 Unparse($focus_count), Units(),
964 Unparse($total_count), ($focus_count*100.0) / $total_count); 967 Unparse($total_count), ($focus_count*100.0) / $total_count);
965 } 968 }
966 if ($ignore ne '') { 969 if ($ignore ne '') {
(...skipping 26 matching lines...) Expand all
993 web [focus] [-ignore1] [-ignore2] 996 web [focus] [-ignore1] [-ignore2]
994 Like GV, but displays profile in your web browser instead of using 997 Like GV, but displays profile in your web browser instead of using
995 Ghostview. Works best if your web browser is already running. 998 Ghostview. Works best if your web browser is already running.
996 To change the browser that gets used: 999 To change the browser that gets used:
997 On Linux, set the /etc/alternatives/gnome-www-browser symlink. 1000 On Linux, set the /etc/alternatives/gnome-www-browser symlink.
998 On OS X, change the Finder association for SVG files. 1001 On OS X, change the Finder association for SVG files.
999 1002
1000 list [routine_regexp] [-ignore1] [-ignore2] 1003 list [routine_regexp] [-ignore1] [-ignore2]
1001 Show source listing of routines whose names match "routine_regexp" 1004 Show source listing of routines whose names match "routine_regexp"
1002 1005
1006 weblist [routine_regexp] [-ignore1] [-ignore2]
1007 Displays a source listing of routines whose names match "routine_regexp"
1008 in a web browser. You can click on source lines to view the
1009 corresponding disassembly.
1010
1003 top [--cum] [-ignore1] [-ignore2] 1011 top [--cum] [-ignore1] [-ignore2]
1004 top20 [--cum] [-ignore1] [-ignore2] 1012 top20 [--cum] [-ignore1] [-ignore2]
1005 top37 [--cum] [-ignore1] [-ignore2] 1013 top37 [--cum] [-ignore1] [-ignore2]
1006 Show top lines ordered by flat profile count, or cumulative count 1014 Show top lines ordered by flat profile count, or cumulative count
1007 if --cum is specified. If a number is present after 'top', the 1015 if --cum is specified. If a number is present after 'top', the
1008 top K routines will be shown (defaults to showing the top 10) 1016 top K routines will be shown (defaults to showing the top 10)
1009 1017
1010 disasm [routine_regexp] [-ignore1] [-ignore2] 1018 disasm [routine_regexp] [-ignore1] [-ignore2]
1011 Show disassembly of routines whose names match "routine_regexp", 1019 Show disassembly of routines whose names match "routine_regexp",
1012 annotated with sample counts. 1020 annotated with sample counts.
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 if ($f != 0 || $c != 0) { 1176 if ($f != 0 || $c != 0) {
1169 printf("%8s %6s %6s %8s %6s %s\n", 1177 printf("%8s %6s %6s %8s %6s %s\n",
1170 Unparse($f), 1178 Unparse($f),
1171 Percent($f, $total), 1179 Percent($f, $total),
1172 Percent($running_sum, $total), 1180 Percent($running_sum, $total),
1173 Unparse($c), 1181 Unparse($c),
1174 Percent($c, $total), 1182 Percent($c, $total),
1175 $sym); 1183 $sym);
1176 } 1184 }
1177 $lines++; 1185 $lines++;
1178 last if ($line_limit >= 0 && $lines > $line_limit); 1186 last if ($line_limit >= 0 && $lines >= $line_limit);
1179 } 1187 }
1180 } 1188 }
1181 1189
1182 # Print the call graph in a way that's suiteable for callgrind. 1190 # Print the call graph in a way that's suiteable for callgrind.
1183 sub PrintCallgrind { 1191 sub PrintCallgrind {
1184 my $calls = shift; 1192 my $calls = shift;
1185 my $filename; 1193 my $filename;
1186 if ($main::opt_interactive) { 1194 if ($main::opt_interactive) {
1187 $filename = shift; 1195 $filename = shift;
1188 print STDERR "Writing callgrind file to '$filename'.\n" 1196 print STDERR "Writing callgrind file to '$filename'.\n"
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 print(($symbols->{$pc}->[0] || "??") . "\n"); 1323 print(($symbols->{$pc}->[0] || "??") . "\n");
1316 } 1324 }
1317 } 1325 }
1318 1326
1319 1327
1320 # For sorting functions by name 1328 # For sorting functions by name
1321 sub ByName { 1329 sub ByName {
1322 return ShortFunctionName($a) cmp ShortFunctionName($b); 1330 return ShortFunctionName($a) cmp ShortFunctionName($b);
1323 } 1331 }
1324 1332
1325 # Print source-listing for all all routines that match $main::opt_list 1333 # Print source-listing for all all routines that match $list_opts
1326 sub PrintListing { 1334 sub PrintListing {
1335 my $total = shift;
1327 my $libs = shift; 1336 my $libs = shift;
1328 my $flat = shift; 1337 my $flat = shift;
1329 my $cumulative = shift; 1338 my $cumulative = shift;
1330 my $list_opts = shift; 1339 my $list_opts = shift;
1340 my $html = shift;
1331 1341
1342 my $output = \*STDOUT;
1343 my $fname = "";
1344
1345 if ($html) {
1346 # Arrange to write the output to a temporary file
1347 $fname = TempName($main::next_tmpfile, "html");
1348 $main::next_tmpfile++;
1349 if (!open(TEMP, ">$fname")) {
1350 print STDERR "$fname: $!\n";
1351 return;
1352 }
1353 $output = \*TEMP;
1354 print $output HtmlListingHeader();
1355 printf $output ("<div class=\"legend\">%s<br>Total: %s %s</div>\n",
1356 $main::prog, Unparse($total), Units());
1357 }
1358
1359 my $listed = 0;
1332 foreach my $lib (@{$libs}) { 1360 foreach my $lib (@{$libs}) {
1333 my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts); 1361 my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);
1334 my $offset = AddressSub($lib->[1], $lib->[3]); 1362 my $offset = AddressSub($lib->[1], $lib->[3]);
1335 foreach my $routine (sort ByName keys(%{$symbol_table})) { 1363 foreach my $routine (sort ByName keys(%{$symbol_table})) {
1336 # Print if there are any samples in this routine 1364 # Print if there are any samples in this routine
1337 my $start_addr = $symbol_table->{$routine}->[0]; 1365 my $start_addr = $symbol_table->{$routine}->[0];
1338 my $end_addr = $symbol_table->{$routine}->[1]; 1366 my $end_addr = $symbol_table->{$routine}->[1];
1339 my $length = hex(AddressSub($end_addr, $start_addr)); 1367 my $length = hex(AddressSub($end_addr, $start_addr));
1340 my $addr = AddressAdd($start_addr, $offset); 1368 my $addr = AddressAdd($start_addr, $offset);
1341 for (my $i = 0; $i < $length; $i++) { 1369 for (my $i = 0; $i < $length; $i++) {
1342 if (defined($cumulative->{$addr})) { 1370 if (defined($cumulative->{$addr})) {
1343 PrintSource($lib->[0], $offset, 1371 $listed += PrintSource(
1344 $routine, $flat, $cumulative, 1372 $lib->[0], $offset,
1345 $start_addr, $end_addr); 1373 $routine, $flat, $cumulative,
1374 $start_addr, $end_addr,
1375 $html,
1376 $output);
1346 last; 1377 last;
1347 } 1378 }
1348 $addr = AddressInc($addr); 1379 $addr = AddressInc($addr);
1349 } 1380 }
1350 } 1381 }
1351 } 1382 }
1383
1384 if ($html) {
1385 if ($listed > 0) {
1386 print $output HtmlListingFooter();
1387 close($output);
1388 RunWeb($fname);
1389 } else {
1390 close($output);
1391 unlink($fname);
1392 }
1393 }
1394 }
1395
1396 sub HtmlListingHeader {
1397 return <<'EOF';
1398 <DOCTYPE html>
1399 <html>
1400 <head>
1401 <title>Pprof listing</title>
1402 <style type="text/css">
1403 body {
1404 font-family: sans-serif;
1405 }
1406 h1 {
1407 font-size: 1.5em;
1408 margin-bottom: 4px;
1409 }
1410 .legend {
1411 font-size: 1.25em;
1412 }
1413 .line {
1414 color: #aaaaaa;
1415 }
1416 .nop {
1417 color: #aaaaaa;
1418 }
1419 .unimportant {
1420 color: #cccccc;
1421 }
1422 .disasmloc {
1423 color: #000000;
1424 }
1425 .deadsrc {
1426 cursor: pointer;
1427 }
1428 .deadsrc:hover {
1429 background-color: #eeeeee;
1430 }
1431 .livesrc {
1432 color: #0000ff;
1433 cursor: pointer;
1434 }
1435 .livesrc:hover {
1436 background-color: #eeeeee;
1437 }
1438 .asm {
1439 color: #008800;
1440 display: none;
1441 }
1442 </style>
1443 <script type="text/javascript">
1444 function pprof_toggle_asm(e) {
1445 var target;
1446 if (!e) e = window.event;
1447 if (e.target) target = e.target;
1448 else if (e.srcElement) target = e.srcElement;
1449
1450 if (target) {
1451 var asm = target.nextSibling;
1452 if (asm && asm.className == "asm") {
1453 asm.style.display = (asm.style.display == "block" ? "" : "block");
1454 e.preventDefault();
1455 return false;
1456 }
1457 }
1458 }
1459 </script>
1460 </head>
1461 <body>
1462 EOF
1463 }
1464
1465 sub HtmlListingFooter {
1466 return <<'EOF';
1467 </body>
1468 </html>
1469 EOF
1470 }
1471
1472 sub HtmlEscape {
1473 my $text = shift;
1474 $text =~ s/&/&amp;/g;
1475 $text =~ s/</&lt;/g;
1476 $text =~ s/>/&gt;/g;
1477 return $text;
1352 } 1478 }
1353 1479
1354 # Returns the indentation of the line, if it has any non-whitespace 1480 # Returns the indentation of the line, if it has any non-whitespace
1355 # characters. Otherwise, returns -1. 1481 # characters. Otherwise, returns -1.
1356 sub Indentation { 1482 sub Indentation {
1357 my $line = shift; 1483 my $line = shift;
1358 if (m/^(\s*)\S/) { 1484 if (m/^(\s*)\S/) {
1359 return length($1); 1485 return length($1);
1360 } else { 1486 } else {
1361 return -1; 1487 return -1;
1362 } 1488 }
1363 } 1489 }
1364 1490
1491 # If the symbol table contains inlining info, Disassemble() may tag an
1492 # instruction with a location inside an inlined function. But for
1493 # source listings, we prefer to use the location in the function we
1494 # are listing. So use MapToSymbols() to fetch full location
1495 # information for each instruction and then pick out the first
1496 # location from a location list (location list contains callers before
1497 # callees in case of inlining).
1498 #
1499 # After this routine has run, each entry in $instructions contains:
1500 # [0] start address
1501 # [1] filename for function we are listing
1502 # [2] line number for function we are listing
1503 # [3] disassembly
1504 # [4] limit address
1505 # [5] most specific filename (may be different from [1] due to inlining)
1506 # [6] most specific line number (may be different from [2] due to inlining)
1507 sub GetTopLevelLineNumbers {
1508 my ($lib, $offset, $instructions) = @_;
1509 my $pcs = [];
1510 for (my $i = 0; $i <= $#{$instructions}; $i++) {
1511 push(@{$pcs}, $instructions->[$i]->[0]);
1512 }
1513 my $symbols = {};
1514 MapToSymbols($lib, $offset, $pcs, $symbols);
1515 for (my $i = 0; $i <= $#{$instructions}; $i++) {
1516 my $e = $instructions->[$i];
1517 push(@{$e}, $e->[1]);
1518 push(@{$e}, $e->[2]);
1519 my $addr = $e->[0];
1520 my $sym = $symbols->{$addr};
1521 if (defined($sym)) {
1522 if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) {
1523 $e->[1] = $1; # File name
1524 $e->[2] = $2; # Line number
1525 }
1526 }
1527 }
1528 }
1529
1365 # Print source-listing for one routine 1530 # Print source-listing for one routine
1366 sub PrintSource { 1531 sub PrintSource {
1367 my $prog = shift; 1532 my $prog = shift;
1368 my $offset = shift; 1533 my $offset = shift;
1369 my $routine = shift; 1534 my $routine = shift;
1370 my $flat = shift; 1535 my $flat = shift;
1371 my $cumulative = shift; 1536 my $cumulative = shift;
1372 my $start_addr = shift; 1537 my $start_addr = shift;
1373 my $end_addr = shift; 1538 my $end_addr = shift;
1539 my $html = shift;
1540 my $output = shift;
1374 1541
1375 # Disassemble all instructions (just to get line numbers) 1542 # Disassemble all instructions (just to get line numbers)
1376 my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); 1543 my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
1544 GetTopLevelLineNumbers($prog, $offset, \@instructions);
1377 1545
1378 # Hack 1: assume that the first source file encountered in the 1546 # Hack 1: assume that the first source file encountered in the
1379 # disassembly contains the routine 1547 # disassembly contains the routine
1380 my $filename = undef; 1548 my $filename = undef;
1381 for (my $i = 0; $i <= $#instructions; $i++) { 1549 for (my $i = 0; $i <= $#instructions; $i++) {
1382 if ($instructions[$i]->[2] >= 0) { 1550 if ($instructions[$i]->[2] >= 0) {
1383 $filename = $instructions[$i]->[1]; 1551 $filename = $instructions[$i]->[1];
1384 last; 1552 last;
1385 } 1553 }
1386 } 1554 }
1387 if (!defined($filename)) { 1555 if (!defined($filename)) {
1388 print STDERR "no filename found in $routine\n"; 1556 print STDERR "no filename found in $routine\n";
1389 return; 1557 return 0;
1390 } 1558 }
1391 1559
1392 # Hack 2: assume that the largest line number from $filename is the 1560 # Hack 2: assume that the largest line number from $filename is the
1393 # end of the procedure. This is typically safe since if P1 contains 1561 # end of the procedure. This is typically safe since if P1 contains
1394 # an inlined call to P2, then P2 usually occurs earlier in the 1562 # an inlined call to P2, then P2 usually occurs earlier in the
1395 # source file. If this does not work, we might have to compute a 1563 # source file. If this does not work, we might have to compute a
1396 # density profile or just print all regions we find. 1564 # density profile or just print all regions we find.
1397 my $lastline = 0; 1565 my $lastline = 0;
1398 for (my $i = 0; $i <= $#instructions; $i++) { 1566 for (my $i = 0; $i <= $#instructions; $i++) {
1399 my $f = $instructions[$i]->[1]; 1567 my $f = $instructions[$i]->[1];
(...skipping 12 matching lines...) Expand all
1412 last; 1580 last;
1413 } 1581 }
1414 } 1582 }
1415 1583
1416 # Hack 4: Extend last line forward until its indentation is less than 1584 # Hack 4: Extend last line forward until its indentation is less than
1417 # the indentation we saw on $firstline 1585 # the indentation we saw on $firstline
1418 my $oldlastline = $lastline; 1586 my $oldlastline = $lastline;
1419 { 1587 {
1420 if (!open(FILE, "<$filename")) { 1588 if (!open(FILE, "<$filename")) {
1421 print STDERR "$filename: $!\n"; 1589 print STDERR "$filename: $!\n";
1422 return; 1590 return 0;
1423 } 1591 }
1424 my $l = 0; 1592 my $l = 0;
1425 my $first_indentation = -1; 1593 my $first_indentation = -1;
1426 while (<FILE>) { 1594 while (<FILE>) {
1427 s/\r//g; # turn windows-looking lines into unix-looking lines 1595 s/\r//g; # turn windows-looking lines into unix-looking lines
1428 $l++; 1596 $l++;
1429 my $indent = Indentation($_); 1597 my $indent = Indentation($_);
1430 if ($l >= $firstline) { 1598 if ($l >= $firstline) {
1431 if ($first_indentation < 0 && $indent >= 0) { 1599 if ($first_indentation < 0 && $indent >= 0) {
1432 $first_indentation = $indent; 1600 $first_indentation = $indent;
1433 last if ($first_indentation == 0); 1601 last if ($first_indentation == 0);
1434 } 1602 }
1435 } 1603 }
1436 if ($l >= $lastline && $indent >= 0) { 1604 if ($l >= $lastline && $indent >= 0) {
1437 if ($indent >= $first_indentation) { 1605 if ($indent >= $first_indentation) {
1438 $lastline = $l+1; 1606 $lastline = $l+1;
1439 } else { 1607 } else {
1440 last; 1608 last;
1441 } 1609 }
1442 } 1610 }
1443 } 1611 }
1444 close(FILE); 1612 close(FILE);
1445 } 1613 }
1446 1614
1447 # Assign all samples to the range $firstline,$lastline, 1615 # Assign all samples to the range $firstline,$lastline,
1448 # Hack 4: If an instruction does not occur in the range, its samples 1616 # Hack 4: If an instruction does not occur in the range, its samples
1449 # are moved to the next instruction that occurs in the range. 1617 # are moved to the next instruction that occurs in the range.
1450 my $samples1 = {}; 1618 my $samples1 = {}; # Map from line number to flat count
1451 my $samples2 = {}; 1619 my $samples2 = {}; # Map from line number to cumulative count
1452 my $running1 = 0; # Unassigned flat counts 1620 my $running1 = 0; # Unassigned flat counts
1453 my $running2 = 0; # Unassigned cumulative counts 1621 my $running2 = 0; # Unassigned cumulative counts
1454 my $total1 = 0; # Total flat counts 1622 my $total1 = 0; # Total flat counts
1455 my $total2 = 0; # Total cumulative counts 1623 my $total2 = 0; # Total cumulative counts
1624 my %disasm = (); # Map from line number to disassembly
1625 my $running_disasm = ""; # Unassigned disassembly
1626 my $skip_marker = "---\n";
1627 if ($html) {
1628 $skip_marker = "";
1629 for (my $l = $firstline; $l <= $lastline; $l++) {
1630 $disasm{$l} = "";
1631 }
1632 }
1633 my $last_dis_filename = '';
1634 my $last_dis_linenum = -1;
1635 my $last_touched_line = -1; # To detect gaps in disassembly for a line
1456 foreach my $e (@instructions) { 1636 foreach my $e (@instructions) {
1457 # Add up counts for all address that fall inside this instruction 1637 # Add up counts for all address that fall inside this instruction
1458 my $c1 = 0; 1638 my $c1 = 0;
1459 my $c2 = 0; 1639 my $c2 = 0;
1460 for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { 1640 for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
1461 $c1 += GetEntry($flat, $a); 1641 $c1 += GetEntry($flat, $a);
1462 $c2 += GetEntry($cumulative, $a); 1642 $c2 += GetEntry($cumulative, $a);
1463 } 1643 }
1644
1645 if ($html) {
1646 my $dis = sprintf(" %6s %6s \t\t%8s: %s ",
1647 HtmlPrintNumber($c1),
1648 HtmlPrintNumber($c2),
1649 UnparseAddress($offset, $e->[0]),
1650 CleanDisassembly($e->[3]));
1651
1652 # Append the most specific source line associated with this instruction
1653 if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) };
1654 $dis = HtmlEscape($dis);
1655 my $f = $e->[5];
1656 my $l = $e->[6];
1657 if ($f ne $last_dis_filename) {
1658 $dis .= sprintf("<span class=disasmloc>%s:%d</span>",
1659 HtmlEscape(CleanFileName($f)), $l);
1660 } elsif ($l ne $last_dis_linenum) {
1661 # De-emphasize the unchanged file name portion
1662 $dis .= sprintf("<span class=unimportant>%s</span>" .
1663 "<span class=disasmloc>:%d</span>",
1664 HtmlEscape(CleanFileName($f)), $l);
1665 } else {
1666 # De-emphasize the entire location
1667 $dis .= sprintf("<span class=unimportant>%s:%d</span>",
1668 HtmlEscape(CleanFileName($f)), $l);
1669 }
1670 $last_dis_filename = $f;
1671 $last_dis_linenum = $l;
1672 $running_disasm .= $dis;
1673 $running_disasm .= "\n";
1674 }
1675
1464 $running1 += $c1; 1676 $running1 += $c1;
1465 $running2 += $c2; 1677 $running2 += $c2;
1466 $total1 += $c1; 1678 $total1 += $c1;
1467 $total2 += $c2; 1679 $total2 += $c2;
1468 my $file = $e->[1]; 1680 my $file = $e->[1];
1469 my $line = $e->[2]; 1681 my $line = $e->[2];
1470 if (($file eq $filename) && 1682 if (($file eq $filename) &&
1471 ($line >= $firstline) && 1683 ($line >= $firstline) &&
1472 ($line <= $lastline)) { 1684 ($line <= $lastline)) {
1473 # Assign all accumulated samples to this line 1685 # Assign all accumulated samples to this line
1474 AddEntry($samples1, $line, $running1); 1686 AddEntry($samples1, $line, $running1);
1475 AddEntry($samples2, $line, $running2); 1687 AddEntry($samples2, $line, $running2);
1476 $running1 = 0; 1688 $running1 = 0;
1477 $running2 = 0; 1689 $running2 = 0;
1690 if ($html) {
1691 if ($line != $last_touched_line && $disasm{$line} ne '') {
1692 $disasm{$line} .= "\n";
1693 }
1694 $disasm{$line} .= $running_disasm;
1695 $running_disasm = '';
1696 $last_touched_line = $line;
1697 }
1478 } 1698 }
1479 } 1699 }
1480 1700
1481 # Assign any leftover samples to $lastline 1701 # Assign any leftover samples to $lastline
1482 AddEntry($samples1, $lastline, $running1); 1702 AddEntry($samples1, $lastline, $running1);
1483 AddEntry($samples2, $lastline, $running2); 1703 AddEntry($samples2, $lastline, $running2);
1704 if ($html) {
1705 if ($lastline != $last_touched_line && $disasm{$lastline} ne '') {
1706 $disasm{$lastline} .= "\n";
1707 }
1708 $disasm{$lastline} .= $running_disasm;
1709 }
1484 1710
1485 printf("ROUTINE ====================== %s in %s\n" . 1711 if ($html) {
1486 "%6s %6s Total %s (flat / cumulative)\n", 1712 printf $output (
1487 ShortFunctionName($routine), 1713 "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\n" .
1488 $filename, 1714 "Total:%6s %6s (flat / cumulative %s)\n",
1489 Units(), 1715 HtmlEscape(ShortFunctionName($routine)),
1490 Unparse($total1), 1716 HtmlEscape(CleanFileName($filename)),
1491 Unparse($total2)); 1717 Unparse($total1),
1718 Unparse($total2),
1719 Units());
1720 } else {
1721 printf $output (
1722 "ROUTINE ====================== %s in %s\n" .
1723 "%6s %6s Total %s (flat / cumulative)\n",
1724 ShortFunctionName($routine),
1725 CleanFileName($filename),
1726 Unparse($total1),
1727 Unparse($total2),
1728 Units());
1729 }
1492 if (!open(FILE, "<$filename")) { 1730 if (!open(FILE, "<$filename")) {
1493 print STDERR "$filename: $!\n"; 1731 print STDERR "$filename: $!\n";
1494 return; 1732 return 0;
1495 } 1733 }
1496 my $l = 0; 1734 my $l = 0;
1497 while (<FILE>) { 1735 while (<FILE>) {
1498 s/\r//g; # turn windows-looking lines into unix-looking lines 1736 s/\r//g; # turn windows-looking lines into unix-looking lines
1499 $l++; 1737 $l++;
1500 if ($l >= $firstline - 5 && 1738 if ($l >= $firstline - 5 &&
1501 (($l <= $oldlastline + 5) || ($l <= $lastline))) { 1739 (($l <= $oldlastline + 5) || ($l <= $lastline))) {
1502 chop; 1740 chop;
1503 my $text = $_; 1741 my $text = $_;
1504 if ($l == $firstline) { printf("---\n"); } 1742 if ($l == $firstline) { print $output $skip_marker; }
1505 printf("%6s %6s %4d: %s\n", 1743 my $n1 = GetEntry($samples1, $l);
1506 UnparseAlt(GetEntry($samples1, $l)), 1744 my $n2 = GetEntry($samples2, $l);
1507 UnparseAlt(GetEntry($samples2, $l)), 1745 if ($html) {
1508 $l, 1746 # Emit a span that has one of the following classes:
1509 $text); 1747 # livesrc -- has samples
1510 if ($l == $lastline) { printf("---\n"); } 1748 # deadsrc -- has disassembly, but with no samples
1749 # nop -- has no matching disasembly
1750 # Also emit an optional span containing disassembly.
1751 my $dis = $disasm{$l};
1752 my $asm = "";
1753 if (defined($dis) && $dis ne '') {
1754 $asm = "<span class=\"asm\">" . $dis . "</span>";
1755 }
1756 my $source_class = (($n1 + $n2 > 0)
1757 ? "livesrc"
1758 : (($asm ne "") ? "deadsrc" : "nop"));
1759 printf $output (
1760 "<span class=\"line\">%5d</span> " .
1761 "<span class=\"%s\">%6s %6s %s</span>%s\n",
1762 $l, $source_class,
1763 HtmlPrintNumber($n1),
1764 HtmlPrintNumber($n2),
1765 HtmlEscape($text),
1766 $asm);
1767 } else {
1768 printf $output(
1769 "%6s %6s %4d: %s\n",
1770 UnparseAlt($n1),
1771 UnparseAlt($n2),
1772 $l,
1773 $text);
1774 }
1775 if ($l == $lastline) { print $output $skip_marker; }
1511 }; 1776 };
1512 } 1777 }
1513 close(FILE); 1778 close(FILE);
1779 if ($html) {
1780 print $output "</pre>\n";
1781 }
1782 return 1;
1514 } 1783 }
1515 1784
1516 # Return the source line for the specified file/linenumber. 1785 # Return the source line for the specified file/linenumber.
1517 # Returns undef if not found. 1786 # Returns undef if not found.
1518 sub SourceLine { 1787 sub SourceLine {
1519 my $file = shift; 1788 my $file = shift;
1520 my $line = shift; 1789 my $line = shift;
1521 1790
1522 # Look in cache 1791 # Look in cache
1523 if (!defined($main::source_cache{$file})) { 1792 if (!defined($main::source_cache{$file})) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 printf("%6s %6s %5d: %s", 1915 printf("%6s %6s %5d: %s",
1647 UnparseAlt($flat_sum{$l}), 1916 UnparseAlt($flat_sum{$l}),
1648 UnparseAlt($cum_sum{$l}), 1917 UnparseAlt($cum_sum{$l}),
1649 $l, 1918 $l,
1650 $line); 1919 $line);
1651 } 1920 }
1652 1921
1653 # Print disassembly 1922 # Print disassembly
1654 for (my $x = $first_inst; $x <= $last_inst; $x++) { 1923 for (my $x = $first_inst; $x <= $last_inst; $x++) {
1655 my $e = $instructions[$x]; 1924 my $e = $instructions[$x];
1656 my $address = $e->[0];
1657 $address = AddressSub($address, $offset); # Make relative to section
1658 $address =~ s/^0x//;
1659 $address =~ s/^0*//;
1660
1661 # Trim symbols
1662 my $d = $e->[3];
1663 while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax)
1664 while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments
1665
1666 printf("%6s %6s %8s: %6s\n", 1925 printf("%6s %6s %8s: %6s\n",
1667 UnparseAlt($flat_count[$x]), 1926 UnparseAlt($flat_count[$x]),
1668 UnparseAlt($cum_count[$x]), 1927 UnparseAlt($cum_count[$x]),
1669 $address, 1928 UnparseAddress($offset, $e->[0]),
1670 $d); 1929 CleanDisassembly($e->[3]));
1671 } 1930 }
1672 } 1931 }
1673 } 1932 }
1674 1933
1675 # Print DOT graph 1934 # Print DOT graph
1676 sub PrintDot { 1935 sub PrintDot {
1677 my $prog = shift; 1936 my $prog = shift;
1678 my $symbols = shift; 1937 my $symbols = shift;
1679 my $raw = shift; 1938 my $raw = shift;
1680 my $flat = shift; 1939 my $flat = shift;
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
2319 # Alternate pretty-printed form: 0 maps to "." 2578 # Alternate pretty-printed form: 0 maps to "."
2320 sub UnparseAlt { 2579 sub UnparseAlt {
2321 my $num = shift; 2580 my $num = shift;
2322 if ($num == 0) { 2581 if ($num == 0) {
2323 return "."; 2582 return ".";
2324 } else { 2583 } else {
2325 return Unparse($num); 2584 return Unparse($num);
2326 } 2585 }
2327 } 2586 }
2328 2587
2588 # Alternate pretty-printed form: 0 maps to ""
2589 sub HtmlPrintNumber {
2590 my $num = shift;
2591 if ($num == 0) {
2592 return "";
2593 } else {
2594 return Unparse($num);
2595 }
2596 }
2597
2329 # Return output units 2598 # Return output units
2330 sub Units { 2599 sub Units {
2331 if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { 2600 if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
2332 if ($main::opt_inuse_objects || $main::opt_alloc_objects) { 2601 if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
2333 return "objects"; 2602 return "objects";
2334 } else { 2603 } else {
2335 if ($main::opt_show_bytes) { 2604 if ($main::opt_show_bytes) {
2336 return "B"; 2605 return "B";
2337 } else { 2606 } else {
2338 return "MB"; 2607 return "MB";
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 '::do_malloc_or_cpp_alloc', 2744 '::do_malloc_or_cpp_alloc',
2476 'DoSampledAllocation', 2745 'DoSampledAllocation',
2477 'simple_alloc::allocate', 2746 'simple_alloc::allocate',
2478 '__malloc_alloc_template::allocate', 2747 '__malloc_alloc_template::allocate',
2479 '__builtin_delete', 2748 '__builtin_delete',
2480 '__builtin_new', 2749 '__builtin_new',
2481 '__builtin_vec_delete', 2750 '__builtin_vec_delete',
2482 '__builtin_vec_new', 2751 '__builtin_vec_new',
2483 'operator new', 2752 'operator new',
2484 'operator new[]', 2753 'operator new[]',
2754 # The entry to our memory-allocation routines on OS X
2755 'malloc_zone_malloc',
2756 'malloc_zone_calloc',
2757 'malloc_zone_valloc',
2758 'malloc_zone_realloc',
2759 'malloc_zone_memalign',
2760 'malloc_zone_free',
2485 # These mark the beginning/end of our custom sections 2761 # These mark the beginning/end of our custom sections
2486 '__start_google_malloc', 2762 '__start_google_malloc',
2487 '__stop_google_malloc', 2763 '__stop_google_malloc',
2488 '__start_malloc_hook', 2764 '__start_malloc_hook',
2489 '__stop_malloc_hook') { 2765 '__stop_malloc_hook') {
2490 $skip{$name} = 1; 2766 $skip{$name} = 1;
2491 $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything 2767 $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything
2492 } 2768 }
2493 # TODO: Remove TCMalloc once everything has been 2769 # TODO: Remove TCMalloc once everything has been
2494 # moved into the tcmalloc:: namespace and we have flushed 2770 # moved into the tcmalloc:: namespace and we have flushed
(...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after
3969 my $buildvar = ""; 4245 my $buildvar = "";
3970 foreach my $l (split("\n", $map)) { 4246 foreach my $l (split("\n", $map)) {
3971 if ($l =~ m/^\s*build=(.*)$/) { 4247 if ($l =~ m/^\s*build=(.*)$/) {
3972 $buildvar = $1; 4248 $buildvar = $1;
3973 } 4249 }
3974 4250
3975 my $start; 4251 my $start;
3976 my $finish; 4252 my $finish;
3977 my $offset; 4253 my $offset;
3978 my $lib; 4254 my $lib;
3979 if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib|bu ndle)((\.\d+)+\w*(\.\d+){0,3})?)$/i) { 4255 if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+(\.(so|dll|dylib|b undle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?)$/i) {
3980 # Full line from /proc/self/maps. Example: 4256 # Full line from /proc/self/maps. Example:
3981 # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so 4257 # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so
3982 $start = HexExtend($1); 4258 $start = HexExtend($1);
3983 $finish = HexExtend($2); 4259 $finish = HexExtend($2);
3984 $offset = HexExtend($3); 4260 $offset = HexExtend($3);
3985 $lib = $4; 4261 $lib = $4;
3986 $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths 4262 $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths
3987 } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) { 4263 } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) {
3988 # Cooked line from DumpAddressMap. Example: 4264 # Cooked line from DumpAddressMap. Example:
3989 # 40000000-40015000: /lib/ld-2.3.2.so 4265 # 40000000-40015000: /lib/ld-2.3.2.so
3990 $start = HexExtend($1); 4266 $start = HexExtend($1);
3991 $finish = HexExtend($2); 4267 $finish = HexExtend($2);
3992 $offset = $zero_offset; 4268 $offset = $zero_offset;
3993 $lib = $3; 4269 $lib = $3;
3994 } else { 4270 } else {
3995 next; 4271 next;
3996 } 4272 }
3997 4273
3998 # Expand "$build" variable if available 4274 # Expand "$build" variable if available
3999 $lib =~ s/\$build\b/$buildvar/g; 4275 $lib =~ s/\$build\b/$buildvar/g;
4000
4001 $lib = FindLibrary($lib); 4276 $lib = FindLibrary($lib);
4002 4277
4003 # Check for pre-relocated libraries, which use pre-relocated symbol tables 4278 # Check for pre-relocated libraries, which use pre-relocated symbol tables
4004 # and thus require adjusting the offset that we'll use to translate 4279 # and thus require adjusting the offset that we'll use to translate
4005 # VM addresses into symbol table addresses. 4280 # VM addresses into symbol table addresses.
4006 # Only do this if we're not going to fetch the symbol table from a 4281 # Only do this if we're not going to fetch the symbol table from a
4007 # debugging copy of the library. 4282 # debugging copy of the library.
4008 if (!DebuggingLibrary($lib)) { 4283 if (!DebuggingLibrary($lib)) {
4009 my $text = ParseTextSectionHeader($lib); 4284 my $text = ParseTextSectionHeader($lib);
4010 if (defined($text)) { 4285 if (defined($text)) {
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
4407 } 4682 }
4408 4683
4409 sub ShortFunctionName { 4684 sub ShortFunctionName {
4410 my $function = shift; 4685 my $function = shift;
4411 while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types 4686 while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types
4412 while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments 4687 while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments
4413 $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type 4688 $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type
4414 return $function; 4689 return $function;
4415 } 4690 }
4416 4691
4692 # Trim overly long symbols found in disassembler output
4693 sub CleanDisassembly {
4694 my $d = shift;
4695 while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax)
4696 while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments
4697 return $d;
4698 }
4699
4700 # Clean file name for display
4701 sub CleanFileName {
4702 my ($f) = @_;
4703 $f =~ s|^/proc/self/cwd/||;
4704 $f =~ s|^\./||;
4705 return $f;
4706 }
4707
4708 # Make address relative to section and clean up for display
4709 sub UnparseAddress {
4710 my ($offset, $address) = @_;
4711 $address = AddressSub($address, $offset);
4712 $address =~ s/^0x//;
4713 $address =~ s/^0*//;
4714 return $address;
4715 }
4716
4417 ##### Miscellaneous ##### 4717 ##### Miscellaneous #####
4418 4718
4419 # Find the right versions of the above object tools to use. The 4719 # Find the right versions of the above object tools to use. The
4420 # argument is the program file being analyzed, and should be an ELF 4720 # argument is the program file being analyzed, and should be an ELF
4421 # 32-bit or ELF 64-bit executable file. The location of the tools 4721 # 32-bit or ELF 64-bit executable file. The location of the tools
4422 # is determined by considering the following options in this order: 4722 # is determined by considering the following options in this order:
4423 # 1) --tools option, if set 4723 # 1) --tools option, if set
4424 # 2) PPROF_TOOLS environment variable, if set 4724 # 2) PPROF_TOOLS environment variable, if set
4425 # 3) the environment 4725 # 3) the environment
4426 sub ConfigureObjTools { 4726 sub ConfigureObjTools {
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
4899 $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16); 5199 $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);
4900 $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16); 5200 $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);
4901 $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16); 5201 $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);
4902 if ($error_count > 0) { 5202 if ($error_count > 0) {
4903 print STDERR $error_count, " errors: FAILED\n"; 5203 print STDERR $error_count, " errors: FAILED\n";
4904 } else { 5204 } else {
4905 print STDERR "PASS\n"; 5205 print STDERR "PASS\n";
4906 } 5206 }
4907 exit ($error_count); 5207 exit ($error_count);
4908 } 5208 }
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/policy ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698