History

Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (40 commits) tracing: Separate raw syscall from syscall tracer ring-buffer-benchmark: Add parameters to set produce/consumer priorities tracing, function tracer: Clean up strstrip() usage ring-buffer benchmark: Run producer/consumer threads at nice +19 tracing: Remove the stale include/trace/power.h tracing: Only print objcopy version warning once from recordmcount tracing: Prevent build warning: 'ftrace_graph_buf' defined but not used ring-buffer: Move access to commit_page up into function used tracing: do not disable interrupts for trace_clock_local ring-buffer: Add multiple iterations between benchmark timestamps kprobes: Sanitize struct kretprobe_instance allocations tracing: Fix to use __always_unused attribute compiler: Introduce __always_unused tracing: Exit with error if a weak function is used in recordmcount.pl tracing: Move conditional into update_funcs() in recordmcount.pl tracing: Add regex for weak functions in recordmcount.pl tracing: Move mcount section search to front of loop in recordmcount.pl tracing: Fix objcopy revision check in recordmcount.pl tracing: Check absolute path of input file in recordmcount.pl tracing: Correct the check for number of arguments in recordmcount.pl ...

Linus Torvalds committed 16 years ago

Commit 96fa2b52 parents 7a797cd b8007ef28 files · +856 −518Browse files

Showing the changes to scripts (1 of 28 files). Show all

Unified · Split

