Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);