History

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).

Steven Rostedt committed 18 years ago

Commit 8feff1c1 parent d74fcd11 file · +86 −20Browse files

Unified · Split

scripts/recordmcount.pl+86−20
@@ -119,17 +119,19 @@ $mv = "mv" if ((length $mv) == 0); · 118 unmodified lines
119119 #print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " .
120120 # "'$nm' '$rm' '$mv' '$inputfile'\n";
121121
122−my %locals;
123−my %convert;
122+my %locals; # List of local (static) functions
123+my %weak; # List of weak functions
124+my %convert; # List of local functions used that needs conversion
124125
125126 my $type;
126127 my $section_regex; # Find the start of a section
127−my $function_regex; # Find the name of a function (return func name)
128+my $function_regex; # Find the name of a function
129+ # (return offset and func name)
128130 my $mcount_regex; # Find the call site to mcount (return offset)
129131
130132 if ($arch eq "x86_64") {
131133 $section_regex = "Disassembly of section";
132− $function_regex = "<(.*?)>:";
134+ $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
133135 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount([+-]0x[0-9a-zA-Z]+)?\$";
134136 $type = ".quad";
135137
@@ -141,7 +143,7 @@ if ($arch eq "x86_64") { · 5 unmodified lines
141143
142144 } elsif ($arch eq "i386") {
143145 $section_regex = "Disassembly of section";
144− $function_regex = "<(.*?)>:";
146+ $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
145147 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
146148 $type = ".long";
147149
@@ -158,7 +160,6 @@ if ($arch eq "x86_64") { · 10 unmodified lines
158160 my $text_found = 0;
159161 my $read_function = 0;
160162 my $opened = 0;
161−my $text = "";
162163 my $mcount_section = "__mcount_loc";
163164
164165 my $dirname;
@@ -186,46 +187,111 @@ my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s"; · 21 unmodified lines
186187 my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
187188
188189 #
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)
190192 #
191193 open (IN, "$nm $inputfile|") || die "error running $nm";
192194 while (<IN>) {
193195 if (/^[0-9a-fA-F]+\s+t\s+(\S+)/) {
194196 $locals{$1} = 1;
197+ } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) {
198+ $weak{$2} = $1;
195199 }
196200 }
197201 close(IN);
198202
203+my @offsets; # Array of offsets of mcount callers
204+my $ref_func; # reference function to use for offsets
205+my $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+#
213+sub 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+
199247 #
200248 # Step 2: find the sections and mcount call sites
201249 #
202250 open(IN, "$objdump -dr $inputfile|") || die "error running $objdump";
203251
252+my $text;
253+
204254 while (<IN>) {
205255 # is it a section?
206256 if (/$section_regex/) {
207257 $read_function = 1;
258+ # print out any recorded offsets
259+ update_funcs() if ($text_found);
260+
261+ # reset all markers and arrays
208262 $text_found = 0;
263+ undef($ref_func);
264+ undef(@offsets);
265+
209266 # section found, now is this a start of a function?
210267 } elsif ($read_function && /$function_regex/) {
211− $read_function = 0;
212268 $text_found = 1;
213− $text = $1;
214− # is this function static? If so, note this fact.
215− if (defined $locals{$text}) {
216− $convert{$text} = 1;
269+ $offset = hex $1;
270+ $text = $2;
271+
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+ }
217283 }
218− # is this a call site to mcount? If so, print the offset from the section
219− } elsif ($text_found && /$mcount_regex/) {
220− if (!$opened) {
221− open(FILE, ">$mcount_s") || die "can't create $mcount_s\n";
222− $opened = 1;
223− print FILE "\t.section $mcount_section,\"a\",\@progbits\n";
224− }
225− print FILE "\t$type $text + 0x$1\n";
284+ }
285+
286+ # is this a call site to mcount? If so, record it to print later
287+ if ($text_found && /$mcount_regex/) {
288+ $offsets[$#offsets + 1] = hex $1;
226289 }
227290 }
228291
292+# dump out anymore offsets that may have been found
293+update_funcs() if ($text_found);
294+
229295 # If we did not find any mcount callers, we are done (do nothing).
230296 if (!$opened) {
231297 exit(0);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t