4317cf95ca024 (Thomas Gleixner 2019-05-31 01:09:38 -0700 1) /* SPDX-License-Identifier: GPL-2.0-only */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 2) /*
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 3) * recordmcount.h
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 4) *
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 5) * This code was taken out of recordmcount.c written by
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 6) * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 7) *
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 8) * The original code had the same algorithms for both 32bit
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 9) * and 64bit ELF files, but the code was duplicated to support
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 10) * the difference in structures that were used. This
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 11) * file creates a macro of everything that is different between
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 12) * the 64 and 32 bit code, such that by including this header
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 13) * twice we can create both sets of functions by including this
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 14) * header once with RECORD_MCOUNT_64 undefined, and again with
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 15) * it defined.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 16) *
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 17) * This conversion to macros was done by:
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 18) * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 19) */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 20) #undef append_func
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 21) #undef is_fake_mcount
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 22) #undef fn_is_fake_mcount
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 23) #undef MIPS_is_fake_mcount
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 24) #undef mcount_adjust
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 25) #undef sift_rel_mcount
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 26) #undef nop_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 27) #undef find_secsym_ndx
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 28) #undef __has_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 29) #undef has_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 30) #undef tot_relsize
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 31) #undef get_mcountsym
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 32) #undef find_symtab
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 33) #undef get_shnum
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 34) #undef set_shnum
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 35) #undef get_shstrndx
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 36) #undef get_symindex
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 37) #undef get_sym_str_and_relp
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 38) #undef do_func
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 39) #undef Elf_Addr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 40) #undef Elf_Ehdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 41) #undef Elf_Shdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 42) #undef Elf_Rel
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 43) #undef Elf_Rela
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 44) #undef Elf_Sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 45) #undef ELF_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 46) #undef Elf_r_sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 47) #undef ELF_R_INFO
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 48) #undef Elf_r_info
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 49) #undef ELF_ST_BIND
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 50) #undef ELF_ST_TYPE
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 51) #undef fn_ELF_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 52) #undef fn_ELF_R_INFO
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 53) #undef uint_t
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 54) #undef _w
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 55) #undef _align
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 56) #undef _size
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 57)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 58) #ifdef RECORD_MCOUNT_64
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 59) # define append_func append64
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 60) # define sift_rel_mcount sift64_rel_mcount
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 61) # define nop_mcount nop_mcount_64
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 62) # define find_secsym_ndx find64_secsym_ndx
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 63) # define __has_rel_mcount __has64_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 64) # define has_rel_mcount has64_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 65) # define tot_relsize tot64_relsize
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 66) # define find_symtab find_symtab64
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 67) # define get_shnum get_shnum64
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 68) # define set_shnum set_shnum64
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 69) # define get_shstrndx get_shstrndx64
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 70) # define get_symindex get_symindex64
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 71) # define get_sym_str_and_relp get_sym_str_and_relp_64
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 72) # define do_func do64
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 73) # define get_mcountsym get_mcountsym_64
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 74) # define is_fake_mcount is_fake_mcount64
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 75) # define fn_is_fake_mcount fn_is_fake_mcount64
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 76) # define MIPS_is_fake_mcount MIPS64_is_fake_mcount
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 77) # define mcount_adjust mcount_adjust_64
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 78) # define Elf_Addr Elf64_Addr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 79) # define Elf_Ehdr Elf64_Ehdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 80) # define Elf_Shdr Elf64_Shdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 81) # define Elf_Rel Elf64_Rel
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 82) # define Elf_Rela Elf64_Rela
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 83) # define Elf_Sym Elf64_Sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 84) # define ELF_R_SYM ELF64_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 85) # define Elf_r_sym Elf64_r_sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 86) # define ELF_R_INFO ELF64_R_INFO
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 87) # define Elf_r_info Elf64_r_info
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 88) # define ELF_ST_BIND ELF64_ST_BIND
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 89) # define ELF_ST_TYPE ELF64_ST_TYPE
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 90) # define fn_ELF_R_SYM fn_ELF64_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 91) # define fn_ELF_R_INFO fn_ELF64_R_INFO
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 92) # define uint_t uint64_t
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 93) # define _w w8
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 94) # define _align 7u
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 95) # define _size 8
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 96) #else
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 97) # define append_func append32
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 98) # define sift_rel_mcount sift32_rel_mcount
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 99) # define nop_mcount nop_mcount_32
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 100) # define find_secsym_ndx find32_secsym_ndx
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 101) # define __has_rel_mcount __has32_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 102) # define has_rel_mcount has32_rel_mcount
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 103) # define tot_relsize tot32_relsize
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 104) # define find_symtab find_symtab32
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 105) # define get_shnum get_shnum32
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 106) # define set_shnum set_shnum32
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 107) # define get_shstrndx get_shstrndx32
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 108) # define get_symindex get_symindex32
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 109) # define get_sym_str_and_relp get_sym_str_and_relp_32
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 110) # define do_func do32
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 111) # define get_mcountsym get_mcountsym_32
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 112) # define is_fake_mcount is_fake_mcount32
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 113) # define fn_is_fake_mcount fn_is_fake_mcount32
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 114) # define MIPS_is_fake_mcount MIPS32_is_fake_mcount
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 115) # define mcount_adjust mcount_adjust_32
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 116) # define Elf_Addr Elf32_Addr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 117) # define Elf_Ehdr Elf32_Ehdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 118) # define Elf_Shdr Elf32_Shdr
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 119) # define Elf_Rel Elf32_Rel
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 120) # define Elf_Rela Elf32_Rela
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 121) # define Elf_Sym Elf32_Sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 122) # define ELF_R_SYM ELF32_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 123) # define Elf_r_sym Elf32_r_sym
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 124) # define ELF_R_INFO ELF32_R_INFO
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 125) # define Elf_r_info Elf32_r_info
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 126) # define ELF_ST_BIND ELF32_ST_BIND
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 127) # define ELF_ST_TYPE ELF32_ST_TYPE
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 128) # define fn_ELF_R_SYM fn_ELF32_R_SYM
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 129) # define fn_ELF_R_INFO fn_ELF32_R_INFO
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 130) # define uint_t uint32_t
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 131) # define _w w
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 132) # define _align 3u
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 133) # define _size 4
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 134) #endif
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 135)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 136) /* Functions and pointers that do_file() may override for specific e_machine. */
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 137) static int fn_is_fake_mcount(Elf_Rel const *rp)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 138) {
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 139) return 0;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 140) }
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 141) static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 142)
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 143) static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 144) {
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 145) return ELF_R_SYM(_w(rp->r_info));
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 146) }
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 147) static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 148)
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 149) static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 150) {
e63233f75a1a6 (John Reiser 2010-11-22 19:41:44 -0800 151) rp->r_info = _w(ELF_R_INFO(sym, type));
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 152) }
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 153) static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 154)
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 155) static int mcount_adjust = 0;
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 156)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 157) /*
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 158) * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 159) * _mcount symbol is needed for dynamic function tracer, with it, to disable
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 160) * tracing(ftrace_make_nop), the instruction in the position is replaced with
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 161) * the "b label" instruction, to enable tracing(ftrace_make_call), replace the
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 162) * instruction back. So, here, we set the 2nd one as fake and filter it.
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 163) *
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 164) * c: 3c030000 lui v1,0x0 <--> b label
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 165) * c: R_MIPS_HI16 _mcount
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 166) * c: R_MIPS_NONE *ABS*
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 167) * c: R_MIPS_NONE *ABS*
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 168) * 10: 64630000 daddiu v1,v1,0
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 169) * 10: R_MIPS_LO16 _mcount
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 170) * 10: R_MIPS_NONE *ABS*
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 171) * 10: R_MIPS_NONE *ABS*
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 172) * 14: 03e0082d move at,ra
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 173) * 18: 0060f809 jalr v1
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 174) * label:
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 175) */
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 176) #define MIPS_FAKEMCOUNT_OFFSET 4
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 177)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 178) static int MIPS_is_fake_mcount(Elf_Rel const *rp)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 179) {
91ad11d7cc6f4 (Alex Smith 2014-06-17 10:39:53 +0100 180) static Elf_Addr old_r_offset = ~(Elf_Addr)0;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 181) Elf_Addr current_r_offset = _w(rp->r_offset);
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 182) int is_fake;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 183)
91ad11d7cc6f4 (Alex Smith 2014-06-17 10:39:53 +0100 184) is_fake = (old_r_offset != ~(Elf_Addr)0) &&
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 185) (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 186) old_r_offset = current_r_offset;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 187)
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 188) return is_fake;
412910cd046c1 (Wu Zhangjin 2010-10-27 18:59:08 +0800 189) }
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 190)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 191) static unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab,
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 192) Elf32_Word const *symtab_shndx)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 193) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 194) unsigned long offset;
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 195) unsigned short shndx = w2(sym->st_shndx);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 196) int index;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 197)
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 198) if (shndx > SHN_UNDEF && shndx < SHN_LORESERVE)
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 199) return shndx;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 200)
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 201) if (shndx == SHN_XINDEX) {
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 202) offset = (unsigned long)sym - (unsigned long)symtab;
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 203) index = offset / sizeof(*sym);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 204)
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 205) return w(symtab_shndx[index]);
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 206) }
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 207)
fb780761e7bd9 (Peter Zijlstra 2021-06-16 23:41:26 +0800 208) return 0;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 209) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 210)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 211) static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 212) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 213) if (shdr0 && !ehdr->e_shnum)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 214) return w(shdr0->sh_size);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 215)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 216) return w2(ehdr->e_shnum);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 217) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 218)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 219) static void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 220) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 221) if (new_shnum >= SHN_LORESERVE) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 222) ehdr->e_shnum = 0;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 223) shdr0->sh_size = w(new_shnum);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 224) } else
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 225) ehdr->e_shnum = w2(new_shnum);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 226) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 227)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 228) static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 229) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 230) if (ehdr->e_shstrndx != SHN_XINDEX)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 231) return w2(ehdr->e_shstrndx);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 232)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 233) return w(shdr0->sh_link);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 234) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 235)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 236) static void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0,
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 237) unsigned const nhdr, Elf32_Word **symtab,
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 238) Elf32_Word **symtab_shndx)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 239) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 240) Elf_Shdr const *relhdr;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 241) unsigned k;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 242)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 243) *symtab = NULL;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 244) *symtab_shndx = NULL;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 245)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 246) for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 247) if (relhdr->sh_type == SHT_SYMTAB)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 248) *symtab = (void *)ehdr + relhdr->sh_offset;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 249) else if (relhdr->sh_type == SHT_SYMTAB_SHNDX)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 250) *symtab_shndx = (void *)ehdr + relhdr->sh_offset;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 251)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 252) if (*symtab && *symtab_shndx)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 253) break;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 254) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 255) }
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 256)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 257) /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 258) static int append_func(Elf_Ehdr *const ehdr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 259) Elf_Shdr *const shstr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 260) uint_t const *const mloc0,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 261) uint_t const *const mlocp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 262) Elf_Rel const *const mrel0,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 263) Elf_Rel const *const mrelp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 264) unsigned int const rel_entsize,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 265) unsigned int const symsec_sh_link)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 266) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 267) /* Begin constructing output file */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 268) Elf_Shdr mcsec;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 269) char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 270) ? ".rela__mcount_loc"
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 271) : ".rel__mcount_loc";
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 272) uint_t const old_shoff = _w(ehdr->e_shoff);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 273) uint_t const old_shstr_sh_size = _w(shstr->sh_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 274) uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 275) Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 276) unsigned int const old_shnum = get_shnum(ehdr, shdr0);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 277) unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 278) uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 279) uint_t new_e_shoff;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 280)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 281) shstr->sh_size = _w(t);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 282) shstr->sh_offset = _w(sb.st_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 283) t += sb.st_size;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 284) t += (_align & -t); /* word-byte align */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 285) new_e_shoff = t;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 286)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 287) set_shnum(ehdr, shdr0, new_shnum);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 288)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 289) /* body for new shstrtab */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 290) if (ulseek(sb.st_size, SEEK_SET) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 291) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 292) if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 293) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 294) if (uwrite(mc_name, 1 + strlen(mc_name)) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 295) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 296)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 297) /* old(modified) Elf_Shdr table, word-byte aligned */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 298) if (ulseek(t, SEEK_SET) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 299) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 300) t += sizeof(Elf_Shdr) * old_shnum;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 301) if (uwrite(old_shoff + (void *)ehdr,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 302) sizeof(Elf_Shdr) * old_shnum) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 303) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 304)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 305) /* new sections __mcount_loc and .rel__mcount_loc */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 306) t += 2*sizeof(mcsec);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 307) mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 308) + old_shstr_sh_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 309) mcsec.sh_type = w(SHT_PROGBITS);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 310) mcsec.sh_flags = _w(SHF_ALLOC);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 311) mcsec.sh_addr = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 312) mcsec.sh_offset = _w(t);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 313) mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 314) mcsec.sh_link = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 315) mcsec.sh_info = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 316) mcsec.sh_addralign = _w(_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 317) mcsec.sh_entsize = _w(_size);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 318) if (uwrite(&mcsec, sizeof(mcsec)) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 319) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 320)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 321) mcsec.sh_name = w(old_shstr_sh_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 322) mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 323) ? w(SHT_RELA)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 324) : w(SHT_REL);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 325) mcsec.sh_flags = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 326) mcsec.sh_addr = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 327) mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 328) mcsec.sh_size = _w((void *)mrelp - (void *)mrel0);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 329) mcsec.sh_link = w(symsec_sh_link);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 330) mcsec.sh_info = w(old_shnum);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 331) mcsec.sh_addralign = _w(_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 332) mcsec.sh_entsize = _w(rel_entsize);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 333)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 334) if (uwrite(&mcsec, sizeof(mcsec)) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 335) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 336)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 337) if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 338) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 339) if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 340) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 341)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 342) ehdr->e_shoff = _w(new_e_shoff);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 343) if (ulseek(0, SEEK_SET) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 344) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 345) if (uwrite(ehdr, sizeof(*ehdr)) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 346) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 347) return 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 348) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 349)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 350) static unsigned get_mcountsym(Elf_Sym const *const sym0,
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 351) Elf_Rel const *relp,
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 352) char const *const str0)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 353) {
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 354) unsigned mcountsym = 0;
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 355)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 356) Elf_Sym const *const symp =
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 357) &sym0[Elf_r_sym(relp)];
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 358) char const *symname = &str0[w(symp->st_name)];
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 359) char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
48bb5dc6cd9d3 (Steven Rostedt 2011-02-09 13:13:23 -0500 360) char const *fentry = "__fentry__";
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 361)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 362) if (symname[0] == '.')
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 363) ++symname; /* ppc64 hack */
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 364) if (strcmp(mcount, symname) == 0 ||
48bb5dc6cd9d3 (Steven Rostedt 2011-02-09 13:13:23 -0500 365) (altmcount && strcmp(altmcount, symname) == 0) ||
48bb5dc6cd9d3 (Steven Rostedt 2011-02-09 13:13:23 -0500 366) (strcmp(fentry, symname) == 0))
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 367) mcountsym = Elf_r_sym(relp);
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 368)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 369) return mcountsym;
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 370) }
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 371)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 372) static void get_sym_str_and_relp(Elf_Shdr const *const relhdr,
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 373) Elf_Ehdr const *const ehdr,
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 374) Elf_Sym const **sym0,
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 375) char const **str0,
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 376) Elf_Rel const **relp)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 377) {
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 378) Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 379) + (void *)ehdr);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 380) unsigned const symsec_sh_link = w(relhdr->sh_link);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 381) Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 382) Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 383) Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 384) + (void *)ehdr);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 385)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 386) *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 387) + (void *)ehdr);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 388)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 389) *str0 = (char const *)(_w(strsec->sh_offset)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 390) + (void *)ehdr);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 391)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 392) *relp = rel0;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 393) }
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 394)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 395) /*
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 396) * Look at the relocations in order to find the calls to mcount.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 397) * Accumulate the section offsets that are found, and their relocation info,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 398) * onto the end of the existing arrays.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 399) */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 400) static uint_t *sift_rel_mcount(uint_t *mlocp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 401) unsigned const offbase,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 402) Elf_Rel **const mrelpp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 403) Elf_Shdr const *const relhdr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 404) Elf_Ehdr const *const ehdr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 405) unsigned const recsym,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 406) uint_t const recval,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 407) unsigned const reltype)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 408) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 409) uint_t *const mloc0 = mlocp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 410) Elf_Rel *mrelp = *mrelpp;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 411) Elf_Sym const *sym0;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 412) char const *str0;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 413) Elf_Rel const *relp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 414) unsigned rel_entsize = _w(relhdr->sh_entsize);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 415) unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 416) unsigned mcountsym = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 417) unsigned t;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 418)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 419) get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 420)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 421) for (t = nrel; t; --t) {
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 422) if (!mcountsym)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 423) mcountsym = get_mcountsym(sym0, relp, str0);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 424)
80e5302e4bc85 (Naveen N. Rao 2019-06-27 00:08:01 +0530 425) if (mcountsym && mcountsym == Elf_r_sym(relp) &&
80e5302e4bc85 (Naveen N. Rao 2019-06-27 00:08:01 +0530 426) !is_fake_mcount(relp)) {
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 427) uint_t const addend =
07d8b595f367f (Martin Schwidefsky 2011-05-10 10:10:40 +0200 428) _w(_w(relp->r_offset) - recval + mcount_adjust);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 429) mrelp->r_offset = _w(offbase
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 430) + ((void *)mlocp - (void *)mloc0));
a2d49358ba9bc (John Reiser 2010-10-27 18:59:07 +0800 431) Elf_r_info(mrelp, recsym, reltype);
dd5477ff3ba97 (Steven Rostedt 2011-04-06 13:21:17 -0400 432) if (rel_entsize == sizeof(Elf_Rela)) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 433) ((Elf_Rela *)mrelp)->r_addend = addend;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 434) *mlocp++ = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 435) } else
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 436) *mlocp++ = addend;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 437)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 438) mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 439) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 440) relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 441) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 442) *mrelpp = mrelp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 443) return mlocp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 444) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 445)
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 446) /*
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 447) * Read the relocation table again, but this time its called on sections
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 448) * that are not going to be traced. The mcount calls here will be converted
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 449) * into nops.
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 450) */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 451) static int nop_mcount(Elf_Shdr const *const relhdr,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 452) Elf_Ehdr const *const ehdr,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 453) const char *const txtname)
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 454) {
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 455) Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 456) + (void *)ehdr);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 457) Elf_Sym const *sym0;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 458) char const *str0;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 459) Elf_Rel const *relp;
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 460) Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)];
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 461) unsigned rel_entsize = _w(relhdr->sh_entsize);
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 462) unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 463) unsigned mcountsym = 0;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 464) unsigned t;
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 465) int once = 0;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 466)
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 467) get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
41b402a201a12 (Steven Rostedt 2011-04-20 21:13:06 -0400 468)
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 469) for (t = nrel; t; --t) {
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 470) int ret = -1;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 471)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 472) if (!mcountsym)
37762cb997762 (Steven Rostedt 2011-04-20 20:47:34 -0400 473) mcountsym = get_mcountsym(sym0, relp, str0);
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 474)
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 475) if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
7f8557b88d6aa (Steven Rostedt (VMware) 2019-10-09 11:05:38 -0400 476) if (make_nop)
c84da8b9ad376 (libin 2015-11-03 08:58:47 +0800 477) ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 478) if (warn_on_notrace_sect && !once) {
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 479) printf("Section %s has mcount callers being ignored\n",
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 480) txtname);
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 481) once = 1;
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 482) /* just warn? */
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 483) if (!make_nop)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 484) return 0;
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 485) }
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 486) }
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 487)
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 488) /*
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 489) * If we successfully removed the mcount, mark the relocation
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 490) * as a nop (don't do anything with it).
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 491) */
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 492) if (!ret) {
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 493) Elf_Rel rel;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 494) rel = *(Elf_Rel *)relp;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 495) Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 496) if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 497) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 498) if (uwrite(&rel, sizeof(rel)) < 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 499) return -1;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 500) }
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 501) relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 502) }
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 503) return 0;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 504) }
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 505)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 506) /*
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 507) * Find a symbol in the given section, to be used as the base for relocating
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 508) * the table of offsets of calls to mcount. A local or global symbol suffices,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 509) * but avoid a Weak symbol because it may be overridden; the change in value
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 510) * would invalidate the relocations of the offsets of the calls to mcount.
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 511) * Often the found symbol will be the unnamed local symbol generated by
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 512) * GNU 'as' for the start of each section. For example:
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 513) * Num: Value Size Type Bind Vis Ndx Name
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 514) * 2: 00000000 0 SECTION LOCAL DEFAULT 1
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 515) */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 516) static int find_secsym_ndx(unsigned const txtndx,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 517) char const *const txtname,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 518) uint_t *const recvalp,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 519) unsigned int *sym_index,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 520) Elf_Shdr const *const symhdr,
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 521) Elf32_Word const *symtab,
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 522) Elf32_Word const *symtab_shndx,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 523) Elf_Ehdr const *const ehdr)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 524) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 525) Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 526) + (void *)ehdr);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 527) unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 528) Elf_Sym const *symp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 529) unsigned t;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 530)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 531) for (symp = sym0, t = nsym; t; --t, ++symp) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 532) unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 533)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 534) if (txtndx == get_symindex(symp, symtab, symtab_shndx)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 535) /* avoid STB_WEAK */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 536) && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 537) /* function symbols on ARM have quirks, avoid them */
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 538) if (w2(ehdr->e_machine) == EM_ARM
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 539) && ELF_ST_TYPE(symp->st_info) == STT_FUNC)
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 540) continue;
9905ce8ad7b79 (Rabin Vincent 2011-05-11 22:53:51 +0530 541)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 542) *recvalp = _w(symp->st_value);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 543) *sym_index = symp - sym0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 544) return 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 545) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 546) }
ac5db1fc89bf8 (nixiaoming 2018-05-24 11:16:12 +0800 547) fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 548) txtndx, txtname);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 549) return -1;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 550) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 551)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 552) /* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 553) static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 554) Elf_Shdr const *const shdr0,
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 555) char const *const shstrtab,
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 556) char const *const fname)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 557) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 558) /* .sh_info depends on .sh_type == SHT_REL[,A] */
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 559) Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 560) char const *const txtname = &shstrtab[w(txthdr->sh_name)];
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 561)
dd5477ff3ba97 (Steven Rostedt 2011-04-06 13:21:17 -0400 562) if (strcmp("__mcount_loc", txtname) == 0) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 563) fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 564) fname);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 565) return already_has_rel_mcount;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 566) }
dd5477ff3ba97 (Steven Rostedt 2011-04-06 13:21:17 -0400 567) if (w(txthdr->sh_type) != SHT_PROGBITS ||
2e885057b7f75 (David Daney 2011-12-19 17:42:42 -0800 568) !(_w(txthdr->sh_flags) & SHF_EXECINSTR))
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 569) return NULL;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 570) return txtname;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 571) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 572)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 573) static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 574) Elf_Shdr const *const shdr0,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 575) char const *const shstrtab,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 576) char const *const fname)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 577) {
dd5477ff3ba97 (Steven Rostedt 2011-04-06 13:21:17 -0400 578) if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 579) return NULL;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 580) return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 581) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 582)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 583)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 584) static unsigned tot_relsize(Elf_Shdr const *const shdr0,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 585) unsigned nhdr,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 586) const char *const shstrtab,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 587) const char *const fname)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 588) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 589) unsigned totrelsz = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 590) Elf_Shdr const *shdrp = shdr0;
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 591) char const *txtname;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 592)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 593) for (; nhdr; --nhdr, ++shdrp) {
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 594) txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 595) if (txtname == already_has_rel_mcount) {
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 596) totrelsz = 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 597) break;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 598) }
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 599) if (txtname && is_mcounted_section_name(txtname))
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 600) totrelsz += _w(shdrp->sh_size);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 601) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 602) return totrelsz;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 603) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 604)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 605) /* Overall supervision for Elf32 ET_REL file. */
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 606) static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
3aec8638246ff (Matt Helsley 2019-07-31 11:24:13 -0700 607) unsigned const reltype)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 608) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 609) Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 610) + (void *)ehdr);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 611) unsigned const nhdr = get_shnum(ehdr, shdr0);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 612) Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)];
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 613) char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 614) + (void *)ehdr);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 615)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 616) Elf_Shdr const *relhdr;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 617) unsigned k;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 618)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 619) Elf32_Word *symtab;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 620) Elf32_Word *symtab_shndx;
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 621)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 622) /* Upper bound on space: assume all relevant relocs are for mcount. */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 623) unsigned totrelsz;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 624)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 625) Elf_Rel * mrel0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 626) Elf_Rel * mrelp;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 627)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 628) uint_t * mloc0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 629) uint_t * mlocp;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 630)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 631) unsigned rel_entsize = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 632) unsigned symsec_sh_link = 0;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 633)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 634) int result = 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 635)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 636) totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 637) if (totrelsz == 0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 638) return 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 639) mrel0 = umalloc(totrelsz);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 640) mrelp = mrel0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 641) if (!mrel0)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 642) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 643)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 644) /* 2*sizeof(address) <= sizeof(Elf_Rel) */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 645) mloc0 = umalloc(totrelsz>>1);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 646) mlocp = mloc0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 647) if (!mloc0) {
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 648) free(mrel0);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 649) return -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 650) }
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 651)
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 652) find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx);
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 653)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 654) for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 655) char const *const txtname = has_rel_mcount(relhdr, shdr0,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 656) shstrtab, fname);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 657) if (txtname == already_has_rel_mcount) {
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 658) result = 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 659) file_updated = 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 660) goto out; /* Nothing to be done; don't append! */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 661) }
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 662) if (txtname && is_mcounted_section_name(txtname)) {
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 663) unsigned int recsym;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 664) uint_t recval = 0;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 665)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 666) symsec_sh_link = w(relhdr->sh_link);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 667) result = find_secsym_ndx(w(relhdr->sh_info), txtname,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 668) &recval, &recsym,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 669) &shdr0[symsec_sh_link],
4ef57b21d6fb4 (Sami Tolvanen 2020-04-24 12:30:46 -0700 670) symtab, symtab_shndx,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 671) ehdr);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 672) if (result)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 673) goto out;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 674)
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 675) rel_entsize = _w(relhdr->sh_entsize);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 676) mlocp = sift_rel_mcount(mlocp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 677) (void *)mlocp - (void *)mloc0, &mrelp,
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 678) relhdr, ehdr, recsym, recval, reltype);
dfad3d598c4bb (Steven Rostedt 2011-04-12 18:53:25 -0400 679) } else if (txtname && (warn_on_notrace_sect || make_nop)) {
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 680) /*
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 681) * This section is ignored by ftrace, but still
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 682) * has mcount calls. Convert them to nops now.
ffd618fa39284 (Steven Rostedt 2011-04-08 03:58:48 -0400 683) */
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 684) if (nop_mcount(relhdr, ehdr, txtname) < 0) {
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 685) result = -1;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 686) goto out;
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 687) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 688) }
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 689) }
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 690) if (!result && mloc0 != mlocp)
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 691) result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 692) rel_entsize, symsec_sh_link);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 693) out:
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 694) free(mrel0);
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 695) free(mloc0);
3f1df12019f33 (Matt Helsley 2019-07-31 11:24:12 -0700 696) return result;
c28d5077f8d79 (Steven Rostedt 2010-10-13 19:06:14 -0400 697) }