scripts/recordmcount.pl+120−99
@@ -6,77 +6,93 @@ · 5 unmodified lines
6# all the offsets to the calls to mcount.6# all the offsets to the calls to mcount.
7#7#
8#8#
9# What we want to end up with is a section in vmlinux called9# What we want to end up with this is that each object file will have a
10# __mcount_loc that contains a list of pointers to all the10# section called __mcount_loc that will hold the list of pointers to mcount
11# call sites in the kernel that call mcount. Later on boot up, the kernel11# callers. After final linking, the vmlinux will have within .init.data the
12# will read this list, save the locations and turn them into nops.12# list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc.
13# When tracing or profiling is later enabled, these locations will then13# Later on boot up, the kernel will read this list, save the locations and turn
14# be converted back to pointers to some function.14# them into nops. When tracing or profiling is later enabled, these locations
15# will then be converted back to pointers to some function.
15#16#
16# This is no easy feat. This script is called just after the original17# This is no easy feat. This script is called just after the original
17# object is compiled and before it is linked.18# object is compiled and before it is linked.
18#19#
19# The references to the call sites are offsets from the section of text20# When parse this object file using 'objdump', the references to the call
20# that the call site is in. Hence, all functions in a section that21# sites are offsets from the section that the call site is in. Hence, all
21# has a call site to mcount, will have the offset from the beginning of22# functions in a section that has a call site to mcount, will have the
22# the section and not the beginning of the function.23# offset from the beginning of the section and not the beginning of the
24# function.
25#
26# But where this section will reside finally in vmlinx is undetermined at
27# this point. So we can't use this kind of offsets to record the final
28# address of this call site.
29#
30# The trick is to change the call offset referring the start of a section to
31# referring a function symbol in this section. During the link step, 'ld' will
32# compute the final address according to the information we record.
23#33#
24# The trick is to find a way to record the beginning of the section.
25# The way we do this is to look at the first function in the section
26# which will also be the location of that section after final link.
27# e.g.34# e.g.
28#35#
29# .section ".sched.text", "ax"36# .section ".sched.text", "ax"
30# .globl my_func
31# my_func:
32# [...]37# [...]
33# call mcount (offset: 0x5)38# func1:
39# [...]
40# call mcount (offset: 0x10)
34# [...]41# [...]
35# ret42# ret
36# other_func:43# .globl fun2
44# func2: (offset: 0x20)
37# [...]45# [...]
38# call mcount (offset: 0x1b)46# [...]
47# ret
48# func3:
49# [...]
50# call mcount (offset: 0x30)
39# [...]51# [...]
40#52#
41# Both relocation offsets for the mcounts in the above example will be53# Both relocation offsets for the mcounts in the above example will be
42# offset from .sched.text. If we make another file called tmp.s with:54# offset from .sched.text. If we choose global symbol func2 as a reference and
55# make another file called tmp.s with the new offsets:
43#56#
44# .section __mcount_loc57# .section __mcount_loc
45# .quad my_func + 0x558# .quad func2 - 0x10
46# .quad my_func + 0x1b59# .quad func2 + 0x10
47#60#
48# We can then compile this tmp.s into tmp.o, and link it to the original61# We can then compile this tmp.s into tmp.o, and link it back to the original
49# object.62# object.
50#63#
51# But this gets hard if my_func is not globl (a static function).64# In our algorithm, we will choose the first global function we meet in this
52# In such a case we have:65# section as the reference. But this gets hard if there is no global functions
66# in this section. In such a case we have to select a local one. E.g. func1:
53#67#
54# .section ".sched.text", "ax"68# .section ".sched.text", "ax"
55# my_func:69# func1:
56# [...]70# [...]
57# call mcount (offset: 0x5)71# call mcount (offset: 0x10)
58# [...]72# [...]
59# ret73# ret
60# other_func:74# func2:
61# [...]75# [...]
62# call mcount (offset: 0x1b)76# call mcount (offset: 0x20)
63# [...]77# [...]
78# .section "other.section"
64#79#
65# If we make the tmp.s the same as above, when we link together with80# If we make the tmp.s the same as above, when we link together with
66# the original object, we will end up with two symbols for my_func:81# the original object, we will end up with two symbols for func1:
67# one local, one global. After final compile, we will end up with82# one local, one global. After final compile, we will end up with
68# an undefined reference to my_func.83# an undefined reference to func1 or a wrong reference to another global
84# func1 in other files.
69#85#
70# Since local objects can reference local variables, we need to find86# Since local objects can reference local variables, we need to find
71# a way to make tmp.o reference the local objects of the original object87# a way to make tmp.o reference the local objects of the original object
72# file after it is linked together. To do this, we convert the my_func88# file after it is linked together. To do this, we convert func1
73# into a global symbol before linking tmp.o. Then after we link tmp.o89# into a global symbol before linking tmp.o. Then after we link tmp.o
74# we will only have a single symbol for my_func that is global.90# we will only have a single symbol for func1 that is global.
75# We can convert my_func back into a local symbol and we are done.91# We can convert func1 back into a local symbol and we are done.
76#92#
77# Here are the steps we take:93# Here are the steps we take:
78#94#
79# 1) Record all the local symbols by using 'nm'95# 1) Record all the local and weak symbols by using 'nm'
80# 2) Use objdump to find all the call site offsets and sections for96# 2) Use objdump to find all the call site offsets and sections for
81# mcount.97# mcount.
82# 3) Compile the list into its own object.98# 3) Compile the list into its own object.
@@ -86,10 +102,8 @@ · 3 unmodified lines
86# 6) Link together this new object with the list object.102# 6) Link together this new object with the list object.
87# 7) Convert the local functions back to local symbols and rename103# 7) Convert the local functions back to local symbols and rename
88# the result as the original object.104# the result as the original object.
89# End.
90# 8) Link the object with the list object.105# 8) Link the object with the list object.
91# 9) Move the result back to the original object.106# 9) Move the result back to the original object.
92# End.
93#107#
94 108
95use strict;109use strict;
@@ -99,7 +113,7 @@ $P =~ s@.*/@@g; · 3 unmodified lines
99 113
100my $V = '0.1';114my $V = '0.1';
101 115
102if ($#ARGV < 7) {116if ($#ARGV != 10) {
103 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";117 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
104 print "version: $V\n";118 print "version: $V\n";
105 exit(1);119 exit(1);
@@ -109,7 +123,7 @@ my ($arch, $bits, $objdump, $objcopy, $cc, · 3 unmodified lines
109 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;123 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
110 124
111# This file refers to mcount and shouldn't be ftraced, so lets' ignore it125# This file refers to mcount and shouldn't be ftraced, so lets' ignore it
112if ($inputfile eq "kernel/trace/ftrace.o") {126if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
113 exit(0);127 exit(0);
114}128}
115 129
@@ -119,6 +133,7 @@ my %text_sections = ( · 3 unmodified lines
119 ".sched.text" => 1,133 ".sched.text" => 1,
120 ".spinlock.text" => 1,134 ".spinlock.text" => 1,
121 ".irqentry.text" => 1,135 ".irqentry.text" => 1,
136 ".text.unlikely" => 1,
122);137);
123 138
124$objdump = "objdump" if ((length $objdump) == 0);139$objdump = "objdump" if ((length $objdump) == 0);
@@ -137,13 +152,47 @@ my %weak; # List of weak functions · 12 unmodified lines
137my %convert; # List of local functions used that needs conversion152my %convert; # List of local functions used that needs conversion
138 153
139my $type;154my $type;
140my $nm_regex; # Find the local functions (return function)155my $local_regex; # Match a local function (return function)
156my $weak_regex; # Match a weak function (return function)
141my $section_regex; # Find the start of a section157my $section_regex; # Find the start of a section
142my $function_regex; # Find the name of a function158my $function_regex; # Find the name of a function
143 # (return offset and func name)159 # (return offset and func name)
144my $mcount_regex; # Find the call site to mcount (return offset)160my $mcount_regex; # Find the call site to mcount (return offset)
145my $alignment; # The .align value to use for $mcount_section161my $alignment; # The .align value to use for $mcount_section
146my $section_type; # Section header plus possible alignment command162my $section_type; # Section header plus possible alignment command
163my $can_use_local = 0; # If we can use local function references
164
165# Shut up recordmcount if user has older objcopy
166my $quiet_recordmcount = ".tmp_quiet_recordmcount";
167my $print_warning = 1;
168$print_warning = 0 if ( -f $quiet_recordmcount);
169
170##
171# check_objcopy - whether objcopy supports --globalize-symbols
172#
173# --globalize-symbols came out in 2.17, we must test the version
174# of objcopy, and if it is less than 2.17, then we can not
175# record local functions.
176sub check_objcopy
177{
178 open (IN, "$objcopy --version |") or die "error running $objcopy";
179 while (<IN>) {
180 if (/objcopy.*\s(\d+)\.(\d+)/) {
181 $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17));
182 last;
183 }
184 }
185 close (IN);
186
187 if (!$can_use_local && $print_warning) {
188 print STDERR "WARNING: could not find objcopy version or version " .
189 "is less than 2.17.\n" .
190 "\tLocal function references are disabled.\n";
191 open (QUIET, ">$quiet_recordmcount");
192 printf QUIET "Disables the warning from recordmcount.pl\n";
193 close QUIET;
194 }
195}
147 196
148if ($arch eq "x86") {197if ($arch eq "x86") {
149 if ($bits == 64) {198 if ($bits == 64) {
@@ -157,7 +206,8 @@ if ($arch eq "x86") { · 7 unmodified lines
157# We base the defaults off of i386, the other archs may206# We base the defaults off of i386, the other archs may
158# feel free to change them in the below if statements.207# feel free to change them in the below if statements.
159#208#
160$nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";209$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";
210$weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)";
161$section_regex = "Disassembly of section\\s+(\\S+):";211$section_regex = "Disassembly of section\\s+(\\S+):";
162$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";212$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
163$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";213$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
@@ -206,7 +256,7 @@ if ($arch eq "x86_64") { · 42 unmodified lines
206 $cc .= " -m32";256 $cc .= " -m32";
207 257
208} elsif ($arch eq "powerpc") {258} elsif ($arch eq "powerpc") {
209 $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";259 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
210 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";260 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
211 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";261 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
212 262
@@ -278,44 +328,17 @@ if ($filename =~ m,^(.*)(\.\S),) { · 65 unmodified lines
278my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";328my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";
279my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";329my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
280 330
281#331check_objcopy();
282# --globalize-symbols came out in 2.17, we must test the version
283# of objcopy, and if it is less than 2.17, then we can not
284# record local functions.
285my $use_locals = 01;
286my $local_warn_once = 0;
287my $found_version = 0;
288
289open (IN, "$objcopy --version |") || die "error running $objcopy";
290while (<IN>) {
291 if (/objcopy.*\s(\d+)\.(\d+)/) {
292 my $major = $1;
293 my $minor = $2;
294
295 $found_version = 1;
296 if ($major < 2 ||
297 ($major == 2 && $minor < 17)) {
298 $use_locals = 0;
299 }
300 last;
301 }
302}
303close (IN);
304
305if (!$found_version) {
306 print STDERR "WARNING: could not find objcopy version.\n" .
307 "\tDisabling local function references.\n";
308}
309 332
310#333#
311# Step 1: find all the local (static functions) and weak symbols.334# Step 1: find all the local (static functions) and weak symbols.
312# 't' is local, 'w/W' is weak (we never use a weak function)335# 't' is local, 'w/W' is weak
313#336#
314open (IN, "$nm $inputfile|") || die "error running $nm";337open (IN, "$nm $inputfile|") || die "error running $nm";
315while (<IN>) {338while (<IN>) {
316 if (/$nm_regex/) {339 if (/$local_regex/) {
317 $locals{$1} = 1;340 $locals{$1} = 1;
318 } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) {341 } elsif (/$weak_regex/) {
319 $weak{$2} = $1;342 $weak{$2} = $1;
320 }343 }
321}344}
@@ -333,26 +356,20 @@ my $offset = 0; # offset of ref_func to section beginning · 11 unmodified lines
333#356#
334sub update_funcs357sub update_funcs
335{358{
336 return if ($#offsets < 0);359 return unless ($ref_func and @offsets);
337
338 defined($ref_func) || die "No function to reference";
339 360
340 # A section only had a weak function, to represent it.361 # Sanity check on weak function. A weak function may be overwritten by
341 # Unfortunately, a weak function may be overwritten by another362 # another function of the same name, making all these offsets incorrect.
342 # function of the same name, making all these offsets incorrect.
343 # To be safe, we simply print a warning and bail.
344 if (defined $weak{$ref_func}) {363 if (defined $weak{$ref_func}) {
345 print STDERR364 die "$inputfile: ERROR: referencing weak function" .
346 "$inputfile: WARNING: referencing weak function" .
347 " $ref_func for mcount\n";365 " $ref_func for mcount\n";
348 return;
349 }366 }
350 367
351 # is this function static? If so, note this fact.368 # is this function static? If so, note this fact.
352 if (defined $locals{$ref_func}) {369 if (defined $locals{$ref_func}) {
353 370
354 # only use locals if objcopy supports globalize-symbols371 # only use locals if objcopy supports globalize-symbols
355 if (!$use_locals) {372 if (!$can_use_local) {
356 return;373 return;
357 }374 }
358 $convert{$ref_func} = 1;375 $convert{$ref_func} = 1;
@@ -378,9 +395,27 @@ open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump"; · 19 unmodified lines
378 395
379my $text;396my $text;
380 397
398
399# read headers first
381my $read_headers = 1;400my $read_headers = 1;
382 401
383while (<IN>) {402while (<IN>) {
403
404 if ($read_headers && /$mcount_section/) {
405 #
406 # Somehow the make process can execute this script on an
407 # object twice. If it does, we would duplicate the mcount
408 # section and it will cause the function tracer self test
409 # to fail. Check if the mcount section exists, and if it does,
410 # warn and exit.
411 #
412 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
413 "\tThis may be an indication that your build is corrupted.\n" .
414 "\tDelete $inputfile and try again. If the same object file\n" .
415 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
416 exit(-1);
417 }
418
384 # is it a section?419 # is it a section?
385 if (/$section_regex/) {420 if (/$section_regex/) {
386 $read_headers = 0;421 $read_headers = 0;
@@ -392,7 +427,7 @@ while (<IN>) { · 5 unmodified lines
392 $read_function = 0;427 $read_function = 0;
393 }428 }
394 # print out any recorded offsets429 # print out any recorded offsets
395 update_funcs() if (defined($ref_func));430 update_funcs();
396 431
397 # reset all markers and arrays432 # reset all markers and arrays
398 $text_found = 0;433 $text_found = 0;
@@ -421,21 +456,7 @@ while (<IN>) { · 22 unmodified lines
421 $offset = hex $1;456 $offset = hex $1;
422 }457 }
423 }458 }
424 } elsif ($read_headers && /$mcount_section/) {
425 #
426 # Somehow the make process can execute this script on an
427 # object twice. If it does, we would duplicate the mcount
428 # section and it will cause the function tracer self test
429 # to fail. Check if the mcount section exists, and if it does,
430 # warn and exit.
431 #
432 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
433 "\tThis may be an indication that your build is corrupted.\n" .
434 "\tDelete $inputfile and try again. If the same object file\n" .
435 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
436 exit(-1);
437 }459 }
438
439 # is this a call site to mcount? If so, record it to print later460 # is this a call site to mcount? If so, record it to print later
440 if ($text_found && /$mcount_regex/) {461 if ($text_found && /$mcount_regex/) {
441 $offsets[$#offsets + 1] = hex $1;462 $offsets[$#offsets + 1] = hex $1;
@@ -443,7 +464,7 @@ while (<IN>) { · 1 unmodified line
443}464}
444 465
445# dump out anymore offsets that may have been found466# dump out anymore offsets that may have been found
446update_funcs() if (defined($ref_func));467update_funcs();
447 468
448# If we did not find any mcount callers, we are done (do nothing).469# If we did not find any mcount callers, we are done (do nothing).
449if (!$opened) {470if (!$opened) {