aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/recordmcount.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/recordmcount.pl')
-rwxr-xr-xscripts/recordmcount.pl106
1 files changed, 86 insertions, 20 deletions
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 36c8355c555e..1891cf9743fc 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -119,17 +119,19 @@ $mv = "mv" if ((length $mv) == 0);
119#print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " . 119#print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " .
120# "'$nm' '$rm' '$mv' '$inputfile'\n"; 120# "'$nm' '$rm' '$mv' '$inputfile'\n";
121 121
122my %locals; 122my %locals; # List of local (static) functions
123my %convert; 123my %weak; # List of weak functions
124my %convert; # List of local functions used that needs conversion
124 125
125my $type; 126my $type;
126my $section_regex; # Find the start of a section 127my $section_regex; # Find the start of a section
127my $function_regex; # Find the name of a function (return func name) 128my $function_regex; # Find the name of a function
129 # (return offset and func name)
128my $mcount_regex; # Find the call site to mcount (return offset) 130my $mcount_regex; # Find the call site to mcount (return offset)
129 131
130if ($arch eq "x86_64") { 132if ($arch eq "x86_64") {
131 $section_regex = "Disassembly of section"; 133 $section_regex = "Disassembly of section";
132 $function_regex = "<(.*?)>:"; 134 $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
133 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$"; 135 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$";
134 $type = ".quad"; 136 $type = ".quad";
135 137
@@ -141,7 +143,7 @@ if ($arch eq "x86_64") {
141 143
142} elsif ($arch eq "i386") { 144} elsif ($arch eq "i386") {
143 $section_regex = "Disassembly of section"; 145 $section_regex = "Disassembly of section";
144 $function_regex = "<(.*?)>:"; 146 $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
145 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; 147 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
146 $type = ".long"; 148 $type = ".long";
147 149
@@ -158,7 +160,6 @@ if ($arch eq "x86_64") {
158my $text_found = 0; 160my $text_found = 0;
159my $read_function = 0; 161my $read_function = 0;
160my $opened = 0; 162my $opened = 0;
161my $text = "";
162my $mcount_section = "__mcount_loc"; 163my $mcount_section = "__mcount_loc";
163 164
164my $dirname; 165my $dirname;
@@ -186,46 +187,111 @@ my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";
186my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o"; 187my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
187 188
188# 189#
189# Step 1: find all the local symbols (static functions). 190# Step 1: find all the local (static functions) and weak symbols.
191# 't' is local, 'w/W' is weak (we never use a weak function)
190# 192#
191open (IN, "$nm $inputfile|") || die "error running $nm"; 193open (IN, "$nm $inputfile|") || die "error running $nm";
192while (<IN>) { 194while (<IN>) {
193 if (/^[0-9a-fA-F]+\s+t\s+(\S+)/) { 195 if (/^[0-9a-fA-F]+\s+t\s+(\S+)/) {
194 $locals{$1} = 1; 196 $locals{$1} = 1;
197 } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) {
198 $weak{$2} = $1;
195 } 199 }
196} 200}
197close(IN); 201close(IN);
198 202
203my @offsets; # Array of offsets of mcount callers
204my $ref_func; # reference function to use for offsets
205my $offset = 0; # offset of ref_func to section beginning
206
207##
208# update_funcs - print out the current mcount callers
209#
210# Go through the list of offsets to callers and write them to
211# the output file in a format that can be read by an assembler.
212#
213sub update_funcs
214{
215 return if ($#offsets < 0);
216
217 defined($ref_func) || die "No function to reference";
218
219 # A section only had a weak function, to represent it.
220 # Unfortunately, a weak function may be overwritten by another
221 # function of the same name, making all these offsets incorrect.
222 # To be safe, we simply print a warning and bail.
223 if (defined $weak{$ref_func}) {
224 print STDERR
225 "$inputfile: WARNING: referencing weak function" .
226 " $ref_func for mcount\n";
227 return;
228 }
229
230 # is this function static? If so, note this fact.
231 if (defined $locals{$ref_func}) {
232 $convert{$ref_func} = 1;
233 }
234
235 # Loop through all the mcount caller offsets and print a reference
236 # to the caller based from the ref_func.
237 for (my $i=0; $i <= $#offsets; $i++) {
238 if (!$opened) {
239 open(FILE, ">$mcount_s") || die "can't create $mcount_s\n";
240 $opened = 1;
241 print FILE "\t.section $mcount_section,\"a\",\@progbits\n";
242 }
243 printf FILE "\t%s %s + %d\n", $type, $ref_func, $offsets[$i] - $offset;
244 }
245}
246
199# 247#
200# Step 2: find the sections and mcount call sites 248# Step 2: find the sections and mcount call sites
201# 249#
202open(IN, "$objdump -dr $inputfile|") || die "error running $objdump"; 250open(IN, "$objdump -dr $inputfile|") || die "error running $objdump";
203 251
252my $text;
253
204while (<IN>) { 254while (<IN>) {
205 # is it a section? 255 # is it a section?
206 if (/$section_regex/) { 256 if (/$section_regex/) {
207 $read_function = 1; 257 $read_function = 1;
258 # print out any recorded offsets
259 update_funcs() if ($text_found);
260
261 # reset all markers and arrays
208 $text_found = 0; 262 $text_found = 0;
263 undef($ref_func);
264 undef(@offsets);
265
209 # section found, now is this a start of a function? 266 # section found, now is this a start of a function?
210 } elsif ($read_function && /$function_regex/) { 267 } elsif ($read_function && /$function_regex/) {
211 $read_function = 0;
212 $text_found = 1; 268 $text_found = 1;
213 $text = $1; 269 $offset = hex $1;
214 # is this function static? If so, note this fact. 270 $text = $2;
215 if (defined $locals{$text}) { 271
216 $convert{$text} = 1; 272 # if this is either a local function or a weak function
273 # keep looking for functions that are global that
274 # we can use safely.
275 if (!defined($locals{$text}) && !defined($weak{$text})) {
276 $ref_func = $text;
277 $read_function = 0;
278 } else {
279 # if we already have a function, and this is weak, skip it
280 if (!defined($ref_func) || !defined($weak{$text})) {
281 $ref_func = $text;
282 }
217 } 283 }
218 # is this a call site to mcount? If so, print the offset from the section 284 }
219 } elsif ($text_found && /$mcount_regex/) { 285
220 if (!$opened) { 286 # is this a call site to mcount? If so, record it to print later
221 open(FILE, ">$mcount_s") || die "can't create $mcount_s\n"; 287 if ($text_found && /$mcount_regex/) {
222 $opened = 1; 288 $offsets[$#offsets + 1] = hex $1;
223 print FILE "\t.section $mcount_section,\"a\",\@progbits\n";
224 }
225 print FILE "\t$type $text + 0x$1\n";
226 } 289 }
227} 290}
228 291
292# dump out anymore offsets that may have been found
293update_funcs() if ($text_found);
294
229# If we did not find any mcount callers, we are done (do nothing). 295# If we did not find any mcount callers, we are done (do nothing).
230if (!$opened) { 296if (!$opened) {
231 exit(0); 297 exit(0);