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