aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2008-08-20 10:07:35 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-14 04:36:00 -0400
commit8feff1cacc29e9cfdc6d1ce5f2108db87b91046e (patch)
treeb8670f1cd683039263f6f1f98962c8a6ed4d6ad6 /scripts
parentd74fcd1e4e8842d5302cd303ef25cef7e67f68b4 (diff)
ftrace: handle weak symbol functions
During tests and checks, I've discovered that there were failures to convert mcount callers into nops. Looking deeper into these failures, code that was attempted to be changed was not an mcount caller. The current code only updates if the code being changed is what it expects, but I still investigate any time there is a failure. What was happening is that a weak symbol was being used as a reference for other mcount callers. That weak symbol was also referenced elsewhere so the offsets were using the strong symbol and not the function symbol that it was referenced from. This patch changes the setting up of the mcount_loc section to search for a global function that is not weak. It will pick a local over a weak but if only a weak is found in a section, a warning is printed and the mcount location is not recorded (just to be safe). Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'scripts')
-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);