Commit 2d8eedad9233d4771fb3134f50e5c5a09e28352c

Authored by Tony Lu
Committed by Chris Metcalf
1 parent dc1ccc4815

ftrace: default to tilegx if ARCH=tile is specified

This matches the existing behavior in arch/tile/Makefile for defconfig.

Reported-by: fengguang.wu@intel.com
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Tony Lu <zlu@tilera.com>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>

Showing 1 changed file with 2 additions and 1 deletions Inline Diff

scripts/recordmcount.pl
1 #!/usr/bin/perl -w 1 #!/usr/bin/perl -w
2 # (c) 2008, Steven Rostedt <srostedt@redhat.com> 2 # (c) 2008, Steven Rostedt <srostedt@redhat.com>
3 # Licensed under the terms of the GNU GPL License version 2 3 # Licensed under the terms of the GNU GPL License version 2
4 # 4 #
5 # recordmcount.pl - makes a section called __mcount_loc that holds 5 # recordmcount.pl - makes a section called __mcount_loc that holds
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 this is that each object file will have a 9 # What we want to end up with this is that each object file will have a
10 # section called __mcount_loc that will hold the list of pointers to mcount 10 # section called __mcount_loc that will hold the list of pointers to mcount
11 # callers. After final linking, the vmlinux will have within .init.data the 11 # callers. After final linking, the vmlinux will have within .init.data the
12 # list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc. 12 # list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc.
13 # Later on boot up, the kernel will read this list, save the locations and turn 13 # Later on boot up, the kernel will read this list, save the locations and turn
14 # them into nops. When tracing or profiling is later enabled, these locations 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 # will then be converted back to pointers to some function.
16 # 16 #
17 # This is no easy feat. This script is called just after the original 17 # This is no easy feat. This script is called just after the original
18 # object is compiled and before it is linked. 18 # object is compiled and before it is linked.
19 # 19 #
20 # When parse this object file using 'objdump', the references to the call 20 # When parse this object file using 'objdump', the references to the call
21 # sites are offsets from the section that the call site is in. Hence, all 21 # sites are offsets from the section that the call site is in. Hence, all
22 # functions in a section that has a call site to mcount, will have the 22 # functions in a section that has a call site to mcount, will have the
23 # offset from the beginning of the section and not the beginning of the 23 # offset from the beginning of the section and not the beginning of the
24 # function. 24 # function.
25 # 25 #
26 # But where this section will reside finally in vmlinx is undetermined at 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 27 # this point. So we can't use this kind of offsets to record the final
28 # address of this call site. 28 # address of this call site.
29 # 29 #
30 # The trick is to change the call offset referring the start of a section to 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 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. 32 # compute the final address according to the information we record.
33 # 33 #
34 # e.g. 34 # e.g.
35 # 35 #
36 # .section ".sched.text", "ax" 36 # .section ".sched.text", "ax"
37 # [...] 37 # [...]
38 # func1: 38 # func1:
39 # [...] 39 # [...]
40 # call mcount (offset: 0x10) 40 # call mcount (offset: 0x10)
41 # [...] 41 # [...]
42 # ret 42 # ret
43 # .globl fun2 43 # .globl fun2
44 # func2: (offset: 0x20) 44 # func2: (offset: 0x20)
45 # [...] 45 # [...]
46 # [...] 46 # [...]
47 # ret 47 # ret
48 # func3: 48 # func3:
49 # [...] 49 # [...]
50 # call mcount (offset: 0x30) 50 # call mcount (offset: 0x30)
51 # [...] 51 # [...]
52 # 52 #
53 # Both relocation offsets for the mcounts in the above example will be 53 # Both relocation offsets for the mcounts in the above example will be
54 # offset from .sched.text. If we choose global symbol func2 as a reference and 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: 55 # make another file called tmp.s with the new offsets:
56 # 56 #
57 # .section __mcount_loc 57 # .section __mcount_loc
58 # .quad func2 - 0x10 58 # .quad func2 - 0x10
59 # .quad func2 + 0x10 59 # .quad func2 + 0x10
60 # 60 #
61 # We can then compile this tmp.s into tmp.o, and link it back to the original 61 # We can then compile this tmp.s into tmp.o, and link it back to the original
62 # object. 62 # object.
63 # 63 #
64 # In our algorithm, we will choose the first global function we meet in this 64 # In our algorithm, we will choose the first global function we meet in this
65 # section as the reference. But this gets hard if there is no global functions 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: 66 # in this section. In such a case we have to select a local one. E.g. func1:
67 # 67 #
68 # .section ".sched.text", "ax" 68 # .section ".sched.text", "ax"
69 # func1: 69 # func1:
70 # [...] 70 # [...]
71 # call mcount (offset: 0x10) 71 # call mcount (offset: 0x10)
72 # [...] 72 # [...]
73 # ret 73 # ret
74 # func2: 74 # func2:
75 # [...] 75 # [...]
76 # call mcount (offset: 0x20) 76 # call mcount (offset: 0x20)
77 # [...] 77 # [...]
78 # .section "other.section" 78 # .section "other.section"
79 # 79 #
80 # If we make the tmp.s the same as above, when we link together with 80 # If we make the tmp.s the same as above, when we link together with
81 # the original object, we will end up with two symbols for func1: 81 # the original object, we will end up with two symbols for func1:
82 # one local, one global. After final compile, we will end up with 82 # one local, one global. After final compile, we will end up with
83 # an undefined reference to func1 or a wrong reference to another global 83 # an undefined reference to func1 or a wrong reference to another global
84 # func1 in other files. 84 # func1 in other files.
85 # 85 #
86 # Since local objects can reference local variables, we need to find 86 # Since local objects can reference local variables, we need to find
87 # a way to make tmp.o reference the local objects of the original object 87 # a way to make tmp.o reference the local objects of the original object
88 # file after it is linked together. To do this, we convert func1 88 # file after it is linked together. To do this, we convert func1
89 # into a global symbol before linking tmp.o. Then after we link tmp.o 89 # into a global symbol before linking tmp.o. Then after we link tmp.o
90 # we will only have a single symbol for func1 that is global. 90 # we will only have a single symbol for func1 that is global.
91 # We can convert func1 back into a local symbol and we are done. 91 # We can convert func1 back into a local symbol and we are done.
92 # 92 #
93 # Here are the steps we take: 93 # Here are the steps we take:
94 # 94 #
95 # 1) Record all the local and weak symbols by using 'nm' 95 # 1) Record all the local and weak symbols by using 'nm'
96 # 2) Use objdump to find all the call site offsets and sections for 96 # 2) Use objdump to find all the call site offsets and sections for
97 # mcount. 97 # mcount.
98 # 3) Compile the list into its own object. 98 # 3) Compile the list into its own object.
99 # 4) Do we have to deal with local functions? If not, go to step 8. 99 # 4) Do we have to deal with local functions? If not, go to step 8.
100 # 5) Make an object that converts these local functions to global symbols 100 # 5) Make an object that converts these local functions to global symbols
101 # with objcopy. 101 # with objcopy.
102 # 6) Link together this new object with the list object. 102 # 6) Link together this new object with the list object.
103 # 7) Convert the local functions back to local symbols and rename 103 # 7) Convert the local functions back to local symbols and rename
104 # the result as the original object. 104 # the result as the original object.
105 # 8) Link the object with the list object. 105 # 8) Link the object with the list object.
106 # 9) Move the result back to the original object. 106 # 9) Move the result back to the original object.
107 # 107 #
108 108
109 use strict; 109 use strict;
110 110
111 my $P = $0; 111 my $P = $0;
112 $P =~ s@.*/@@g; 112 $P =~ s@.*/@@g;
113 113
114 my $V = '0.1'; 114 my $V = '0.1';
115 115
116 if ($#ARGV != 11) { 116 if ($#ARGV != 11) {
117 print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n"; 117 print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
118 print "version: $V\n"; 118 print "version: $V\n";
119 exit(1); 119 exit(1);
120 } 120 }
121 121
122 my ($arch, $endian, $bits, $objdump, $objcopy, $cc, 122 my ($arch, $endian, $bits, $objdump, $objcopy, $cc,
123 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV; 123 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
124 124
125 # This file refers to mcount and shouldn't be ftraced, so lets' ignore it 125 # This file refers to mcount and shouldn't be ftraced, so lets' ignore it
126 if ($inputfile =~ m,kernel/trace/ftrace\.o$,) { 126 if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
127 exit(0); 127 exit(0);
128 } 128 }
129 129
130 # Acceptable sections to record. 130 # Acceptable sections to record.
131 my %text_sections = ( 131 my %text_sections = (
132 ".text" => 1, 132 ".text" => 1,
133 ".ref.text" => 1, 133 ".ref.text" => 1,
134 ".sched.text" => 1, 134 ".sched.text" => 1,
135 ".spinlock.text" => 1, 135 ".spinlock.text" => 1,
136 ".irqentry.text" => 1, 136 ".irqentry.text" => 1,
137 ".kprobes.text" => 1, 137 ".kprobes.text" => 1,
138 ".text.unlikely" => 1, 138 ".text.unlikely" => 1,
139 ); 139 );
140 140
141 # Note: we are nice to C-programmers here, thus we skip the '||='-idiom. 141 # Note: we are nice to C-programmers here, thus we skip the '||='-idiom.
142 $objdump = 'objdump' if (!$objdump); 142 $objdump = 'objdump' if (!$objdump);
143 $objcopy = 'objcopy' if (!$objcopy); 143 $objcopy = 'objcopy' if (!$objcopy);
144 $cc = 'gcc' if (!$cc); 144 $cc = 'gcc' if (!$cc);
145 $ld = 'ld' if (!$ld); 145 $ld = 'ld' if (!$ld);
146 $nm = 'nm' if (!$nm); 146 $nm = 'nm' if (!$nm);
147 $rm = 'rm' if (!$rm); 147 $rm = 'rm' if (!$rm);
148 $mv = 'mv' if (!$mv); 148 $mv = 'mv' if (!$mv);
149 149
150 #print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " . 150 #print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " .
151 # "'$nm' '$rm' '$mv' '$inputfile'\n"; 151 # "'$nm' '$rm' '$mv' '$inputfile'\n";
152 152
153 my %locals; # List of local (static) functions 153 my %locals; # List of local (static) functions
154 my %weak; # List of weak functions 154 my %weak; # List of weak functions
155 my %convert; # List of local functions used that needs conversion 155 my %convert; # List of local functions used that needs conversion
156 156
157 my $type; 157 my $type;
158 my $local_regex; # Match a local function (return function) 158 my $local_regex; # Match a local function (return function)
159 my $weak_regex; # Match a weak function (return function) 159 my $weak_regex; # Match a weak function (return function)
160 my $section_regex; # Find the start of a section 160 my $section_regex; # Find the start of a section
161 my $function_regex; # Find the name of a function 161 my $function_regex; # Find the name of a function
162 # (return offset and func name) 162 # (return offset and func name)
163 my $mcount_regex; # Find the call site to mcount (return offset) 163 my $mcount_regex; # Find the call site to mcount (return offset)
164 my $mcount_adjust; # Address adjustment to mcount offset 164 my $mcount_adjust; # Address adjustment to mcount offset
165 my $alignment; # The .align value to use for $mcount_section 165 my $alignment; # The .align value to use for $mcount_section
166 my $section_type; # Section header plus possible alignment command 166 my $section_type; # Section header plus possible alignment command
167 my $can_use_local = 0; # If we can use local function references 167 my $can_use_local = 0; # If we can use local function references
168 168
169 # Shut up recordmcount if user has older objcopy 169 # Shut up recordmcount if user has older objcopy
170 my $quiet_recordmcount = ".tmp_quiet_recordmcount"; 170 my $quiet_recordmcount = ".tmp_quiet_recordmcount";
171 my $print_warning = 1; 171 my $print_warning = 1;
172 $print_warning = 0 if ( -f $quiet_recordmcount); 172 $print_warning = 0 if ( -f $quiet_recordmcount);
173 173
174 ## 174 ##
175 # check_objcopy - whether objcopy supports --globalize-symbols 175 # check_objcopy - whether objcopy supports --globalize-symbols
176 # 176 #
177 # --globalize-symbols came out in 2.17, we must test the version 177 # --globalize-symbols came out in 2.17, we must test the version
178 # of objcopy, and if it is less than 2.17, then we can not 178 # of objcopy, and if it is less than 2.17, then we can not
179 # record local functions. 179 # record local functions.
180 sub check_objcopy 180 sub check_objcopy
181 { 181 {
182 open (IN, "$objcopy --version |") or die "error running $objcopy"; 182 open (IN, "$objcopy --version |") or die "error running $objcopy";
183 while (<IN>) { 183 while (<IN>) {
184 if (/objcopy.*\s(\d+)\.(\d+)/) { 184 if (/objcopy.*\s(\d+)\.(\d+)/) {
185 $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17)); 185 $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17));
186 last; 186 last;
187 } 187 }
188 } 188 }
189 close (IN); 189 close (IN);
190 190
191 if (!$can_use_local && $print_warning) { 191 if (!$can_use_local && $print_warning) {
192 print STDERR "WARNING: could not find objcopy version or version " . 192 print STDERR "WARNING: could not find objcopy version or version " .
193 "is less than 2.17.\n" . 193 "is less than 2.17.\n" .
194 "\tLocal function references are disabled.\n"; 194 "\tLocal function references are disabled.\n";
195 open (QUIET, ">$quiet_recordmcount"); 195 open (QUIET, ">$quiet_recordmcount");
196 printf QUIET "Disables the warning from recordmcount.pl\n"; 196 printf QUIET "Disables the warning from recordmcount.pl\n";
197 close QUIET; 197 close QUIET;
198 } 198 }
199 } 199 }
200 200
201 if ($arch =~ /(x86(_64)?)|(i386)/) { 201 if ($arch =~ /(x86(_64)?)|(i386)/) {
202 if ($bits == 64) { 202 if ($bits == 64) {
203 $arch = "x86_64"; 203 $arch = "x86_64";
204 } else { 204 } else {
205 $arch = "i386"; 205 $arch = "i386";
206 } 206 }
207 } 207 }
208 208
209 # 209 #
210 # We base the defaults off of i386, the other archs may 210 # We base the defaults off of i386, the other archs may
211 # feel free to change them in the below if statements. 211 # feel free to change them in the below if statements.
212 # 212 #
213 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; 213 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";
214 $weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)"; 214 $weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)";
215 $section_regex = "Disassembly of section\\s+(\\S+):"; 215 $section_regex = "Disassembly of section\\s+(\\S+):";
216 $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; 216 $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
217 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)\$"; 217 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)\$";
218 $section_type = '@progbits'; 218 $section_type = '@progbits';
219 $mcount_adjust = 0; 219 $mcount_adjust = 0;
220 $type = ".long"; 220 $type = ".long";
221 221
222 if ($arch eq "x86_64") { 222 if ($arch eq "x86_64") {
223 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)([+-]0x[0-9a-zA-Z]+)?\$"; 223 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)([+-]0x[0-9a-zA-Z]+)?\$";
224 $type = ".quad"; 224 $type = ".quad";
225 $alignment = 8; 225 $alignment = 8;
226 $mcount_adjust = -1; 226 $mcount_adjust = -1;
227 227
228 # force flags for this arch 228 # force flags for this arch
229 $ld .= " -m elf_x86_64"; 229 $ld .= " -m elf_x86_64";
230 $objdump .= " -M x86-64"; 230 $objdump .= " -M x86-64";
231 $objcopy .= " -O elf64-x86-64"; 231 $objcopy .= " -O elf64-x86-64";
232 $cc .= " -m64"; 232 $cc .= " -m64";
233 233
234 } elsif ($arch eq "i386") { 234 } elsif ($arch eq "i386") {
235 $alignment = 4; 235 $alignment = 4;
236 $mcount_adjust = -1; 236 $mcount_adjust = -1;
237 237
238 # force flags for this arch 238 # force flags for this arch
239 $ld .= " -m elf_i386"; 239 $ld .= " -m elf_i386";
240 $objdump .= " -M i386"; 240 $objdump .= " -M i386";
241 $objcopy .= " -O elf32-i386"; 241 $objcopy .= " -O elf32-i386";
242 $cc .= " -m32"; 242 $cc .= " -m32";
243 243
244 } elsif ($arch eq "s390" && $bits == 32) { 244 } elsif ($arch eq "s390" && $bits == 32) {
245 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$"; 245 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$";
246 $mcount_adjust = -4; 246 $mcount_adjust = -4;
247 $alignment = 4; 247 $alignment = 4;
248 $ld .= " -m elf_s390"; 248 $ld .= " -m elf_s390";
249 $cc .= " -m31"; 249 $cc .= " -m31";
250 250
251 } elsif ($arch eq "s390" && $bits == 64) { 251 } elsif ($arch eq "s390" && $bits == 64) {
252 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$"; 252 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
253 $mcount_adjust = -8; 253 $mcount_adjust = -8;
254 $alignment = 8; 254 $alignment = 8;
255 $type = ".quad"; 255 $type = ".quad";
256 $ld .= " -m elf64_s390"; 256 $ld .= " -m elf64_s390";
257 $cc .= " -m64"; 257 $cc .= " -m64";
258 258
259 } elsif ($arch eq "sh") { 259 } elsif ($arch eq "sh") {
260 $alignment = 2; 260 $alignment = 2;
261 261
262 # force flags for this arch 262 # force flags for this arch
263 $ld .= " -m shlelf_linux"; 263 $ld .= " -m shlelf_linux";
264 $objcopy .= " -O elf32-sh-linux"; 264 $objcopy .= " -O elf32-sh-linux";
265 $cc .= " -m32"; 265 $cc .= " -m32";
266 266
267 } elsif ($arch eq "powerpc") { 267 } elsif ($arch eq "powerpc") {
268 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; 268 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
269 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:"; 269 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
270 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; 270 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
271 271
272 if ($bits == 64) { 272 if ($bits == 64) {
273 $type = ".quad"; 273 $type = ".quad";
274 } 274 }
275 275
276 } elsif ($arch eq "arm") { 276 } elsif ($arch eq "arm") {
277 $alignment = 2; 277 $alignment = 2;
278 $section_type = '%progbits'; 278 $section_type = '%progbits';
279 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" . 279 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
280 "\\s+(__gnu_mcount_nc|mcount)\$"; 280 "\\s+(__gnu_mcount_nc|mcount)\$";
281 281
282 } elsif ($arch eq "ia64") { 282 } elsif ($arch eq "ia64") {
283 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 283 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
284 $type = "data8"; 284 $type = "data8";
285 285
286 if ($is_module eq "0") { 286 if ($is_module eq "0") {
287 $cc .= " -mconstant-gp"; 287 $cc .= " -mconstant-gp";
288 } 288 }
289 } elsif ($arch eq "sparc64") { 289 } elsif ($arch eq "sparc64") {
290 # In the objdump output there are giblets like: 290 # In the objdump output there are giblets like:
291 # 0000000000000000 <igmp_net_exit-0x18>: 291 # 0000000000000000 <igmp_net_exit-0x18>:
292 # As there's some data blobs that get emitted into the 292 # As there's some data blobs that get emitted into the
293 # text section before the first instructions and the first 293 # text section before the first instructions and the first
294 # real symbols. We don't want to match that, so to combat 294 # real symbols. We don't want to match that, so to combat
295 # this we use '\w' so we'll match just plain symbol names, 295 # this we use '\w' so we'll match just plain symbol names,
296 # and not those that also include hex offsets inside of the 296 # and not those that also include hex offsets inside of the
297 # '<>' brackets. Actually the generic function_regex setting 297 # '<>' brackets. Actually the generic function_regex setting
298 # could safely use this too. 298 # could safely use this too.
299 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\w*?)>:"; 299 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\w*?)>:";
300 300
301 # Sparc64 calls '_mcount' instead of plain 'mcount'. 301 # Sparc64 calls '_mcount' instead of plain 'mcount'.
302 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 302 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
303 303
304 $alignment = 8; 304 $alignment = 8;
305 $type = ".xword"; 305 $type = ".xword";
306 $ld .= " -m elf64_sparc"; 306 $ld .= " -m elf64_sparc";
307 $cc .= " -m64"; 307 $cc .= " -m64";
308 $objcopy .= " -O elf64-sparc"; 308 $objcopy .= " -O elf64-sparc";
309 } elsif ($arch eq "mips") { 309 } elsif ($arch eq "mips") {
310 # To enable module support, we need to enable the -mlong-calls option 310 # To enable module support, we need to enable the -mlong-calls option
311 # of gcc for module, after using this option, we can not get the real 311 # of gcc for module, after using this option, we can not get the real
312 # offset of the calling to _mcount, but the offset of the lui 312 # offset of the calling to _mcount, but the offset of the lui
313 # instruction or the addiu one. herein, we record the address of the 313 # instruction or the addiu one. herein, we record the address of the
314 # first one, and then we can replace this instruction by a branch 314 # first one, and then we can replace this instruction by a branch
315 # instruction to jump over the profiling function to filter the 315 # instruction to jump over the profiling function to filter the
316 # indicated functions, or swith back to the lui instruction to trace 316 # indicated functions, or swith back to the lui instruction to trace
317 # them, which means dynamic tracing. 317 # them, which means dynamic tracing.
318 # 318 #
319 # c: 3c030000 lui v1,0x0 319 # c: 3c030000 lui v1,0x0
320 # c: R_MIPS_HI16 _mcount 320 # c: R_MIPS_HI16 _mcount
321 # c: R_MIPS_NONE *ABS* 321 # c: R_MIPS_NONE *ABS*
322 # c: R_MIPS_NONE *ABS* 322 # c: R_MIPS_NONE *ABS*
323 # 10: 64630000 daddiu v1,v1,0 323 # 10: 64630000 daddiu v1,v1,0
324 # 10: R_MIPS_LO16 _mcount 324 # 10: R_MIPS_LO16 _mcount
325 # 10: R_MIPS_NONE *ABS* 325 # 10: R_MIPS_NONE *ABS*
326 # 10: R_MIPS_NONE *ABS* 326 # 10: R_MIPS_NONE *ABS*
327 # 14: 03e0082d move at,ra 327 # 14: 03e0082d move at,ra
328 # 18: 0060f809 jalr v1 328 # 18: 0060f809 jalr v1
329 # 329 #
330 # for the kernel: 330 # for the kernel:
331 # 331 #
332 # 10: 03e0082d move at,ra 332 # 10: 03e0082d move at,ra
333 # 14: 0c000000 jal 0 <loongson_halt> 333 # 14: 0c000000 jal 0 <loongson_halt>
334 # 14: R_MIPS_26 _mcount 334 # 14: R_MIPS_26 _mcount
335 # 14: R_MIPS_NONE *ABS* 335 # 14: R_MIPS_NONE *ABS*
336 # 14: R_MIPS_NONE *ABS* 336 # 14: R_MIPS_NONE *ABS*
337 # 18: 00020021 nop 337 # 18: 00020021 nop
338 if ($is_module eq "0") { 338 if ($is_module eq "0") {
339 $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$"; 339 $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$";
340 } else { 340 } else {
341 $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$"; 341 $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
342 } 342 }
343 $objdump .= " -Melf-trad".$endian."mips "; 343 $objdump .= " -Melf-trad".$endian."mips ";
344 344
345 if ($endian eq "big") { 345 if ($endian eq "big") {
346 $endian = " -EB "; 346 $endian = " -EB ";
347 $ld .= " -melf".$bits."btsmip"; 347 $ld .= " -melf".$bits."btsmip";
348 } else { 348 } else {
349 $endian = " -EL "; 349 $endian = " -EL ";
350 $ld .= " -melf".$bits."ltsmip"; 350 $ld .= " -melf".$bits."ltsmip";
351 } 351 }
352 352
353 $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian; 353 $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian;
354 $ld .= $endian; 354 $ld .= $endian;
355 355
356 if ($bits == 64) { 356 if ($bits == 64) {
357 $function_regex = 357 $function_regex =
358 "^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:"; 358 "^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:";
359 $type = ".dword"; 359 $type = ".dword";
360 } 360 }
361 } elsif ($arch eq "microblaze") { 361 } elsif ($arch eq "microblaze") {
362 # Microblaze calls '_mcount' instead of plain 'mcount'. 362 # Microblaze calls '_mcount' instead of plain 'mcount'.
363 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 363 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
364 } elsif ($arch eq "blackfin") { 364 } elsif ($arch eq "blackfin") {
365 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$"; 365 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
366 $mcount_adjust = -4; 366 $mcount_adjust = -4;
367 } elsif ($arch eq "tilegx") { 367 } elsif ($arch eq "tilegx" || $arch eq "tile") {
368 # Default to the newer TILE-Gx architecture if only "tile" is given.
368 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$"; 369 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
369 $type = ".quad"; 370 $type = ".quad";
370 $alignment = 8; 371 $alignment = 8;
371 } else { 372 } else {
372 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; 373 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
373 } 374 }
374 375
375 my $text_found = 0; 376 my $text_found = 0;
376 my $read_function = 0; 377 my $read_function = 0;
377 my $opened = 0; 378 my $opened = 0;
378 my $mcount_section = "__mcount_loc"; 379 my $mcount_section = "__mcount_loc";
379 380
380 my $dirname; 381 my $dirname;
381 my $filename; 382 my $filename;
382 my $prefix; 383 my $prefix;
383 my $ext; 384 my $ext;
384 385
385 if ($inputfile =~ m,^(.*)/([^/]*)$,) { 386 if ($inputfile =~ m,^(.*)/([^/]*)$,) {
386 $dirname = $1; 387 $dirname = $1;
387 $filename = $2; 388 $filename = $2;
388 } else { 389 } else {
389 $dirname = "."; 390 $dirname = ".";
390 $filename = $inputfile; 391 $filename = $inputfile;
391 } 392 }
392 393
393 if ($filename =~ m,^(.*)(\.\S),) { 394 if ($filename =~ m,^(.*)(\.\S),) {
394 $prefix = $1; 395 $prefix = $1;
395 $ext = $2; 396 $ext = $2;
396 } else { 397 } else {
397 $prefix = $filename; 398 $prefix = $filename;
398 $ext = ""; 399 $ext = "";
399 } 400 }
400 401
401 my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s"; 402 my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";
402 my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o"; 403 my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
403 404
404 check_objcopy(); 405 check_objcopy();
405 406
406 # 407 #
407 # Step 1: find all the local (static functions) and weak symbols. 408 # Step 1: find all the local (static functions) and weak symbols.
408 # 't' is local, 'w/W' is weak 409 # 't' is local, 'w/W' is weak
409 # 410 #
410 open (IN, "$nm $inputfile|") || die "error running $nm"; 411 open (IN, "$nm $inputfile|") || die "error running $nm";
411 while (<IN>) { 412 while (<IN>) {
412 if (/$local_regex/) { 413 if (/$local_regex/) {
413 $locals{$1} = 1; 414 $locals{$1} = 1;
414 } elsif (/$weak_regex/) { 415 } elsif (/$weak_regex/) {
415 $weak{$2} = $1; 416 $weak{$2} = $1;
416 } 417 }
417 } 418 }
418 close(IN); 419 close(IN);
419 420
420 my @offsets; # Array of offsets of mcount callers 421 my @offsets; # Array of offsets of mcount callers
421 my $ref_func; # reference function to use for offsets 422 my $ref_func; # reference function to use for offsets
422 my $offset = 0; # offset of ref_func to section beginning 423 my $offset = 0; # offset of ref_func to section beginning
423 424
424 ## 425 ##
425 # update_funcs - print out the current mcount callers 426 # update_funcs - print out the current mcount callers
426 # 427 #
427 # Go through the list of offsets to callers and write them to 428 # Go through the list of offsets to callers and write them to
428 # the output file in a format that can be read by an assembler. 429 # the output file in a format that can be read by an assembler.
429 # 430 #
430 sub update_funcs 431 sub update_funcs
431 { 432 {
432 return unless ($ref_func and @offsets); 433 return unless ($ref_func and @offsets);
433 434
434 # Sanity check on weak function. A weak function may be overwritten by 435 # Sanity check on weak function. A weak function may be overwritten by
435 # another function of the same name, making all these offsets incorrect. 436 # another function of the same name, making all these offsets incorrect.
436 if (defined $weak{$ref_func}) { 437 if (defined $weak{$ref_func}) {
437 die "$inputfile: ERROR: referencing weak function" . 438 die "$inputfile: ERROR: referencing weak function" .
438 " $ref_func for mcount\n"; 439 " $ref_func for mcount\n";
439 } 440 }
440 441
441 # is this function static? If so, note this fact. 442 # is this function static? If so, note this fact.
442 if (defined $locals{$ref_func}) { 443 if (defined $locals{$ref_func}) {
443 444
444 # only use locals if objcopy supports globalize-symbols 445 # only use locals if objcopy supports globalize-symbols
445 if (!$can_use_local) { 446 if (!$can_use_local) {
446 return; 447 return;
447 } 448 }
448 $convert{$ref_func} = 1; 449 $convert{$ref_func} = 1;
449 } 450 }
450 451
451 # Loop through all the mcount caller offsets and print a reference 452 # Loop through all the mcount caller offsets and print a reference
452 # to the caller based from the ref_func. 453 # to the caller based from the ref_func.
453 if (!$opened) { 454 if (!$opened) {
454 open(FILE, ">$mcount_s") || die "can't create $mcount_s\n"; 455 open(FILE, ">$mcount_s") || die "can't create $mcount_s\n";
455 $opened = 1; 456 $opened = 1;
456 print FILE "\t.section $mcount_section,\"a\",$section_type\n"; 457 print FILE "\t.section $mcount_section,\"a\",$section_type\n";
457 print FILE "\t.align $alignment\n" if (defined($alignment)); 458 print FILE "\t.align $alignment\n" if (defined($alignment));
458 } 459 }
459 foreach my $cur_offset (@offsets) { 460 foreach my $cur_offset (@offsets) {
460 printf FILE "\t%s %s + %d\n", $type, $ref_func, $cur_offset - $offset; 461 printf FILE "\t%s %s + %d\n", $type, $ref_func, $cur_offset - $offset;
461 } 462 }
462 } 463 }
463 464
464 # 465 #
465 # Step 2: find the sections and mcount call sites 466 # Step 2: find the sections and mcount call sites
466 # 467 #
467 open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump"; 468 open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump";
468 469
469 my $text; 470 my $text;
470 471
471 472
472 # read headers first 473 # read headers first
473 my $read_headers = 1; 474 my $read_headers = 1;
474 475
475 while (<IN>) { 476 while (<IN>) {
476 477
477 if ($read_headers && /$mcount_section/) { 478 if ($read_headers && /$mcount_section/) {
478 # 479 #
479 # Somehow the make process can execute this script on an 480 # Somehow the make process can execute this script on an
480 # object twice. If it does, we would duplicate the mcount 481 # object twice. If it does, we would duplicate the mcount
481 # section and it will cause the function tracer self test 482 # section and it will cause the function tracer self test
482 # to fail. Check if the mcount section exists, and if it does, 483 # to fail. Check if the mcount section exists, and if it does,
483 # warn and exit. 484 # warn and exit.
484 # 485 #
485 print STDERR "ERROR: $mcount_section already in $inputfile\n" . 486 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
486 "\tThis may be an indication that your build is corrupted.\n" . 487 "\tThis may be an indication that your build is corrupted.\n" .
487 "\tDelete $inputfile and try again. If the same object file\n" . 488 "\tDelete $inputfile and try again. If the same object file\n" .
488 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n"; 489 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
489 exit(-1); 490 exit(-1);
490 } 491 }
491 492
492 # is it a section? 493 # is it a section?
493 if (/$section_regex/) { 494 if (/$section_regex/) {
494 $read_headers = 0; 495 $read_headers = 0;
495 496
496 # Only record text sections that we know are safe 497 # Only record text sections that we know are safe
497 $read_function = defined($text_sections{$1}); 498 $read_function = defined($text_sections{$1});
498 # print out any recorded offsets 499 # print out any recorded offsets
499 update_funcs(); 500 update_funcs();
500 501
501 # reset all markers and arrays 502 # reset all markers and arrays
502 $text_found = 0; 503 $text_found = 0;
503 undef($ref_func); 504 undef($ref_func);
504 undef(@offsets); 505 undef(@offsets);
505 506
506 # section found, now is this a start of a function? 507 # section found, now is this a start of a function?
507 } elsif ($read_function && /$function_regex/) { 508 } elsif ($read_function && /$function_regex/) {
508 $text_found = 1; 509 $text_found = 1;
509 $text = $2; 510 $text = $2;
510 511
511 # if this is either a local function or a weak function 512 # if this is either a local function or a weak function
512 # keep looking for functions that are global that 513 # keep looking for functions that are global that
513 # we can use safely. 514 # we can use safely.
514 if (!defined($locals{$text}) && !defined($weak{$text})) { 515 if (!defined($locals{$text}) && !defined($weak{$text})) {
515 $ref_func = $text; 516 $ref_func = $text;
516 $read_function = 0; 517 $read_function = 0;
517 $offset = hex $1; 518 $offset = hex $1;
518 } else { 519 } else {
519 # if we already have a function, and this is weak, skip it 520 # if we already have a function, and this is weak, skip it
520 if (!defined($ref_func) && !defined($weak{$text}) && 521 if (!defined($ref_func) && !defined($weak{$text}) &&
521 # PPC64 can have symbols that start with .L and 522 # PPC64 can have symbols that start with .L and
522 # gcc considers these special. Don't use them! 523 # gcc considers these special. Don't use them!
523 $text !~ /^\.L/) { 524 $text !~ /^\.L/) {
524 $ref_func = $text; 525 $ref_func = $text;
525 $offset = hex $1; 526 $offset = hex $1;
526 } 527 }
527 } 528 }
528 } 529 }
529 # is this a call site to mcount? If so, record it to print later 530 # is this a call site to mcount? If so, record it to print later
530 if ($text_found && /$mcount_regex/) { 531 if ($text_found && /$mcount_regex/) {
531 push(@offsets, (hex $1) + $mcount_adjust); 532 push(@offsets, (hex $1) + $mcount_adjust);
532 } 533 }
533 } 534 }
534 535
535 # dump out anymore offsets that may have been found 536 # dump out anymore offsets that may have been found
536 update_funcs(); 537 update_funcs();
537 538
538 # If we did not find any mcount callers, we are done (do nothing). 539 # If we did not find any mcount callers, we are done (do nothing).
539 if (!$opened) { 540 if (!$opened) {
540 exit(0); 541 exit(0);
541 } 542 }
542 543
543 close(FILE); 544 close(FILE);
544 545
545 # 546 #
546 # Step 3: Compile the file that holds the list of call sites to mcount. 547 # Step 3: Compile the file that holds the list of call sites to mcount.
547 # 548 #
548 `$cc -o $mcount_o -c $mcount_s`; 549 `$cc -o $mcount_o -c $mcount_s`;
549 550
550 my @converts = keys %convert; 551 my @converts = keys %convert;
551 552
552 # 553 #
553 # Step 4: Do we have sections that started with local functions? 554 # Step 4: Do we have sections that started with local functions?
554 # 555 #
555 if ($#converts >= 0) { 556 if ($#converts >= 0) {
556 my $globallist = ""; 557 my $globallist = "";
557 my $locallist = ""; 558 my $locallist = "";
558 559
559 foreach my $con (@converts) { 560 foreach my $con (@converts) {
560 $globallist .= " --globalize-symbol $con"; 561 $globallist .= " --globalize-symbol $con";
561 $locallist .= " --localize-symbol $con"; 562 $locallist .= " --localize-symbol $con";
562 } 563 }
563 564
564 my $globalobj = $dirname . "/.tmp_gl_" . $filename; 565 my $globalobj = $dirname . "/.tmp_gl_" . $filename;
565 my $globalmix = $dirname . "/.tmp_mx_" . $filename; 566 my $globalmix = $dirname . "/.tmp_mx_" . $filename;
566 567
567 # 568 #
568 # Step 5: set up each local function as a global 569 # Step 5: set up each local function as a global
569 # 570 #
570 `$objcopy $globallist $inputfile $globalobj`; 571 `$objcopy $globallist $inputfile $globalobj`;
571 572
572 # 573 #
573 # Step 6: Link the global version to our list. 574 # Step 6: Link the global version to our list.
574 # 575 #
575 `$ld -r $globalobj $mcount_o -o $globalmix`; 576 `$ld -r $globalobj $mcount_o -o $globalmix`;
576 577
577 # 578 #
578 # Step 7: Convert the local functions back into local symbols 579 # Step 7: Convert the local functions back into local symbols
579 # 580 #
580 `$objcopy $locallist $globalmix $inputfile`; 581 `$objcopy $locallist $globalmix $inputfile`;
581 582
582 # Remove the temp files 583 # Remove the temp files
583 `$rm $globalobj $globalmix`; 584 `$rm $globalobj $globalmix`;
584 585
585 } else { 586 } else {
586 587
587 my $mix = $dirname . "/.tmp_mx_" . $filename; 588 my $mix = $dirname . "/.tmp_mx_" . $filename;
588 589
589 # 590 #
590 # Step 8: Link the object with our list of call sites object. 591 # Step 8: Link the object with our list of call sites object.
591 # 592 #
592 `$ld -r $inputfile $mcount_o -o $mix`; 593 `$ld -r $inputfile $mcount_o -o $mix`;
593 594
594 # 595 #
595 # Step 9: Move the result back to the original object. 596 # Step 9: Move the result back to the original object.
596 # 597 #
597 `$mv $mix $inputfile`; 598 `$mv $mix $inputfile`;
598 } 599 }
599 600
600 # Clean up the temp files 601 # Clean up the temp files
601 `$rm $mcount_o $mcount_s`; 602 `$rm $mcount_o $mcount_s`;
602 603
603 exit(0); 604 exit(0);
604 605