1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl 24f19048fSThomas Gleixner# SPDX-License-Identifier: GPL-2.0-only 38da3821bSSteven Rostedt# (c) 2008, Steven Rostedt <[email protected]> 48da3821bSSteven Rostedt# 58da3821bSSteven Rostedt# recordmcount.pl - makes a section called __mcount_loc that holds 68da3821bSSteven Rostedt# all the offsets to the calls to mcount. 78da3821bSSteven Rostedt# 88da3821bSSteven Rostedt# 9d49f6aa7SLi Hong# What we want to end up with this is that each object file will have a 10d49f6aa7SLi Hong# section called __mcount_loc that will hold the list of pointers to mcount 11d49f6aa7SLi Hong# callers. After final linking, the vmlinux will have within .init.data the 12d49f6aa7SLi Hong# list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc. 13d49f6aa7SLi Hong# Later on boot up, the kernel will read this list, save the locations and turn 14d49f6aa7SLi Hong# them into nops. When tracing or profiling is later enabled, these locations 15d49f6aa7SLi Hong# will then be converted back to pointers to some function. 168da3821bSSteven Rostedt# 178da3821bSSteven Rostedt# This is no easy feat. This script is called just after the original 188da3821bSSteven Rostedt# object is compiled and before it is linked. 198da3821bSSteven Rostedt# 20d49f6aa7SLi Hong# When parse this object file using 'objdump', the references to the call 21d49f6aa7SLi Hong# sites are offsets from the section that the call site is in. Hence, all 22d49f6aa7SLi Hong# functions in a section that has a call site to mcount, will have the 23d49f6aa7SLi Hong# offset from the beginning of the section and not the beginning of the 24d49f6aa7SLi Hong# function. 258da3821bSSteven Rostedt# 26d49f6aa7SLi Hong# But where this section will reside finally in vmlinx is undetermined at 27d49f6aa7SLi Hong# this point. So we can't use this kind of offsets to record the final 28d49f6aa7SLi Hong# address of this call site. 29d49f6aa7SLi Hong# 30d49f6aa7SLi Hong# The trick is to change the call offset referring the start of a section to 31d49f6aa7SLi Hong# referring a function symbol in this section. During the link step, 'ld' will 32d49f6aa7SLi Hong# compute the final address according to the information we record. 33d49f6aa7SLi Hong# 348da3821bSSteven Rostedt# e.g. 358da3821bSSteven Rostedt# 3631b6e76eSTim Abbott# .section ".sched.text", "ax" 378da3821bSSteven Rostedt# [...] 38d49f6aa7SLi Hong# func1: 39d49f6aa7SLi Hong# [...] 40d49f6aa7SLi Hong# call mcount (offset: 0x10) 418da3821bSSteven Rostedt# [...] 428da3821bSSteven Rostedt# ret 43d49f6aa7SLi Hong# .globl fun2 44d49f6aa7SLi Hong# func2: (offset: 0x20) 458da3821bSSteven Rostedt# [...] 46d49f6aa7SLi Hong# [...] 47d49f6aa7SLi Hong# ret 48d49f6aa7SLi Hong# func3: 49d49f6aa7SLi Hong# [...] 50d49f6aa7SLi Hong# call mcount (offset: 0x30) 518da3821bSSteven Rostedt# [...] 528da3821bSSteven Rostedt# 538da3821bSSteven Rostedt# Both relocation offsets for the mcounts in the above example will be 54d49f6aa7SLi Hong# offset from .sched.text. If we choose global symbol func2 as a reference and 55d49f6aa7SLi Hong# make another file called tmp.s with the new offsets: 568da3821bSSteven Rostedt# 578da3821bSSteven Rostedt# .section __mcount_loc 58d49f6aa7SLi Hong# .quad func2 - 0x10 59d49f6aa7SLi Hong# .quad func2 + 0x10 608da3821bSSteven Rostedt# 61d49f6aa7SLi Hong# We can then compile this tmp.s into tmp.o, and link it back to the original 628da3821bSSteven Rostedt# object. 638da3821bSSteven Rostedt# 64d49f6aa7SLi Hong# In our algorithm, we will choose the first global function we meet in this 65d49f6aa7SLi Hong# section as the reference. But this gets hard if there is no global functions 66d49f6aa7SLi Hong# in this section. In such a case we have to select a local one. E.g. func1: 678da3821bSSteven Rostedt# 6831b6e76eSTim Abbott# .section ".sched.text", "ax" 69d49f6aa7SLi Hong# func1: 708da3821bSSteven Rostedt# [...] 71d49f6aa7SLi Hong# call mcount (offset: 0x10) 728da3821bSSteven Rostedt# [...] 738da3821bSSteven Rostedt# ret 74d49f6aa7SLi Hong# func2: 758da3821bSSteven Rostedt# [...] 76d49f6aa7SLi Hong# call mcount (offset: 0x20) 778da3821bSSteven Rostedt# [...] 78d49f6aa7SLi Hong# .section "other.section" 798da3821bSSteven Rostedt# 808da3821bSSteven Rostedt# If we make the tmp.s the same as above, when we link together with 81d49f6aa7SLi Hong# the original object, we will end up with two symbols for func1: 828da3821bSSteven Rostedt# one local, one global. After final compile, we will end up with 83d49f6aa7SLi Hong# an undefined reference to func1 or a wrong reference to another global 84d49f6aa7SLi Hong# func1 in other files. 858da3821bSSteven Rostedt# 868da3821bSSteven Rostedt# Since local objects can reference local variables, we need to find 878da3821bSSteven Rostedt# a way to make tmp.o reference the local objects of the original object 88d49f6aa7SLi Hong# file after it is linked together. To do this, we convert func1 898da3821bSSteven Rostedt# into a global symbol before linking tmp.o. Then after we link tmp.o 90d49f6aa7SLi Hong# we will only have a single symbol for func1 that is global. 91d49f6aa7SLi Hong# We can convert func1 back into a local symbol and we are done. 928da3821bSSteven Rostedt# 938da3821bSSteven Rostedt# Here are the steps we take: 948da3821bSSteven Rostedt# 95306dcf47SLi Hong# 1) Record all the local and weak symbols by using 'nm' 968da3821bSSteven Rostedt# 2) Use objdump to find all the call site offsets and sections for 978da3821bSSteven Rostedt# mcount. 988da3821bSSteven Rostedt# 3) Compile the list into its own object. 998da3821bSSteven Rostedt# 4) Do we have to deal with local functions? If not, go to step 8. 1008da3821bSSteven Rostedt# 5) Make an object that converts these local functions to global symbols 1018da3821bSSteven Rostedt# with objcopy. 1028da3821bSSteven Rostedt# 6) Link together this new object with the list object. 1038da3821bSSteven Rostedt# 7) Convert the local functions back to local symbols and rename 1048da3821bSSteven Rostedt# the result as the original object. 1058da3821bSSteven Rostedt# 8) Link the object with the list object. 1068da3821bSSteven Rostedt# 9) Move the result back to the original object. 1078da3821bSSteven Rostedt# 1088da3821bSSteven Rostedt 109cb77f0d6SKamil Rytarowskiuse warnings; 1108da3821bSSteven Rostedtuse strict; 1118da3821bSSteven Rostedt 1128da3821bSSteven Rostedtmy $P = $0; 1138da3821bSSteven Rostedt$P =~ s@.*/@@g; 1148da3821bSSteven Rostedt 1158da3821bSSteven Rostedtmy $V = '0.1'; 1168da3821bSSteven Rostedt 117e6299d26SWu Zhangjinif ($#ARGV != 11) { 118e6299d26SWu Zhangjin print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n"; 1198da3821bSSteven Rostedt print "version: $V\n"; 1208da3821bSSteven Rostedt exit(1); 1218da3821bSSteven Rostedt} 1228da3821bSSteven Rostedt 123e6299d26SWu Zhangjinmy ($arch, $endian, $bits, $objdump, $objcopy, $cc, 12418c167fdSShaohua Li $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV; 1258da3821bSSteven Rostedt 12625aac9dcSShaohua Li# This file refers to mcount and shouldn't be ftraced, so lets' ignore it 127bdd3b052SLi Hongif ($inputfile =~ m,kernel/trace/ftrace\.o$,) { 12825aac9dcSShaohua Li exit(0); 12925aac9dcSShaohua Li} 13025aac9dcSShaohua Li 13134698bcbSSteven Rostedt# Acceptable sections to record. 13234698bcbSSteven Rostedtmy %text_sections = ( 13334698bcbSSteven Rostedt ".text" => 1, 13442c269c8SSteven Rostedt (VMware) ".init.text" => 1, 1351274a9c2SSteven Rostedt ".ref.text" => 1, 136d144d5eeSLiming Wang ".sched.text" => 1, 137d144d5eeSLiming Wang ".spinlock.text" => 1, 138a0343e82SFrederic Weisbecker ".irqentry.text" => 1, 139e436fd61SDmitry Vyukov ".softirqentry.text" => 1, 1409f087e76SSteven Rostedt ".kprobes.text" => 1, 1416727ad9eSChris Metcalf ".cpuidle.text" => 1, 1424d828949SJiri Olsa ".text.unlikely" => 1, 14334698bcbSSteven Rostedt); 14434698bcbSSteven Rostedt 1459c8e2f6dSJoe Lawrence# Acceptable section-prefixes to record. 1469c8e2f6dSJoe Lawrencemy %text_section_prefixes = ( 1479c8e2f6dSJoe Lawrence ".text." => 1, 1489c8e2f6dSJoe Lawrence); 1499c8e2f6dSJoe Lawrence 150dfaa9e2cSWolfram Sang# Note: we are nice to C-programmers here, thus we skip the '||='-idiom. 151dfaa9e2cSWolfram Sang$objdump = 'objdump' if (!$objdump); 152dfaa9e2cSWolfram Sang$objcopy = 'objcopy' if (!$objcopy); 153dfaa9e2cSWolfram Sang$cc = 'gcc' if (!$cc); 154dfaa9e2cSWolfram Sang$ld = 'ld' if (!$ld); 155dfaa9e2cSWolfram Sang$nm = 'nm' if (!$nm); 156dfaa9e2cSWolfram Sang$rm = 'rm' if (!$rm); 157dfaa9e2cSWolfram Sang$mv = 'mv' if (!$mv); 1588da3821bSSteven Rostedt 1598da3821bSSteven Rostedt#print STDERR "running: $P '$arch' '$objdump' '$objcopy' '$cc' '$ld' " . 1608da3821bSSteven Rostedt# "'$nm' '$rm' '$mv' '$inputfile'\n"; 1618da3821bSSteven Rostedt 1628feff1caSSteven Rostedtmy %locals; # List of local (static) functions 1638feff1caSSteven Rostedtmy %weak; # List of weak functions 1648feff1caSSteven Rostedtmy %convert; # List of local functions used that needs conversion 1658da3821bSSteven Rostedt 1668da3821bSSteven Rostedtmy $type; 167306dcf47SLi Hongmy $local_regex; # Match a local function (return function) 168306dcf47SLi Hongmy $weak_regex; # Match a weak function (return function) 1698da3821bSSteven Rostedtmy $section_regex; # Find the start of a section 1708feff1caSSteven Rostedtmy $function_regex; # Find the name of a function 1718feff1caSSteven Rostedt # (return offset and func name) 1728da3821bSSteven Rostedtmy $mcount_regex; # Find the call site to mcount (return offset) 173465c6ccaSMike Frysingermy $mcount_adjust; # Address adjustment to mcount offset 1747d5222a6SMatt Flemingmy $alignment; # The .align value to use for $mcount_section 175e58918abSJim Radfordmy $section_type; # Section header plus possible alignment command 1768da3821bSSteven Rostedt 177b82a4045SJan Kiszkaif ($arch =~ /(x86(_64)?)|(i386)/) { 178dce9d18aSSteven Rostedt if ($bits == 64) { 179dce9d18aSSteven Rostedt $arch = "x86_64"; 180dce9d18aSSteven Rostedt } else { 181dce9d18aSSteven Rostedt $arch = "i386"; 182dce9d18aSSteven Rostedt } 183dce9d18aSSteven Rostedt} 184dce9d18aSSteven Rostedt 185c204f726SSteven Rostedt# 186c204f726SSteven Rostedt# We base the defaults off of i386, the other archs may 187c204f726SSteven Rostedt# feel free to change them in the below if statements. 188c204f726SSteven Rostedt# 189306dcf47SLi Hong$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; 190306dcf47SLi Hong$weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)"; 19134698bcbSSteven Rostedt$section_regex = "Disassembly of section\\s+(\\S+):"; 192be358af1SSteven Rostedt$function_regex = "^([0-9a-fA-F]+)\\s+<([^^]*?)>:"; 193f02b625dSJamie Iles$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)\$"; 194e58918abSJim Radford$section_type = '@progbits'; 195465c6ccaSMike Frysinger$mcount_adjust = 0; 196c204f726SSteven Rostedt$type = ".long"; 197c204f726SSteven Rostedt 198c204f726SSteven Rostedtif ($arch eq "x86_64") { 199f02b625dSJamie Iles $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)([+-]0x[0-9a-zA-Z]+)?\$"; 2008da3821bSSteven Rostedt $type = ".quad"; 2017d5222a6SMatt Fleming $alignment = 8; 202521ccb5cSMartin Schwidefsky $mcount_adjust = -1; 203d74fcd1eSSteven Rostedt 204d74fcd1eSSteven Rostedt # force flags for this arch 205d74fcd1eSSteven Rostedt $ld .= " -m elf_x86_64"; 206d74fcd1eSSteven Rostedt $objdump .= " -M x86-64"; 207d74fcd1eSSteven Rostedt $objcopy .= " -O elf64-x86-64"; 208d74fcd1eSSteven Rostedt $cc .= " -m64"; 209d74fcd1eSSteven Rostedt 2108da3821bSSteven Rostedt} elsif ($arch eq "i386") { 2117d5222a6SMatt Fleming $alignment = 4; 212521ccb5cSMartin Schwidefsky $mcount_adjust = -1; 213d74fcd1eSSteven Rostedt 214d74fcd1eSSteven Rostedt # force flags for this arch 215d74fcd1eSSteven Rostedt $ld .= " -m elf_i386"; 216d74fcd1eSSteven Rostedt $objdump .= " -M i386"; 217d74fcd1eSSteven Rostedt $objcopy .= " -O elf32-i386"; 218d74fcd1eSSteven Rostedt $cc .= " -m32"; 219d74fcd1eSSteven Rostedt 220dfd9f7abSHeiko Carstens} elsif ($arch eq "s390" && $bits == 64) { 221e6d60b36SHeiko Carstens if ($cc =~ /-DCC_USING_HOTPATCH/) { 2224eb1782eSHeiko Carstens $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*(brcl\\s*0,|jgnop\\s*)[0-9a-f]+ <([^\+]*)>\$"; 223e6d60b36SHeiko Carstens $mcount_adjust = 0; 224e6d60b36SHeiko Carstens } 225dfd9f7abSHeiko Carstens $alignment = 8; 226dfd9f7abSHeiko Carstens $type = ".quad"; 227dfd9f7abSHeiko Carstens $ld .= " -m elf64_s390"; 228dfd9f7abSHeiko Carstens $cc .= " -m64"; 229dfd9f7abSHeiko Carstens 2300da85c09SMatt Fleming} elsif ($arch eq "sh") { 2313a3d04aeSMatt Fleming $alignment = 2; 2320da85c09SMatt Fleming 2330da85c09SMatt Fleming # force flags for this arch 2340da85c09SMatt Fleming $ld .= " -m shlelf_linux"; 23593ca6963SRong Chen if ($endian eq "big") { 23693ca6963SRong Chen $objcopy .= " -O elf32-shbig-linux"; 23793ca6963SRong Chen } else { 2380da85c09SMatt Fleming $objcopy .= " -O elf32-sh-linux"; 23993ca6963SRong Chen } 2400da85c09SMatt Fleming 24142e007d0SSteven Rostedt} elsif ($arch eq "powerpc") { 2421421dc6dSNicholas Piggin my $ldemulation; 2431421dc6dSNicholas Piggin 244306dcf47SLi Hong $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; 2452e50c4beSUlrich Weigand # See comment in the sparc64 section for why we use '\w'. 2462e50c4beSUlrich Weigand $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:"; 24742e007d0SSteven Rostedt $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; 248c204f726SSteven Rostedt 2491421dc6dSNicholas Piggin if ($endian eq "big") { 2501421dc6dSNicholas Piggin $cc .= " -mbig-endian "; 2511421dc6dSNicholas Piggin $ld .= " -EB "; 2521421dc6dSNicholas Piggin $ldemulation = "ppc" 2531421dc6dSNicholas Piggin } else { 2541421dc6dSNicholas Piggin $cc .= " -mlittle-endian "; 2551421dc6dSNicholas Piggin $ld .= " -EL "; 2561421dc6dSNicholas Piggin $ldemulation = "lppc" 2571421dc6dSNicholas Piggin } 25842e007d0SSteven Rostedt if ($bits == 64) { 25942e007d0SSteven Rostedt $type = ".quad"; 2601421dc6dSNicholas Piggin $cc .= " -m64 "; 2611421dc6dSNicholas Piggin $ld .= " -m elf64".$ldemulation." "; 2621421dc6dSNicholas Piggin } else { 2631421dc6dSNicholas Piggin $cc .= " -m32 "; 2641421dc6dSNicholas Piggin $ld .= " -m elf32".$ldemulation." "; 26542e007d0SSteven Rostedt } 26642e007d0SSteven Rostedt 267e58918abSJim Radford} elsif ($arch eq "arm") { 268e58918abSJim Radford $alignment = 2; 269e58918abSJim Radford $section_type = '%progbits'; 27072dc43a9SRabin Vincent $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" . 2713b6c223bSRabin Vincent "\\s+(__gnu_mcount_nc|mcount)\$"; 272e58918abSJim Radford 273af64d2aaSAKASHI Takahiro} elsif ($arch eq "arm64") { 274af64d2aaSAKASHI Takahiro $alignment = 3; 275af64d2aaSAKASHI Takahiro $section_type = '%progbits'; 276af64d2aaSAKASHI Takahiro $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$"; 277af64d2aaSAKASHI Takahiro $type = ".quad"; 2789be12f9bSDavid S. Miller} elsif ($arch eq "sparc64") { 2799be12f9bSDavid S. Miller # In the objdump output there are giblets like: 2809be12f9bSDavid S. Miller # 0000000000000000 <igmp_net_exit-0x18>: 2819be12f9bSDavid S. Miller # As there's some data blobs that get emitted into the 2829be12f9bSDavid S. Miller # text section before the first instructions and the first 2839be12f9bSDavid S. Miller # real symbols. We don't want to match that, so to combat 2849be12f9bSDavid S. Miller # this we use '\w' so we'll match just plain symbol names, 2859be12f9bSDavid S. Miller # and not those that also include hex offsets inside of the 2869be12f9bSDavid S. Miller # '<>' brackets. Actually the generic function_regex setting 2879be12f9bSDavid S. Miller # could safely use this too. 2889be12f9bSDavid S. Miller $function_regex = "^([0-9a-fA-F]+)\\s+<(\\w*?)>:"; 2899be12f9bSDavid S. Miller 2909be12f9bSDavid S. Miller # Sparc64 calls '_mcount' instead of plain 'mcount'. 2919be12f9bSDavid S. Miller $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 2929be12f9bSDavid S. Miller 2939be12f9bSDavid S. Miller $alignment = 8; 2949be12f9bSDavid S. Miller $type = ".xword"; 2959be12f9bSDavid S. Miller $ld .= " -m elf64_sparc"; 2969be12f9bSDavid S. Miller $cc .= " -m64"; 2979be12f9bSDavid S. Miller $objcopy .= " -O elf64-sparc"; 298538f1952SWu Zhangjin} elsif ($arch eq "mips") { 299538f1952SWu Zhangjin # To enable module support, we need to enable the -mlong-calls option 300538f1952SWu Zhangjin # of gcc for module, after using this option, we can not get the real 301538f1952SWu Zhangjin # offset of the calling to _mcount, but the offset of the lui 302538f1952SWu Zhangjin # instruction or the addiu one. herein, we record the address of the 303538f1952SWu Zhangjin # first one, and then we can replace this instruction by a branch 304538f1952SWu Zhangjin # instruction to jump over the profiling function to filter the 30508a7e621SMasahiro Yamada # indicated functions, or switch back to the lui instruction to trace 306538f1952SWu Zhangjin # them, which means dynamic tracing. 307538f1952SWu Zhangjin # 308538f1952SWu Zhangjin # c: 3c030000 lui v1,0x0 309538f1952SWu Zhangjin # c: R_MIPS_HI16 _mcount 310538f1952SWu Zhangjin # c: R_MIPS_NONE *ABS* 311538f1952SWu Zhangjin # c: R_MIPS_NONE *ABS* 312538f1952SWu Zhangjin # 10: 64630000 daddiu v1,v1,0 313538f1952SWu Zhangjin # 10: R_MIPS_LO16 _mcount 314538f1952SWu Zhangjin # 10: R_MIPS_NONE *ABS* 315538f1952SWu Zhangjin # 10: R_MIPS_NONE *ABS* 316538f1952SWu Zhangjin # 14: 03e0082d move at,ra 317538f1952SWu Zhangjin # 18: 0060f809 jalr v1 318538f1952SWu Zhangjin # 319538f1952SWu Zhangjin # for the kernel: 320538f1952SWu Zhangjin # 321538f1952SWu Zhangjin # 10: 03e0082d move at,ra 322538f1952SWu Zhangjin # 14: 0c000000 jal 0 <loongson_halt> 323538f1952SWu Zhangjin # 14: R_MIPS_26 _mcount 324538f1952SWu Zhangjin # 14: R_MIPS_NONE *ABS* 325538f1952SWu Zhangjin # 14: R_MIPS_NONE *ABS* 326538f1952SWu Zhangjin # 18: 00020021 nop 327538f1952SWu Zhangjin if ($is_module eq "0") { 328a484e54fSDavid Daney $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$"; 329538f1952SWu Zhangjin } else { 330538f1952SWu Zhangjin $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$"; 331538f1952SWu Zhangjin } 332538f1952SWu Zhangjin $objdump .= " -Melf-trad".$endian."mips "; 333538f1952SWu Zhangjin 334538f1952SWu Zhangjin if ($endian eq "big") { 335538f1952SWu Zhangjin $endian = " -EB "; 336538f1952SWu Zhangjin $ld .= " -melf".$bits."btsmip"; 337538f1952SWu Zhangjin } else { 338538f1952SWu Zhangjin $endian = " -EL "; 339538f1952SWu Zhangjin $ld .= " -melf".$bits."ltsmip"; 340538f1952SWu Zhangjin } 341538f1952SWu Zhangjin 342538f1952SWu Zhangjin $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian; 343538f1952SWu Zhangjin $ld .= $endian; 344538f1952SWu Zhangjin 345538f1952SWu Zhangjin if ($bits == 64) { 346538f1952SWu Zhangjin $function_regex = 347538f1952SWu Zhangjin "^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:"; 348538f1952SWu Zhangjin $type = ".dword"; 349538f1952SWu Zhangjin } 3507d241ff0SMichal Simek} elsif ($arch eq "microblaze") { 3517d241ff0SMichal Simek # Microblaze calls '_mcount' instead of plain 'mcount'. 3527d241ff0SMichal Simek $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 353a1d2a6b4SAlan Kao} elsif ($arch eq "riscv") { 354a1d2a6b4SAlan Kao $function_regex = "^([0-9a-fA-F]+)\\s+<([^.0-9][0-9a-zA-Z_\\.]+)>:"; 355*de5f3984SNathan Chancellor $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL(_PLT)?\\s_mcount\$"; 356a1d2a6b4SAlan Kao $type = ".quad"; 357a1d2a6b4SAlan Kao $alignment = 2; 35828bb030fSGuo Ren} elsif ($arch eq "csky") { 35928bb030fSGuo Ren $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_CKCORE_PCREL_JSR_IMM26BY2\\s+_mcount\$"; 36028bb030fSGuo Ren $alignment = 2; 3618da3821bSSteven Rostedt} else { 3628da3821bSSteven Rostedt die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; 3638da3821bSSteven Rostedt} 3648da3821bSSteven Rostedt 3658da3821bSSteven Rostedtmy $text_found = 0; 3668da3821bSSteven Rostedtmy $read_function = 0; 3678da3821bSSteven Rostedtmy $opened = 0; 3688da3821bSSteven Rostedtmy $mcount_section = "__mcount_loc"; 3698da3821bSSteven Rostedt 3708da3821bSSteven Rostedtmy $dirname; 3718da3821bSSteven Rostedtmy $filename; 3728da3821bSSteven Rostedtmy $prefix; 3738da3821bSSteven Rostedtmy $ext; 3748da3821bSSteven Rostedt 3758da3821bSSteven Rostedtif ($inputfile =~ m,^(.*)/([^/]*)$,) { 3768da3821bSSteven Rostedt $dirname = $1; 3778da3821bSSteven Rostedt $filename = $2; 3788da3821bSSteven Rostedt} else { 3798da3821bSSteven Rostedt $dirname = "."; 3808da3821bSSteven Rostedt $filename = $inputfile; 3818da3821bSSteven Rostedt} 3828da3821bSSteven Rostedt 3838da3821bSSteven Rostedtif ($filename =~ m,^(.*)(\.\S),) { 3848da3821bSSteven Rostedt $prefix = $1; 3858da3821bSSteven Rostedt $ext = $2; 3868da3821bSSteven Rostedt} else { 3878da3821bSSteven Rostedt $prefix = $filename; 3888da3821bSSteven Rostedt $ext = ""; 3898da3821bSSteven Rostedt} 3908da3821bSSteven Rostedt 3918da3821bSSteven Rostedtmy $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s"; 3928da3821bSSteven Rostedtmy $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o"; 3938da3821bSSteven Rostedt 394f2f8458eSSteven Rostedt# 3958feff1caSSteven Rostedt# Step 1: find all the local (static functions) and weak symbols. 396306dcf47SLi Hong# 't' is local, 'w/W' is weak 3978da3821bSSteven Rostedt# 3988da3821bSSteven Rostedtopen (IN, "$nm $inputfile|") || die "error running $nm"; 3998da3821bSSteven Rostedtwhile (<IN>) { 400306dcf47SLi Hong if (/$local_regex/) { 4018da3821bSSteven Rostedt $locals{$1} = 1; 402306dcf47SLi Hong } elsif (/$weak_regex/) { 4038feff1caSSteven Rostedt $weak{$2} = $1; 4048da3821bSSteven Rostedt } 4058da3821bSSteven Rostedt} 4068da3821bSSteven Rostedtclose(IN); 4078da3821bSSteven Rostedt 4088feff1caSSteven Rostedtmy @offsets; # Array of offsets of mcount callers 4098feff1caSSteven Rostedtmy $ref_func; # reference function to use for offsets 4108feff1caSSteven Rostedtmy $offset = 0; # offset of ref_func to section beginning 4118feff1caSSteven Rostedt 4128feff1caSSteven Rostedt## 4138feff1caSSteven Rostedt# update_funcs - print out the current mcount callers 4148feff1caSSteven Rostedt# 4158feff1caSSteven Rostedt# Go through the list of offsets to callers and write them to 4168feff1caSSteven Rostedt# the output file in a format that can be read by an assembler. 4178feff1caSSteven Rostedt# 4188feff1caSSteven Rostedtsub update_funcs 4198feff1caSSteven Rostedt{ 4206092858cSLi Hong return unless ($ref_func and @offsets); 4218feff1caSSteven Rostedt 422c4b8ac2cSLi Hong # Sanity check on weak function. A weak function may be overwritten by 423c4b8ac2cSLi Hong # another function of the same name, making all these offsets incorrect. 4248feff1caSSteven Rostedt if (defined $weak{$ref_func}) { 425c4b8ac2cSLi Hong die "$inputfile: ERROR: referencing weak function" . 4268feff1caSSteven Rostedt " $ref_func for mcount\n"; 4278feff1caSSteven Rostedt } 4288feff1caSSteven Rostedt 4298feff1caSSteven Rostedt # is this function static? If so, note this fact. 4308feff1caSSteven Rostedt if (defined $locals{$ref_func}) { 4318feff1caSSteven Rostedt $convert{$ref_func} = 1; 4328feff1caSSteven Rostedt } 4338feff1caSSteven Rostedt 4348feff1caSSteven Rostedt # Loop through all the mcount caller offsets and print a reference 4358feff1caSSteven Rostedt # to the caller based from the ref_func. 4368feff1caSSteven Rostedt if (!$opened) { 4378feff1caSSteven Rostedt open(FILE, ">$mcount_s") || die "can't create $mcount_s\n"; 4388feff1caSSteven Rostedt $opened = 1; 439e58918abSJim Radford print FILE "\t.section $mcount_section,\"a\",$section_type\n"; 44042e007d0SSteven Rostedt print FILE "\t.align $alignment\n" if (defined($alignment)); 4418feff1caSSteven Rostedt } 442dc4f8845SWolfram Sang foreach my $cur_offset (@offsets) { 443dc4f8845SWolfram Sang printf FILE "\t%s %s + %d\n", $type, $ref_func, $cur_offset - $offset; 4448feff1caSSteven Rostedt } 4458feff1caSSteven Rostedt} 4468feff1caSSteven Rostedt 4478da3821bSSteven Rostedt# 4488da3821bSSteven Rostedt# Step 2: find the sections and mcount call sites 4498da3821bSSteven Rostedt# 45077a88274SMasahiro Yamadaopen(IN, "LC_ALL=C $objdump -hdr $inputfile|") || die "error running $objdump"; 4518da3821bSSteven Rostedt 4528feff1caSSteven Rostedtmy $text; 4538feff1caSSteven Rostedt 454db24c7dcSLi Hong 455db24c7dcSLi Hong# read headers first 456b43f7093SSteven Rostedtmy $read_headers = 1; 457b43f7093SSteven Rostedt 4588da3821bSSteven Rostedtwhile (<IN>) { 459db24c7dcSLi Hong 460db24c7dcSLi Hong if ($read_headers && /$mcount_section/) { 461db24c7dcSLi Hong # 462db24c7dcSLi Hong # Somehow the make process can execute this script on an 463db24c7dcSLi Hong # object twice. If it does, we would duplicate the mcount 464db24c7dcSLi Hong # section and it will cause the function tracer self test 465db24c7dcSLi Hong # to fail. Check if the mcount section exists, and if it does, 466db24c7dcSLi Hong # warn and exit. 467db24c7dcSLi Hong # 468db24c7dcSLi Hong print STDERR "ERROR: $mcount_section already in $inputfile\n" . 469db24c7dcSLi Hong "\tThis may be an indication that your build is corrupted.\n" . 470db24c7dcSLi Hong "\tDelete $inputfile and try again. If the same object file\n" . 471db24c7dcSLi Hong "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n"; 472db24c7dcSLi Hong exit(-1); 473db24c7dcSLi Hong } 474db24c7dcSLi Hong 4758da3821bSSteven Rostedt # is it a section? 4768da3821bSSteven Rostedt if (/$section_regex/) { 477b43f7093SSteven Rostedt $read_headers = 0; 47834698bcbSSteven Rostedt 47934698bcbSSteven Rostedt # Only record text sections that we know are safe 480dfaa9e2cSWolfram Sang $read_function = defined($text_sections{$1}); 4819c8e2f6dSJoe Lawrence if (!$read_function) { 4829c8e2f6dSJoe Lawrence foreach my $prefix (keys %text_section_prefixes) { 4839c8e2f6dSJoe Lawrence if (substr($1, 0, length $prefix) eq $prefix) { 4849c8e2f6dSJoe Lawrence $read_function = 1; 4859c8e2f6dSJoe Lawrence last; 4869c8e2f6dSJoe Lawrence } 4879c8e2f6dSJoe Lawrence } 4889c8e2f6dSJoe Lawrence } 4898feff1caSSteven Rostedt # print out any recorded offsets 4906092858cSLi Hong update_funcs(); 4918feff1caSSteven Rostedt 4928feff1caSSteven Rostedt # reset all markers and arrays 4938da3821bSSteven Rostedt $text_found = 0; 4948feff1caSSteven Rostedt undef($ref_func); 4958feff1caSSteven Rostedt undef(@offsets); 4968feff1caSSteven Rostedt 4978da3821bSSteven Rostedt # section found, now is this a start of a function? 4988da3821bSSteven Rostedt } elsif ($read_function && /$function_regex/) { 4998da3821bSSteven Rostedt $text_found = 1; 5008feff1caSSteven Rostedt $text = $2; 5018feff1caSSteven Rostedt 5028feff1caSSteven Rostedt # if this is either a local function or a weak function 5038feff1caSSteven Rostedt # keep looking for functions that are global that 5048feff1caSSteven Rostedt # we can use safely. 5058feff1caSSteven Rostedt if (!defined($locals{$text}) && !defined($weak{$text})) { 5068feff1caSSteven Rostedt $ref_func = $text; 5078feff1caSSteven Rostedt $read_function = 0; 508bd171d5fSMatt Fleming $offset = hex $1; 5098feff1caSSteven Rostedt } else { 5108feff1caSSteven Rostedt # if we already have a function, and this is weak, skip it 5113f6e968eSSteven Rostedt if (!defined($ref_func) && !defined($weak{$text}) && 5123f6e968eSSteven Rostedt # PPC64 can have symbols that start with .L and 5133f6e968eSSteven Rostedt # gcc considers these special. Don't use them! 5143f6e968eSSteven Rostedt $text !~ /^\.L/) { 5158feff1caSSteven Rostedt $ref_func = $text; 516bd171d5fSMatt Fleming $offset = hex $1; 5178da3821bSSteven Rostedt } 5188da3821bSSteven Rostedt } 5198feff1caSSteven Rostedt } 5208feff1caSSteven Rostedt # is this a call site to mcount? If so, record it to print later 5218feff1caSSteven Rostedt if ($text_found && /$mcount_regex/) { 522465c6ccaSMike Frysinger push(@offsets, (hex $1) + $mcount_adjust); 5238feff1caSSteven Rostedt } 5248feff1caSSteven Rostedt} 5258feff1caSSteven Rostedt 5268feff1caSSteven Rostedt# dump out anymore offsets that may have been found 5276092858cSLi Hongupdate_funcs(); 5288da3821bSSteven Rostedt 5298da3821bSSteven Rostedt# If we did not find any mcount callers, we are done (do nothing). 5308da3821bSSteven Rostedtif (!$opened) { 5318da3821bSSteven Rostedt exit(0); 5328da3821bSSteven Rostedt} 5338da3821bSSteven Rostedt 5348da3821bSSteven Rostedtclose(FILE); 5358da3821bSSteven Rostedt 5368da3821bSSteven Rostedt# 5378da3821bSSteven Rostedt# Step 3: Compile the file that holds the list of call sites to mcount. 5388da3821bSSteven Rostedt# 5398da3821bSSteven Rostedt`$cc -o $mcount_o -c $mcount_s`; 5408da3821bSSteven Rostedt 5418da3821bSSteven Rostedtmy @converts = keys %convert; 5428da3821bSSteven Rostedt 5438da3821bSSteven Rostedt# 5448da3821bSSteven Rostedt# Step 4: Do we have sections that started with local functions? 5458da3821bSSteven Rostedt# 5468da3821bSSteven Rostedtif ($#converts >= 0) { 5478da3821bSSteven Rostedt my $globallist = ""; 5488da3821bSSteven Rostedt my $locallist = ""; 5498da3821bSSteven Rostedt 5508da3821bSSteven Rostedt foreach my $con (@converts) { 5518da3821bSSteven Rostedt $globallist .= " --globalize-symbol $con"; 5528da3821bSSteven Rostedt $locallist .= " --localize-symbol $con"; 5538da3821bSSteven Rostedt } 5548da3821bSSteven Rostedt 5558da3821bSSteven Rostedt my $globalobj = $dirname . "/.tmp_gl_" . $filename; 5568da3821bSSteven Rostedt my $globalmix = $dirname . "/.tmp_mx_" . $filename; 5578da3821bSSteven Rostedt 5588da3821bSSteven Rostedt # 5598da3821bSSteven Rostedt # Step 5: set up each local function as a global 5608da3821bSSteven Rostedt # 5618da3821bSSteven Rostedt `$objcopy $globallist $inputfile $globalobj`; 5628da3821bSSteven Rostedt 5638da3821bSSteven Rostedt # 5648da3821bSSteven Rostedt # Step 6: Link the global version to our list. 5658da3821bSSteven Rostedt # 5668da3821bSSteven Rostedt `$ld -r $globalobj $mcount_o -o $globalmix`; 5678da3821bSSteven Rostedt 5688da3821bSSteven Rostedt # 5698da3821bSSteven Rostedt # Step 7: Convert the local functions back into local symbols 5708da3821bSSteven Rostedt # 5718da3821bSSteven Rostedt `$objcopy $locallist $globalmix $inputfile`; 5728da3821bSSteven Rostedt 5738da3821bSSteven Rostedt # Remove the temp files 5748da3821bSSteven Rostedt `$rm $globalobj $globalmix`; 5758da3821bSSteven Rostedt 5768da3821bSSteven Rostedt} else { 5778da3821bSSteven Rostedt 5788da3821bSSteven Rostedt my $mix = $dirname . "/.tmp_mx_" . $filename; 5798da3821bSSteven Rostedt 5808da3821bSSteven Rostedt # 5818da3821bSSteven Rostedt # Step 8: Link the object with our list of call sites object. 5828da3821bSSteven Rostedt # 5838da3821bSSteven Rostedt `$ld -r $inputfile $mcount_o -o $mix`; 5848da3821bSSteven Rostedt 5858da3821bSSteven Rostedt # 5868da3821bSSteven Rostedt # Step 9: Move the result back to the original object. 5878da3821bSSteven Rostedt # 5888da3821bSSteven Rostedt `$mv $mix $inputfile`; 5898da3821bSSteven Rostedt} 5908da3821bSSteven Rostedt 5918da3821bSSteven Rostedt# Clean up the temp files 5928da3821bSSteven Rostedt`$rm $mcount_o $mcount_s`; 5938da3821bSSteven Rostedt 5948da3821bSSteven Rostedtexit(0); 595b700fc3aSSteven Rostedt (VMware) 596b700fc3aSSteven Rostedt (VMware)# vim: softtabstop=4 597