VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   55 Tags
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) }