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