162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * recordmcount.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This code was taken out of recordmcount.c written by 662306a36Sopenharmony_ci * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * The original code had the same algorithms for both 32bit 962306a36Sopenharmony_ci * and 64bit ELF files, but the code was duplicated to support 1062306a36Sopenharmony_ci * the difference in structures that were used. This 1162306a36Sopenharmony_ci * file creates a macro of everything that is different between 1262306a36Sopenharmony_ci * the 64 and 32 bit code, such that by including this header 1362306a36Sopenharmony_ci * twice we can create both sets of functions by including this 1462306a36Sopenharmony_ci * header once with RECORD_MCOUNT_64 undefined, and again with 1562306a36Sopenharmony_ci * it defined. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * This conversion to macros was done by: 1862306a36Sopenharmony_ci * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci#undef append_func 2162306a36Sopenharmony_ci#undef is_fake_mcount 2262306a36Sopenharmony_ci#undef fn_is_fake_mcount 2362306a36Sopenharmony_ci#undef MIPS_is_fake_mcount 2462306a36Sopenharmony_ci#undef mcount_adjust 2562306a36Sopenharmony_ci#undef sift_rel_mcount 2662306a36Sopenharmony_ci#undef nop_mcount 2762306a36Sopenharmony_ci#undef find_secsym_ndx 2862306a36Sopenharmony_ci#undef __has_rel_mcount 2962306a36Sopenharmony_ci#undef has_rel_mcount 3062306a36Sopenharmony_ci#undef tot_relsize 3162306a36Sopenharmony_ci#undef get_mcountsym 3262306a36Sopenharmony_ci#undef find_symtab 3362306a36Sopenharmony_ci#undef get_shnum 3462306a36Sopenharmony_ci#undef set_shnum 3562306a36Sopenharmony_ci#undef get_shstrndx 3662306a36Sopenharmony_ci#undef get_symindex 3762306a36Sopenharmony_ci#undef get_sym_str_and_relp 3862306a36Sopenharmony_ci#undef do_func 3962306a36Sopenharmony_ci#undef Elf_Addr 4062306a36Sopenharmony_ci#undef Elf_Ehdr 4162306a36Sopenharmony_ci#undef Elf_Shdr 4262306a36Sopenharmony_ci#undef Elf_Rel 4362306a36Sopenharmony_ci#undef Elf_Rela 4462306a36Sopenharmony_ci#undef Elf_Sym 4562306a36Sopenharmony_ci#undef ELF_R_SYM 4662306a36Sopenharmony_ci#undef Elf_r_sym 4762306a36Sopenharmony_ci#undef ELF_R_INFO 4862306a36Sopenharmony_ci#undef Elf_r_info 4962306a36Sopenharmony_ci#undef ELF_ST_BIND 5062306a36Sopenharmony_ci#undef ELF_ST_TYPE 5162306a36Sopenharmony_ci#undef fn_ELF_R_SYM 5262306a36Sopenharmony_ci#undef fn_ELF_R_INFO 5362306a36Sopenharmony_ci#undef uint_t 5462306a36Sopenharmony_ci#undef _w 5562306a36Sopenharmony_ci#undef _align 5662306a36Sopenharmony_ci#undef _size 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#ifdef RECORD_MCOUNT_64 5962306a36Sopenharmony_ci# define append_func append64 6062306a36Sopenharmony_ci# define sift_rel_mcount sift64_rel_mcount 6162306a36Sopenharmony_ci# define nop_mcount nop_mcount_64 6262306a36Sopenharmony_ci# define find_secsym_ndx find64_secsym_ndx 6362306a36Sopenharmony_ci# define __has_rel_mcount __has64_rel_mcount 6462306a36Sopenharmony_ci# define has_rel_mcount has64_rel_mcount 6562306a36Sopenharmony_ci# define tot_relsize tot64_relsize 6662306a36Sopenharmony_ci# define find_symtab find_symtab64 6762306a36Sopenharmony_ci# define get_shnum get_shnum64 6862306a36Sopenharmony_ci# define set_shnum set_shnum64 6962306a36Sopenharmony_ci# define get_shstrndx get_shstrndx64 7062306a36Sopenharmony_ci# define get_symindex get_symindex64 7162306a36Sopenharmony_ci# define get_sym_str_and_relp get_sym_str_and_relp_64 7262306a36Sopenharmony_ci# define do_func do64 7362306a36Sopenharmony_ci# define get_mcountsym get_mcountsym_64 7462306a36Sopenharmony_ci# define is_fake_mcount is_fake_mcount64 7562306a36Sopenharmony_ci# define fn_is_fake_mcount fn_is_fake_mcount64 7662306a36Sopenharmony_ci# define MIPS_is_fake_mcount MIPS64_is_fake_mcount 7762306a36Sopenharmony_ci# define mcount_adjust mcount_adjust_64 7862306a36Sopenharmony_ci# define Elf_Addr Elf64_Addr 7962306a36Sopenharmony_ci# define Elf_Ehdr Elf64_Ehdr 8062306a36Sopenharmony_ci# define Elf_Shdr Elf64_Shdr 8162306a36Sopenharmony_ci# define Elf_Rel Elf64_Rel 8262306a36Sopenharmony_ci# define Elf_Rela Elf64_Rela 8362306a36Sopenharmony_ci# define Elf_Sym Elf64_Sym 8462306a36Sopenharmony_ci# define ELF_R_SYM ELF64_R_SYM 8562306a36Sopenharmony_ci# define Elf_r_sym Elf64_r_sym 8662306a36Sopenharmony_ci# define ELF_R_INFO ELF64_R_INFO 8762306a36Sopenharmony_ci# define Elf_r_info Elf64_r_info 8862306a36Sopenharmony_ci# define ELF_ST_BIND ELF64_ST_BIND 8962306a36Sopenharmony_ci# define ELF_ST_TYPE ELF64_ST_TYPE 9062306a36Sopenharmony_ci# define fn_ELF_R_SYM fn_ELF64_R_SYM 9162306a36Sopenharmony_ci# define fn_ELF_R_INFO fn_ELF64_R_INFO 9262306a36Sopenharmony_ci# define uint_t uint64_t 9362306a36Sopenharmony_ci# define _w w8 9462306a36Sopenharmony_ci# define _align 7u 9562306a36Sopenharmony_ci# define _size 8 9662306a36Sopenharmony_ci#else 9762306a36Sopenharmony_ci# define append_func append32 9862306a36Sopenharmony_ci# define sift_rel_mcount sift32_rel_mcount 9962306a36Sopenharmony_ci# define nop_mcount nop_mcount_32 10062306a36Sopenharmony_ci# define find_secsym_ndx find32_secsym_ndx 10162306a36Sopenharmony_ci# define __has_rel_mcount __has32_rel_mcount 10262306a36Sopenharmony_ci# define has_rel_mcount has32_rel_mcount 10362306a36Sopenharmony_ci# define tot_relsize tot32_relsize 10462306a36Sopenharmony_ci# define find_symtab find_symtab32 10562306a36Sopenharmony_ci# define get_shnum get_shnum32 10662306a36Sopenharmony_ci# define set_shnum set_shnum32 10762306a36Sopenharmony_ci# define get_shstrndx get_shstrndx32 10862306a36Sopenharmony_ci# define get_symindex get_symindex32 10962306a36Sopenharmony_ci# define get_sym_str_and_relp get_sym_str_and_relp_32 11062306a36Sopenharmony_ci# define do_func do32 11162306a36Sopenharmony_ci# define get_mcountsym get_mcountsym_32 11262306a36Sopenharmony_ci# define is_fake_mcount is_fake_mcount32 11362306a36Sopenharmony_ci# define fn_is_fake_mcount fn_is_fake_mcount32 11462306a36Sopenharmony_ci# define MIPS_is_fake_mcount MIPS32_is_fake_mcount 11562306a36Sopenharmony_ci# define mcount_adjust mcount_adjust_32 11662306a36Sopenharmony_ci# define Elf_Addr Elf32_Addr 11762306a36Sopenharmony_ci# define Elf_Ehdr Elf32_Ehdr 11862306a36Sopenharmony_ci# define Elf_Shdr Elf32_Shdr 11962306a36Sopenharmony_ci# define Elf_Rel Elf32_Rel 12062306a36Sopenharmony_ci# define Elf_Rela Elf32_Rela 12162306a36Sopenharmony_ci# define Elf_Sym Elf32_Sym 12262306a36Sopenharmony_ci# define ELF_R_SYM ELF32_R_SYM 12362306a36Sopenharmony_ci# define Elf_r_sym Elf32_r_sym 12462306a36Sopenharmony_ci# define ELF_R_INFO ELF32_R_INFO 12562306a36Sopenharmony_ci# define Elf_r_info Elf32_r_info 12662306a36Sopenharmony_ci# define ELF_ST_BIND ELF32_ST_BIND 12762306a36Sopenharmony_ci# define ELF_ST_TYPE ELF32_ST_TYPE 12862306a36Sopenharmony_ci# define fn_ELF_R_SYM fn_ELF32_R_SYM 12962306a36Sopenharmony_ci# define fn_ELF_R_INFO fn_ELF32_R_INFO 13062306a36Sopenharmony_ci# define uint_t uint32_t 13162306a36Sopenharmony_ci# define _w w 13262306a36Sopenharmony_ci# define _align 3u 13362306a36Sopenharmony_ci# define _size 4 13462306a36Sopenharmony_ci#endif 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Functions and pointers that do_file() may override for specific e_machine. */ 13762306a36Sopenharmony_cistatic int fn_is_fake_mcount(Elf_Rel const *rp) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_cistatic int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic uint_t fn_ELF_R_SYM(Elf_Rel const *rp) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return ELF_R_SYM(_w(rp->r_info)); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_cistatic uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci rp->r_info = _w(ELF_R_INFO(sym, type)); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_cistatic void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int mcount_adjust = 0; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* 15862306a36Sopenharmony_ci * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st 15962306a36Sopenharmony_ci * _mcount symbol is needed for dynamic function tracer, with it, to disable 16062306a36Sopenharmony_ci * tracing(ftrace_make_nop), the instruction in the position is replaced with 16162306a36Sopenharmony_ci * the "b label" instruction, to enable tracing(ftrace_make_call), replace the 16262306a36Sopenharmony_ci * instruction back. So, here, we set the 2nd one as fake and filter it. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * c: 3c030000 lui v1,0x0 <--> b label 16562306a36Sopenharmony_ci * c: R_MIPS_HI16 _mcount 16662306a36Sopenharmony_ci * c: R_MIPS_NONE *ABS* 16762306a36Sopenharmony_ci * c: R_MIPS_NONE *ABS* 16862306a36Sopenharmony_ci * 10: 64630000 daddiu v1,v1,0 16962306a36Sopenharmony_ci * 10: R_MIPS_LO16 _mcount 17062306a36Sopenharmony_ci * 10: R_MIPS_NONE *ABS* 17162306a36Sopenharmony_ci * 10: R_MIPS_NONE *ABS* 17262306a36Sopenharmony_ci * 14: 03e0082d move at,ra 17362306a36Sopenharmony_ci * 18: 0060f809 jalr v1 17462306a36Sopenharmony_ci * label: 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_ci#define MIPS_FAKEMCOUNT_OFFSET 4 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic int MIPS_is_fake_mcount(Elf_Rel const *rp) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci static Elf_Addr old_r_offset = ~(Elf_Addr)0; 18162306a36Sopenharmony_ci Elf_Addr current_r_offset = _w(rp->r_offset); 18262306a36Sopenharmony_ci int is_fake; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci is_fake = (old_r_offset != ~(Elf_Addr)0) && 18562306a36Sopenharmony_ci (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET); 18662306a36Sopenharmony_ci old_r_offset = current_r_offset; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return is_fake; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab, 19262306a36Sopenharmony_ci Elf32_Word const *symtab_shndx) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci unsigned long offset; 19562306a36Sopenharmony_ci unsigned short shndx = w2(sym->st_shndx); 19662306a36Sopenharmony_ci int index; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (shndx > SHN_UNDEF && shndx < SHN_LORESERVE) 19962306a36Sopenharmony_ci return shndx; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (shndx == SHN_XINDEX) { 20262306a36Sopenharmony_ci offset = (unsigned long)sym - (unsigned long)symtab; 20362306a36Sopenharmony_ci index = offset / sizeof(*sym); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return w(symtab_shndx[index]); 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci if (shdr0 && !ehdr->e_shnum) 21462306a36Sopenharmony_ci return w(shdr0->sh_size); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return w2(ehdr->e_shnum); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci if (new_shnum >= SHN_LORESERVE) { 22262306a36Sopenharmony_ci ehdr->e_shnum = 0; 22362306a36Sopenharmony_ci shdr0->sh_size = w(new_shnum); 22462306a36Sopenharmony_ci } else 22562306a36Sopenharmony_ci ehdr->e_shnum = w2(new_shnum); 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci if (ehdr->e_shstrndx != SHN_XINDEX) 23162306a36Sopenharmony_ci return w2(ehdr->e_shstrndx); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci return w(shdr0->sh_link); 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0, 23762306a36Sopenharmony_ci unsigned const nhdr, Elf32_Word **symtab, 23862306a36Sopenharmony_ci Elf32_Word **symtab_shndx) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci Elf_Shdr const *relhdr; 24162306a36Sopenharmony_ci unsigned k; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci *symtab = NULL; 24462306a36Sopenharmony_ci *symtab_shndx = NULL; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 24762306a36Sopenharmony_ci if (relhdr->sh_type == SHT_SYMTAB) 24862306a36Sopenharmony_ci *symtab = (void *)ehdr + relhdr->sh_offset; 24962306a36Sopenharmony_ci else if (relhdr->sh_type == SHT_SYMTAB_SHNDX) 25062306a36Sopenharmony_ci *symtab_shndx = (void *)ehdr + relhdr->sh_offset; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (*symtab && *symtab_shndx) 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ 25862306a36Sopenharmony_cistatic int append_func(Elf_Ehdr *const ehdr, 25962306a36Sopenharmony_ci Elf_Shdr *const shstr, 26062306a36Sopenharmony_ci uint_t const *const mloc0, 26162306a36Sopenharmony_ci uint_t const *const mlocp, 26262306a36Sopenharmony_ci Elf_Rel const *const mrel0, 26362306a36Sopenharmony_ci Elf_Rel const *const mrelp, 26462306a36Sopenharmony_ci unsigned int const rel_entsize, 26562306a36Sopenharmony_ci unsigned int const symsec_sh_link) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci /* Begin constructing output file */ 26862306a36Sopenharmony_ci Elf_Shdr mcsec; 26962306a36Sopenharmony_ci char const *mc_name = (sizeof(Elf_Rela) == rel_entsize) 27062306a36Sopenharmony_ci ? ".rela__mcount_loc" 27162306a36Sopenharmony_ci : ".rel__mcount_loc"; 27262306a36Sopenharmony_ci uint_t const old_shoff = _w(ehdr->e_shoff); 27362306a36Sopenharmony_ci uint_t const old_shstr_sh_size = _w(shstr->sh_size); 27462306a36Sopenharmony_ci uint_t const old_shstr_sh_offset = _w(shstr->sh_offset); 27562306a36Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr); 27662306a36Sopenharmony_ci unsigned int const old_shnum = get_shnum(ehdr, shdr0); 27762306a36Sopenharmony_ci unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */ 27862306a36Sopenharmony_ci uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size); 27962306a36Sopenharmony_ci uint_t new_e_shoff; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci shstr->sh_size = _w(t); 28262306a36Sopenharmony_ci shstr->sh_offset = _w(sb.st_size); 28362306a36Sopenharmony_ci t += sb.st_size; 28462306a36Sopenharmony_ci t += (_align & -t); /* word-byte align */ 28562306a36Sopenharmony_ci new_e_shoff = t; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci set_shnum(ehdr, shdr0, new_shnum); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* body for new shstrtab */ 29062306a36Sopenharmony_ci if (ulseek(sb.st_size, SEEK_SET) < 0) 29162306a36Sopenharmony_ci return -1; 29262306a36Sopenharmony_ci if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0) 29362306a36Sopenharmony_ci return -1; 29462306a36Sopenharmony_ci if (uwrite(mc_name, 1 + strlen(mc_name)) < 0) 29562306a36Sopenharmony_ci return -1; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* old(modified) Elf_Shdr table, word-byte aligned */ 29862306a36Sopenharmony_ci if (ulseek(t, SEEK_SET) < 0) 29962306a36Sopenharmony_ci return -1; 30062306a36Sopenharmony_ci t += sizeof(Elf_Shdr) * old_shnum; 30162306a36Sopenharmony_ci if (uwrite(old_shoff + (void *)ehdr, 30262306a36Sopenharmony_ci sizeof(Elf_Shdr) * old_shnum) < 0) 30362306a36Sopenharmony_ci return -1; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* new sections __mcount_loc and .rel__mcount_loc */ 30662306a36Sopenharmony_ci t += 2*sizeof(mcsec); 30762306a36Sopenharmony_ci mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel") 30862306a36Sopenharmony_ci + old_shstr_sh_size); 30962306a36Sopenharmony_ci mcsec.sh_type = w(SHT_PROGBITS); 31062306a36Sopenharmony_ci mcsec.sh_flags = _w(SHF_ALLOC); 31162306a36Sopenharmony_ci mcsec.sh_addr = 0; 31262306a36Sopenharmony_ci mcsec.sh_offset = _w(t); 31362306a36Sopenharmony_ci mcsec.sh_size = _w((void *)mlocp - (void *)mloc0); 31462306a36Sopenharmony_ci mcsec.sh_link = 0; 31562306a36Sopenharmony_ci mcsec.sh_info = 0; 31662306a36Sopenharmony_ci mcsec.sh_addralign = _w(_size); 31762306a36Sopenharmony_ci mcsec.sh_entsize = _w(_size); 31862306a36Sopenharmony_ci if (uwrite(&mcsec, sizeof(mcsec)) < 0) 31962306a36Sopenharmony_ci return -1; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci mcsec.sh_name = w(old_shstr_sh_size); 32262306a36Sopenharmony_ci mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize) 32362306a36Sopenharmony_ci ? w(SHT_RELA) 32462306a36Sopenharmony_ci : w(SHT_REL); 32562306a36Sopenharmony_ci mcsec.sh_flags = 0; 32662306a36Sopenharmony_ci mcsec.sh_addr = 0; 32762306a36Sopenharmony_ci mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t); 32862306a36Sopenharmony_ci mcsec.sh_size = _w((void *)mrelp - (void *)mrel0); 32962306a36Sopenharmony_ci mcsec.sh_link = w(symsec_sh_link); 33062306a36Sopenharmony_ci mcsec.sh_info = w(old_shnum); 33162306a36Sopenharmony_ci mcsec.sh_addralign = _w(_size); 33262306a36Sopenharmony_ci mcsec.sh_entsize = _w(rel_entsize); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (uwrite(&mcsec, sizeof(mcsec)) < 0) 33562306a36Sopenharmony_ci return -1; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0) 33862306a36Sopenharmony_ci return -1; 33962306a36Sopenharmony_ci if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0) 34062306a36Sopenharmony_ci return -1; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci ehdr->e_shoff = _w(new_e_shoff); 34362306a36Sopenharmony_ci if (ulseek(0, SEEK_SET) < 0) 34462306a36Sopenharmony_ci return -1; 34562306a36Sopenharmony_ci if (uwrite(ehdr, sizeof(*ehdr)) < 0) 34662306a36Sopenharmony_ci return -1; 34762306a36Sopenharmony_ci return 0; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic unsigned get_mcountsym(Elf_Sym const *const sym0, 35162306a36Sopenharmony_ci Elf_Rel const *relp, 35262306a36Sopenharmony_ci char const *const str0) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci unsigned mcountsym = 0; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci Elf_Sym const *const symp = 35762306a36Sopenharmony_ci &sym0[Elf_r_sym(relp)]; 35862306a36Sopenharmony_ci char const *symname = &str0[w(symp->st_name)]; 35962306a36Sopenharmony_ci char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; 36062306a36Sopenharmony_ci char const *fentry = "__fentry__"; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (symname[0] == '.') 36362306a36Sopenharmony_ci ++symname; /* ppc64 hack */ 36462306a36Sopenharmony_ci if (strcmp(mcount, symname) == 0 || 36562306a36Sopenharmony_ci (altmcount && strcmp(altmcount, symname) == 0) || 36662306a36Sopenharmony_ci (strcmp(fentry, symname) == 0)) 36762306a36Sopenharmony_ci mcountsym = Elf_r_sym(relp); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return mcountsym; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic void get_sym_str_and_relp(Elf_Shdr const *const relhdr, 37362306a36Sopenharmony_ci Elf_Ehdr const *const ehdr, 37462306a36Sopenharmony_ci Elf_Sym const **sym0, 37562306a36Sopenharmony_ci char const **str0, 37662306a36Sopenharmony_ci Elf_Rel const **relp) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 37962306a36Sopenharmony_ci + (void *)ehdr); 38062306a36Sopenharmony_ci unsigned const symsec_sh_link = w(relhdr->sh_link); 38162306a36Sopenharmony_ci Elf_Shdr const *const symsec = &shdr0[symsec_sh_link]; 38262306a36Sopenharmony_ci Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)]; 38362306a36Sopenharmony_ci Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset) 38462306a36Sopenharmony_ci + (void *)ehdr); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset) 38762306a36Sopenharmony_ci + (void *)ehdr); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci *str0 = (char const *)(_w(strsec->sh_offset) 39062306a36Sopenharmony_ci + (void *)ehdr); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci *relp = rel0; 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* 39662306a36Sopenharmony_ci * Look at the relocations in order to find the calls to mcount. 39762306a36Sopenharmony_ci * Accumulate the section offsets that are found, and their relocation info, 39862306a36Sopenharmony_ci * onto the end of the existing arrays. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_cistatic uint_t *sift_rel_mcount(uint_t *mlocp, 40162306a36Sopenharmony_ci unsigned const offbase, 40262306a36Sopenharmony_ci Elf_Rel **const mrelpp, 40362306a36Sopenharmony_ci Elf_Shdr const *const relhdr, 40462306a36Sopenharmony_ci Elf_Ehdr const *const ehdr, 40562306a36Sopenharmony_ci unsigned const recsym, 40662306a36Sopenharmony_ci uint_t const recval, 40762306a36Sopenharmony_ci unsigned const reltype) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci uint_t *const mloc0 = mlocp; 41062306a36Sopenharmony_ci Elf_Rel *mrelp = *mrelpp; 41162306a36Sopenharmony_ci Elf_Sym const *sym0; 41262306a36Sopenharmony_ci char const *str0; 41362306a36Sopenharmony_ci Elf_Rel const *relp; 41462306a36Sopenharmony_ci unsigned rel_entsize = _w(relhdr->sh_entsize); 41562306a36Sopenharmony_ci unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 41662306a36Sopenharmony_ci unsigned mcountsym = 0; 41762306a36Sopenharmony_ci unsigned t; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci for (t = nrel; t; --t) { 42262306a36Sopenharmony_ci if (!mcountsym) 42362306a36Sopenharmony_ci mcountsym = get_mcountsym(sym0, relp, str0); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (mcountsym && mcountsym == Elf_r_sym(relp) && 42662306a36Sopenharmony_ci !is_fake_mcount(relp)) { 42762306a36Sopenharmony_ci uint_t const addend = 42862306a36Sopenharmony_ci _w(_w(relp->r_offset) - recval + mcount_adjust); 42962306a36Sopenharmony_ci mrelp->r_offset = _w(offbase 43062306a36Sopenharmony_ci + ((void *)mlocp - (void *)mloc0)); 43162306a36Sopenharmony_ci Elf_r_info(mrelp, recsym, reltype); 43262306a36Sopenharmony_ci if (rel_entsize == sizeof(Elf_Rela)) { 43362306a36Sopenharmony_ci ((Elf_Rela *)mrelp)->r_addend = addend; 43462306a36Sopenharmony_ci *mlocp++ = 0; 43562306a36Sopenharmony_ci } else 43662306a36Sopenharmony_ci *mlocp++ = addend; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp); 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci relp = (Elf_Rel const *)(rel_entsize + (void *)relp); 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci *mrelpp = mrelp; 44362306a36Sopenharmony_ci return mlocp; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/* 44762306a36Sopenharmony_ci * Read the relocation table again, but this time its called on sections 44862306a36Sopenharmony_ci * that are not going to be traced. The mcount calls here will be converted 44962306a36Sopenharmony_ci * into nops. 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_cistatic int nop_mcount(Elf_Shdr const *const relhdr, 45262306a36Sopenharmony_ci Elf_Ehdr const *const ehdr, 45362306a36Sopenharmony_ci const char *const txtname) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 45662306a36Sopenharmony_ci + (void *)ehdr); 45762306a36Sopenharmony_ci Elf_Sym const *sym0; 45862306a36Sopenharmony_ci char const *str0; 45962306a36Sopenharmony_ci Elf_Rel const *relp; 46062306a36Sopenharmony_ci Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)]; 46162306a36Sopenharmony_ci unsigned rel_entsize = _w(relhdr->sh_entsize); 46262306a36Sopenharmony_ci unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 46362306a36Sopenharmony_ci unsigned mcountsym = 0; 46462306a36Sopenharmony_ci unsigned t; 46562306a36Sopenharmony_ci int once = 0; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci for (t = nrel; t; --t) { 47062306a36Sopenharmony_ci int ret = -1; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (!mcountsym) 47362306a36Sopenharmony_ci mcountsym = get_mcountsym(sym0, relp, str0); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { 47662306a36Sopenharmony_ci if (make_nop) 47762306a36Sopenharmony_ci ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset)); 47862306a36Sopenharmony_ci if (warn_on_notrace_sect && !once) { 47962306a36Sopenharmony_ci printf("Section %s has mcount callers being ignored\n", 48062306a36Sopenharmony_ci txtname); 48162306a36Sopenharmony_ci once = 1; 48262306a36Sopenharmony_ci /* just warn? */ 48362306a36Sopenharmony_ci if (!make_nop) 48462306a36Sopenharmony_ci return 0; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* 48962306a36Sopenharmony_ci * If we successfully removed the mcount, mark the relocation 49062306a36Sopenharmony_ci * as a nop (don't do anything with it). 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_ci if (!ret) { 49362306a36Sopenharmony_ci Elf_Rel rel; 49462306a36Sopenharmony_ci rel = *(Elf_Rel *)relp; 49562306a36Sopenharmony_ci Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop); 49662306a36Sopenharmony_ci if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0) 49762306a36Sopenharmony_ci return -1; 49862306a36Sopenharmony_ci if (uwrite(&rel, sizeof(rel)) < 0) 49962306a36Sopenharmony_ci return -1; 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci relp = (Elf_Rel const *)(rel_entsize + (void *)relp); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci return 0; 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci/* 50762306a36Sopenharmony_ci * Find a symbol in the given section, to be used as the base for relocating 50862306a36Sopenharmony_ci * the table of offsets of calls to mcount. A local or global symbol suffices, 50962306a36Sopenharmony_ci * but avoid a Weak symbol because it may be overridden; the change in value 51062306a36Sopenharmony_ci * would invalidate the relocations of the offsets of the calls to mcount. 51162306a36Sopenharmony_ci * Often the found symbol will be the unnamed local symbol generated by 51262306a36Sopenharmony_ci * GNU 'as' for the start of each section. For example: 51362306a36Sopenharmony_ci * Num: Value Size Type Bind Vis Ndx Name 51462306a36Sopenharmony_ci * 2: 00000000 0 SECTION LOCAL DEFAULT 1 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_cistatic int find_secsym_ndx(unsigned const txtndx, 51762306a36Sopenharmony_ci char const *const txtname, 51862306a36Sopenharmony_ci uint_t *const recvalp, 51962306a36Sopenharmony_ci unsigned int *sym_index, 52062306a36Sopenharmony_ci Elf_Shdr const *const symhdr, 52162306a36Sopenharmony_ci Elf32_Word const *symtab, 52262306a36Sopenharmony_ci Elf32_Word const *symtab_shndx, 52362306a36Sopenharmony_ci Elf_Ehdr const *const ehdr) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset) 52662306a36Sopenharmony_ci + (void *)ehdr); 52762306a36Sopenharmony_ci unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize); 52862306a36Sopenharmony_ci Elf_Sym const *symp; 52962306a36Sopenharmony_ci unsigned t; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci for (symp = sym0, t = nsym; t; --t, ++symp) { 53262306a36Sopenharmony_ci unsigned int const st_bind = ELF_ST_BIND(symp->st_info); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (txtndx == get_symindex(symp, symtab, symtab_shndx) 53562306a36Sopenharmony_ci /* avoid STB_WEAK */ 53662306a36Sopenharmony_ci && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) { 53762306a36Sopenharmony_ci /* function symbols on ARM have quirks, avoid them */ 53862306a36Sopenharmony_ci if (w2(ehdr->e_machine) == EM_ARM 53962306a36Sopenharmony_ci && ELF_ST_TYPE(symp->st_info) == STT_FUNC) 54062306a36Sopenharmony_ci continue; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci *recvalp = _w(symp->st_value); 54362306a36Sopenharmony_ci *sym_index = symp - sym0; 54462306a36Sopenharmony_ci return 0; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci fprintf(stderr, "Cannot find symbol for section %u: %s.\n", 54862306a36Sopenharmony_ci txtndx, txtname); 54962306a36Sopenharmony_ci return -1; 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */ 55362306a36Sopenharmony_cistatic char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */ 55462306a36Sopenharmony_ci Elf_Shdr const *const shdr0, 55562306a36Sopenharmony_ci char const *const shstrtab, 55662306a36Sopenharmony_ci char const *const fname) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci /* .sh_info depends on .sh_type == SHT_REL[,A] */ 55962306a36Sopenharmony_ci Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)]; 56062306a36Sopenharmony_ci char const *const txtname = &shstrtab[w(txthdr->sh_name)]; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (strcmp("__mcount_loc", txtname) == 0) { 56362306a36Sopenharmony_ci fprintf(stderr, "warning: __mcount_loc already exists: %s\n", 56462306a36Sopenharmony_ci fname); 56562306a36Sopenharmony_ci return already_has_rel_mcount; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci if (w(txthdr->sh_type) != SHT_PROGBITS || 56862306a36Sopenharmony_ci !(_w(txthdr->sh_flags) & SHF_EXECINSTR)) 56962306a36Sopenharmony_ci return NULL; 57062306a36Sopenharmony_ci return txtname; 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic char const *has_rel_mcount(Elf_Shdr const *const relhdr, 57462306a36Sopenharmony_ci Elf_Shdr const *const shdr0, 57562306a36Sopenharmony_ci char const *const shstrtab, 57662306a36Sopenharmony_ci char const *const fname) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA) 57962306a36Sopenharmony_ci return NULL; 58062306a36Sopenharmony_ci return __has_rel_mcount(relhdr, shdr0, shstrtab, fname); 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_cistatic unsigned tot_relsize(Elf_Shdr const *const shdr0, 58562306a36Sopenharmony_ci unsigned nhdr, 58662306a36Sopenharmony_ci const char *const shstrtab, 58762306a36Sopenharmony_ci const char *const fname) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci unsigned totrelsz = 0; 59062306a36Sopenharmony_ci Elf_Shdr const *shdrp = shdr0; 59162306a36Sopenharmony_ci char const *txtname; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci for (; nhdr; --nhdr, ++shdrp) { 59462306a36Sopenharmony_ci txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname); 59562306a36Sopenharmony_ci if (txtname == already_has_rel_mcount) { 59662306a36Sopenharmony_ci totrelsz = 0; 59762306a36Sopenharmony_ci break; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci if (txtname && is_mcounted_section_name(txtname)) 60062306a36Sopenharmony_ci totrelsz += _w(shdrp->sh_size); 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci return totrelsz; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci/* Overall supervision for Elf32 ET_REL file. */ 60662306a36Sopenharmony_cistatic int do_func(Elf_Ehdr *const ehdr, char const *const fname, 60762306a36Sopenharmony_ci unsigned const reltype) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 61062306a36Sopenharmony_ci + (void *)ehdr); 61162306a36Sopenharmony_ci unsigned const nhdr = get_shnum(ehdr, shdr0); 61262306a36Sopenharmony_ci Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)]; 61362306a36Sopenharmony_ci char const *const shstrtab = (char const *)(_w(shstr->sh_offset) 61462306a36Sopenharmony_ci + (void *)ehdr); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci Elf_Shdr const *relhdr; 61762306a36Sopenharmony_ci unsigned k; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci Elf32_Word *symtab; 62062306a36Sopenharmony_ci Elf32_Word *symtab_shndx; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci /* Upper bound on space: assume all relevant relocs are for mcount. */ 62362306a36Sopenharmony_ci unsigned totrelsz; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci Elf_Rel * mrel0; 62662306a36Sopenharmony_ci Elf_Rel * mrelp; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci uint_t * mloc0; 62962306a36Sopenharmony_ci uint_t * mlocp; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci unsigned rel_entsize = 0; 63262306a36Sopenharmony_ci unsigned symsec_sh_link = 0; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci int result = 0; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname); 63762306a36Sopenharmony_ci if (totrelsz == 0) 63862306a36Sopenharmony_ci return 0; 63962306a36Sopenharmony_ci mrel0 = umalloc(totrelsz); 64062306a36Sopenharmony_ci mrelp = mrel0; 64162306a36Sopenharmony_ci if (!mrel0) 64262306a36Sopenharmony_ci return -1; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* 2*sizeof(address) <= sizeof(Elf_Rel) */ 64562306a36Sopenharmony_ci mloc0 = umalloc(totrelsz>>1); 64662306a36Sopenharmony_ci mlocp = mloc0; 64762306a36Sopenharmony_ci if (!mloc0) { 64862306a36Sopenharmony_ci free(mrel0); 64962306a36Sopenharmony_ci return -1; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 65562306a36Sopenharmony_ci char const *const txtname = has_rel_mcount(relhdr, shdr0, 65662306a36Sopenharmony_ci shstrtab, fname); 65762306a36Sopenharmony_ci if (txtname == already_has_rel_mcount) { 65862306a36Sopenharmony_ci result = 0; 65962306a36Sopenharmony_ci file_updated = 0; 66062306a36Sopenharmony_ci goto out; /* Nothing to be done; don't append! */ 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci if (txtname && is_mcounted_section_name(txtname)) { 66362306a36Sopenharmony_ci unsigned int recsym; 66462306a36Sopenharmony_ci uint_t recval = 0; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci symsec_sh_link = w(relhdr->sh_link); 66762306a36Sopenharmony_ci result = find_secsym_ndx(w(relhdr->sh_info), txtname, 66862306a36Sopenharmony_ci &recval, &recsym, 66962306a36Sopenharmony_ci &shdr0[symsec_sh_link], 67062306a36Sopenharmony_ci symtab, symtab_shndx, 67162306a36Sopenharmony_ci ehdr); 67262306a36Sopenharmony_ci if (result) 67362306a36Sopenharmony_ci goto out; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci rel_entsize = _w(relhdr->sh_entsize); 67662306a36Sopenharmony_ci mlocp = sift_rel_mcount(mlocp, 67762306a36Sopenharmony_ci (void *)mlocp - (void *)mloc0, &mrelp, 67862306a36Sopenharmony_ci relhdr, ehdr, recsym, recval, reltype); 67962306a36Sopenharmony_ci } else if (txtname && (warn_on_notrace_sect || make_nop)) { 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * This section is ignored by ftrace, but still 68262306a36Sopenharmony_ci * has mcount calls. Convert them to nops now. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ci if (nop_mcount(relhdr, ehdr, txtname) < 0) { 68562306a36Sopenharmony_ci result = -1; 68662306a36Sopenharmony_ci goto out; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci if (!result && mloc0 != mlocp) 69162306a36Sopenharmony_ci result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp, 69262306a36Sopenharmony_ci rel_entsize, symsec_sh_link); 69362306a36Sopenharmony_ciout: 69462306a36Sopenharmony_ci free(mrel0); 69562306a36Sopenharmony_ci free(mloc0); 69662306a36Sopenharmony_ci return result; 69762306a36Sopenharmony_ci} 698