18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * recordmcount.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This code was taken out of recordmcount.c written by 68c2ecf20Sopenharmony_ci * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * The original code had the same algorithms for both 32bit 98c2ecf20Sopenharmony_ci * and 64bit ELF files, but the code was duplicated to support 108c2ecf20Sopenharmony_ci * the difference in structures that were used. This 118c2ecf20Sopenharmony_ci * file creates a macro of everything that is different between 128c2ecf20Sopenharmony_ci * the 64 and 32 bit code, such that by including this header 138c2ecf20Sopenharmony_ci * twice we can create both sets of functions by including this 148c2ecf20Sopenharmony_ci * header once with RECORD_MCOUNT_64 undefined, and again with 158c2ecf20Sopenharmony_ci * it defined. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * This conversion to macros was done by: 188c2ecf20Sopenharmony_ci * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci#undef append_func 218c2ecf20Sopenharmony_ci#undef is_fake_mcount 228c2ecf20Sopenharmony_ci#undef fn_is_fake_mcount 238c2ecf20Sopenharmony_ci#undef MIPS_is_fake_mcount 248c2ecf20Sopenharmony_ci#undef mcount_adjust 258c2ecf20Sopenharmony_ci#undef sift_rel_mcount 268c2ecf20Sopenharmony_ci#undef nop_mcount 278c2ecf20Sopenharmony_ci#undef find_secsym_ndx 288c2ecf20Sopenharmony_ci#undef __has_rel_mcount 298c2ecf20Sopenharmony_ci#undef has_rel_mcount 308c2ecf20Sopenharmony_ci#undef tot_relsize 318c2ecf20Sopenharmony_ci#undef get_mcountsym 328c2ecf20Sopenharmony_ci#undef find_symtab 338c2ecf20Sopenharmony_ci#undef get_shnum 348c2ecf20Sopenharmony_ci#undef set_shnum 358c2ecf20Sopenharmony_ci#undef get_shstrndx 368c2ecf20Sopenharmony_ci#undef get_symindex 378c2ecf20Sopenharmony_ci#undef get_sym_str_and_relp 388c2ecf20Sopenharmony_ci#undef do_func 398c2ecf20Sopenharmony_ci#undef Elf_Addr 408c2ecf20Sopenharmony_ci#undef Elf_Ehdr 418c2ecf20Sopenharmony_ci#undef Elf_Shdr 428c2ecf20Sopenharmony_ci#undef Elf_Rel 438c2ecf20Sopenharmony_ci#undef Elf_Rela 448c2ecf20Sopenharmony_ci#undef Elf_Sym 458c2ecf20Sopenharmony_ci#undef ELF_R_SYM 468c2ecf20Sopenharmony_ci#undef Elf_r_sym 478c2ecf20Sopenharmony_ci#undef ELF_R_INFO 488c2ecf20Sopenharmony_ci#undef Elf_r_info 498c2ecf20Sopenharmony_ci#undef ELF_ST_BIND 508c2ecf20Sopenharmony_ci#undef ELF_ST_TYPE 518c2ecf20Sopenharmony_ci#undef fn_ELF_R_SYM 528c2ecf20Sopenharmony_ci#undef fn_ELF_R_INFO 538c2ecf20Sopenharmony_ci#undef uint_t 548c2ecf20Sopenharmony_ci#undef _w 558c2ecf20Sopenharmony_ci#undef _align 568c2ecf20Sopenharmony_ci#undef _size 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#ifdef RECORD_MCOUNT_64 598c2ecf20Sopenharmony_ci# define append_func append64 608c2ecf20Sopenharmony_ci# define sift_rel_mcount sift64_rel_mcount 618c2ecf20Sopenharmony_ci# define nop_mcount nop_mcount_64 628c2ecf20Sopenharmony_ci# define find_secsym_ndx find64_secsym_ndx 638c2ecf20Sopenharmony_ci# define __has_rel_mcount __has64_rel_mcount 648c2ecf20Sopenharmony_ci# define has_rel_mcount has64_rel_mcount 658c2ecf20Sopenharmony_ci# define tot_relsize tot64_relsize 668c2ecf20Sopenharmony_ci# define find_symtab find_symtab64 678c2ecf20Sopenharmony_ci# define get_shnum get_shnum64 688c2ecf20Sopenharmony_ci# define set_shnum set_shnum64 698c2ecf20Sopenharmony_ci# define get_shstrndx get_shstrndx64 708c2ecf20Sopenharmony_ci# define get_symindex get_symindex64 718c2ecf20Sopenharmony_ci# define get_sym_str_and_relp get_sym_str_and_relp_64 728c2ecf20Sopenharmony_ci# define do_func do64 738c2ecf20Sopenharmony_ci# define get_mcountsym get_mcountsym_64 748c2ecf20Sopenharmony_ci# define is_fake_mcount is_fake_mcount64 758c2ecf20Sopenharmony_ci# define fn_is_fake_mcount fn_is_fake_mcount64 768c2ecf20Sopenharmony_ci# define MIPS_is_fake_mcount MIPS64_is_fake_mcount 778c2ecf20Sopenharmony_ci# define mcount_adjust mcount_adjust_64 788c2ecf20Sopenharmony_ci# define Elf_Addr Elf64_Addr 798c2ecf20Sopenharmony_ci# define Elf_Ehdr Elf64_Ehdr 808c2ecf20Sopenharmony_ci# define Elf_Shdr Elf64_Shdr 818c2ecf20Sopenharmony_ci# define Elf_Rel Elf64_Rel 828c2ecf20Sopenharmony_ci# define Elf_Rela Elf64_Rela 838c2ecf20Sopenharmony_ci# define Elf_Sym Elf64_Sym 848c2ecf20Sopenharmony_ci# define ELF_R_SYM ELF64_R_SYM 858c2ecf20Sopenharmony_ci# define Elf_r_sym Elf64_r_sym 868c2ecf20Sopenharmony_ci# define ELF_R_INFO ELF64_R_INFO 878c2ecf20Sopenharmony_ci# define Elf_r_info Elf64_r_info 888c2ecf20Sopenharmony_ci# define ELF_ST_BIND ELF64_ST_BIND 898c2ecf20Sopenharmony_ci# define ELF_ST_TYPE ELF64_ST_TYPE 908c2ecf20Sopenharmony_ci# define fn_ELF_R_SYM fn_ELF64_R_SYM 918c2ecf20Sopenharmony_ci# define fn_ELF_R_INFO fn_ELF64_R_INFO 928c2ecf20Sopenharmony_ci# define uint_t uint64_t 938c2ecf20Sopenharmony_ci# define _w w8 948c2ecf20Sopenharmony_ci# define _align 7u 958c2ecf20Sopenharmony_ci# define _size 8 968c2ecf20Sopenharmony_ci#else 978c2ecf20Sopenharmony_ci# define append_func append32 988c2ecf20Sopenharmony_ci# define sift_rel_mcount sift32_rel_mcount 998c2ecf20Sopenharmony_ci# define nop_mcount nop_mcount_32 1008c2ecf20Sopenharmony_ci# define find_secsym_ndx find32_secsym_ndx 1018c2ecf20Sopenharmony_ci# define __has_rel_mcount __has32_rel_mcount 1028c2ecf20Sopenharmony_ci# define has_rel_mcount has32_rel_mcount 1038c2ecf20Sopenharmony_ci# define tot_relsize tot32_relsize 1048c2ecf20Sopenharmony_ci# define find_symtab find_symtab32 1058c2ecf20Sopenharmony_ci# define get_shnum get_shnum32 1068c2ecf20Sopenharmony_ci# define set_shnum set_shnum32 1078c2ecf20Sopenharmony_ci# define get_shstrndx get_shstrndx32 1088c2ecf20Sopenharmony_ci# define get_symindex get_symindex32 1098c2ecf20Sopenharmony_ci# define get_sym_str_and_relp get_sym_str_and_relp_32 1108c2ecf20Sopenharmony_ci# define do_func do32 1118c2ecf20Sopenharmony_ci# define get_mcountsym get_mcountsym_32 1128c2ecf20Sopenharmony_ci# define is_fake_mcount is_fake_mcount32 1138c2ecf20Sopenharmony_ci# define fn_is_fake_mcount fn_is_fake_mcount32 1148c2ecf20Sopenharmony_ci# define MIPS_is_fake_mcount MIPS32_is_fake_mcount 1158c2ecf20Sopenharmony_ci# define mcount_adjust mcount_adjust_32 1168c2ecf20Sopenharmony_ci# define Elf_Addr Elf32_Addr 1178c2ecf20Sopenharmony_ci# define Elf_Ehdr Elf32_Ehdr 1188c2ecf20Sopenharmony_ci# define Elf_Shdr Elf32_Shdr 1198c2ecf20Sopenharmony_ci# define Elf_Rel Elf32_Rel 1208c2ecf20Sopenharmony_ci# define Elf_Rela Elf32_Rela 1218c2ecf20Sopenharmony_ci# define Elf_Sym Elf32_Sym 1228c2ecf20Sopenharmony_ci# define ELF_R_SYM ELF32_R_SYM 1238c2ecf20Sopenharmony_ci# define Elf_r_sym Elf32_r_sym 1248c2ecf20Sopenharmony_ci# define ELF_R_INFO ELF32_R_INFO 1258c2ecf20Sopenharmony_ci# define Elf_r_info Elf32_r_info 1268c2ecf20Sopenharmony_ci# define ELF_ST_BIND ELF32_ST_BIND 1278c2ecf20Sopenharmony_ci# define ELF_ST_TYPE ELF32_ST_TYPE 1288c2ecf20Sopenharmony_ci# define fn_ELF_R_SYM fn_ELF32_R_SYM 1298c2ecf20Sopenharmony_ci# define fn_ELF_R_INFO fn_ELF32_R_INFO 1308c2ecf20Sopenharmony_ci# define uint_t uint32_t 1318c2ecf20Sopenharmony_ci# define _w w 1328c2ecf20Sopenharmony_ci# define _align 3u 1338c2ecf20Sopenharmony_ci# define _size 4 1348c2ecf20Sopenharmony_ci#endif 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* Functions and pointers that do_file() may override for specific e_machine. */ 1378c2ecf20Sopenharmony_cistatic int fn_is_fake_mcount(Elf_Rel const *rp) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci return 0; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_cistatic int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic uint_t fn_ELF_R_SYM(Elf_Rel const *rp) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci return ELF_R_SYM(_w(rp->r_info)); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_cistatic uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci rp->r_info = _w(ELF_R_INFO(sym, type)); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_cistatic void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int mcount_adjust = 0; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* 1588c2ecf20Sopenharmony_ci * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st 1598c2ecf20Sopenharmony_ci * _mcount symbol is needed for dynamic function tracer, with it, to disable 1608c2ecf20Sopenharmony_ci * tracing(ftrace_make_nop), the instruction in the position is replaced with 1618c2ecf20Sopenharmony_ci * the "b label" instruction, to enable tracing(ftrace_make_call), replace the 1628c2ecf20Sopenharmony_ci * instruction back. So, here, we set the 2nd one as fake and filter it. 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * c: 3c030000 lui v1,0x0 <--> b label 1658c2ecf20Sopenharmony_ci * c: R_MIPS_HI16 _mcount 1668c2ecf20Sopenharmony_ci * c: R_MIPS_NONE *ABS* 1678c2ecf20Sopenharmony_ci * c: R_MIPS_NONE *ABS* 1688c2ecf20Sopenharmony_ci * 10: 64630000 daddiu v1,v1,0 1698c2ecf20Sopenharmony_ci * 10: R_MIPS_LO16 _mcount 1708c2ecf20Sopenharmony_ci * 10: R_MIPS_NONE *ABS* 1718c2ecf20Sopenharmony_ci * 10: R_MIPS_NONE *ABS* 1728c2ecf20Sopenharmony_ci * 14: 03e0082d move at,ra 1738c2ecf20Sopenharmony_ci * 18: 0060f809 jalr v1 1748c2ecf20Sopenharmony_ci * label: 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci#define MIPS_FAKEMCOUNT_OFFSET 4 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic int MIPS_is_fake_mcount(Elf_Rel const *rp) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci static Elf_Addr old_r_offset = ~(Elf_Addr)0; 1818c2ecf20Sopenharmony_ci Elf_Addr current_r_offset = _w(rp->r_offset); 1828c2ecf20Sopenharmony_ci int is_fake; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci is_fake = (old_r_offset != ~(Elf_Addr)0) && 1858c2ecf20Sopenharmony_ci (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET); 1868c2ecf20Sopenharmony_ci old_r_offset = current_r_offset; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return is_fake; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab, 1928c2ecf20Sopenharmony_ci Elf32_Word const *symtab_shndx) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci unsigned long offset; 1958c2ecf20Sopenharmony_ci unsigned short shndx = w2(sym->st_shndx); 1968c2ecf20Sopenharmony_ci int index; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (shndx > SHN_UNDEF && shndx < SHN_LORESERVE) 1998c2ecf20Sopenharmony_ci return shndx; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (shndx == SHN_XINDEX) { 2028c2ecf20Sopenharmony_ci offset = (unsigned long)sym - (unsigned long)symtab; 2038c2ecf20Sopenharmony_ci index = offset / sizeof(*sym); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci return w(symtab_shndx[index]); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return 0; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci if (shdr0 && !ehdr->e_shnum) 2148c2ecf20Sopenharmony_ci return w(shdr0->sh_size); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return w2(ehdr->e_shnum); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci if (new_shnum >= SHN_LORESERVE) { 2228c2ecf20Sopenharmony_ci ehdr->e_shnum = 0; 2238c2ecf20Sopenharmony_ci shdr0->sh_size = w(new_shnum); 2248c2ecf20Sopenharmony_ci } else 2258c2ecf20Sopenharmony_ci ehdr->e_shnum = w2(new_shnum); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci if (ehdr->e_shstrndx != SHN_XINDEX) 2318c2ecf20Sopenharmony_ci return w2(ehdr->e_shstrndx); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return w(shdr0->sh_link); 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0, 2378c2ecf20Sopenharmony_ci unsigned const nhdr, Elf32_Word **symtab, 2388c2ecf20Sopenharmony_ci Elf32_Word **symtab_shndx) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci Elf_Shdr const *relhdr; 2418c2ecf20Sopenharmony_ci unsigned k; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci *symtab = NULL; 2448c2ecf20Sopenharmony_ci *symtab_shndx = NULL; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 2478c2ecf20Sopenharmony_ci if (relhdr->sh_type == SHT_SYMTAB) 2488c2ecf20Sopenharmony_ci *symtab = (void *)ehdr + relhdr->sh_offset; 2498c2ecf20Sopenharmony_ci else if (relhdr->sh_type == SHT_SYMTAB_SHNDX) 2508c2ecf20Sopenharmony_ci *symtab_shndx = (void *)ehdr + relhdr->sh_offset; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (*symtab && *symtab_shndx) 2538c2ecf20Sopenharmony_ci break; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ 2588c2ecf20Sopenharmony_cistatic int append_func(Elf_Ehdr *const ehdr, 2598c2ecf20Sopenharmony_ci Elf_Shdr *const shstr, 2608c2ecf20Sopenharmony_ci uint_t const *const mloc0, 2618c2ecf20Sopenharmony_ci uint_t const *const mlocp, 2628c2ecf20Sopenharmony_ci Elf_Rel const *const mrel0, 2638c2ecf20Sopenharmony_ci Elf_Rel const *const mrelp, 2648c2ecf20Sopenharmony_ci unsigned int const rel_entsize, 2658c2ecf20Sopenharmony_ci unsigned int const symsec_sh_link) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci /* Begin constructing output file */ 2688c2ecf20Sopenharmony_ci Elf_Shdr mcsec; 2698c2ecf20Sopenharmony_ci char const *mc_name = (sizeof(Elf_Rela) == rel_entsize) 2708c2ecf20Sopenharmony_ci ? ".rela__mcount_loc" 2718c2ecf20Sopenharmony_ci : ".rel__mcount_loc"; 2728c2ecf20Sopenharmony_ci uint_t const old_shoff = _w(ehdr->e_shoff); 2738c2ecf20Sopenharmony_ci uint_t const old_shstr_sh_size = _w(shstr->sh_size); 2748c2ecf20Sopenharmony_ci uint_t const old_shstr_sh_offset = _w(shstr->sh_offset); 2758c2ecf20Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr); 2768c2ecf20Sopenharmony_ci unsigned int const old_shnum = get_shnum(ehdr, shdr0); 2778c2ecf20Sopenharmony_ci unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */ 2788c2ecf20Sopenharmony_ci uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size); 2798c2ecf20Sopenharmony_ci uint_t new_e_shoff; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci shstr->sh_size = _w(t); 2828c2ecf20Sopenharmony_ci shstr->sh_offset = _w(sb.st_size); 2838c2ecf20Sopenharmony_ci t += sb.st_size; 2848c2ecf20Sopenharmony_ci t += (_align & -t); /* word-byte align */ 2858c2ecf20Sopenharmony_ci new_e_shoff = t; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci set_shnum(ehdr, shdr0, new_shnum); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* body for new shstrtab */ 2908c2ecf20Sopenharmony_ci if (ulseek(sb.st_size, SEEK_SET) < 0) 2918c2ecf20Sopenharmony_ci return -1; 2928c2ecf20Sopenharmony_ci if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0) 2938c2ecf20Sopenharmony_ci return -1; 2948c2ecf20Sopenharmony_ci if (uwrite(mc_name, 1 + strlen(mc_name)) < 0) 2958c2ecf20Sopenharmony_ci return -1; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* old(modified) Elf_Shdr table, word-byte aligned */ 2988c2ecf20Sopenharmony_ci if (ulseek(t, SEEK_SET) < 0) 2998c2ecf20Sopenharmony_ci return -1; 3008c2ecf20Sopenharmony_ci t += sizeof(Elf_Shdr) * old_shnum; 3018c2ecf20Sopenharmony_ci if (uwrite(old_shoff + (void *)ehdr, 3028c2ecf20Sopenharmony_ci sizeof(Elf_Shdr) * old_shnum) < 0) 3038c2ecf20Sopenharmony_ci return -1; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* new sections __mcount_loc and .rel__mcount_loc */ 3068c2ecf20Sopenharmony_ci t += 2*sizeof(mcsec); 3078c2ecf20Sopenharmony_ci mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel") 3088c2ecf20Sopenharmony_ci + old_shstr_sh_size); 3098c2ecf20Sopenharmony_ci mcsec.sh_type = w(SHT_PROGBITS); 3108c2ecf20Sopenharmony_ci mcsec.sh_flags = _w(SHF_ALLOC); 3118c2ecf20Sopenharmony_ci mcsec.sh_addr = 0; 3128c2ecf20Sopenharmony_ci mcsec.sh_offset = _w(t); 3138c2ecf20Sopenharmony_ci mcsec.sh_size = _w((void *)mlocp - (void *)mloc0); 3148c2ecf20Sopenharmony_ci mcsec.sh_link = 0; 3158c2ecf20Sopenharmony_ci mcsec.sh_info = 0; 3168c2ecf20Sopenharmony_ci mcsec.sh_addralign = _w(_size); 3178c2ecf20Sopenharmony_ci mcsec.sh_entsize = _w(_size); 3188c2ecf20Sopenharmony_ci if (uwrite(&mcsec, sizeof(mcsec)) < 0) 3198c2ecf20Sopenharmony_ci return -1; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci mcsec.sh_name = w(old_shstr_sh_size); 3228c2ecf20Sopenharmony_ci mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize) 3238c2ecf20Sopenharmony_ci ? w(SHT_RELA) 3248c2ecf20Sopenharmony_ci : w(SHT_REL); 3258c2ecf20Sopenharmony_ci mcsec.sh_flags = 0; 3268c2ecf20Sopenharmony_ci mcsec.sh_addr = 0; 3278c2ecf20Sopenharmony_ci mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t); 3288c2ecf20Sopenharmony_ci mcsec.sh_size = _w((void *)mrelp - (void *)mrel0); 3298c2ecf20Sopenharmony_ci mcsec.sh_link = w(symsec_sh_link); 3308c2ecf20Sopenharmony_ci mcsec.sh_info = w(old_shnum); 3318c2ecf20Sopenharmony_ci mcsec.sh_addralign = _w(_size); 3328c2ecf20Sopenharmony_ci mcsec.sh_entsize = _w(rel_entsize); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (uwrite(&mcsec, sizeof(mcsec)) < 0) 3358c2ecf20Sopenharmony_ci return -1; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0) 3388c2ecf20Sopenharmony_ci return -1; 3398c2ecf20Sopenharmony_ci if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0) 3408c2ecf20Sopenharmony_ci return -1; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci ehdr->e_shoff = _w(new_e_shoff); 3438c2ecf20Sopenharmony_ci if (ulseek(0, SEEK_SET) < 0) 3448c2ecf20Sopenharmony_ci return -1; 3458c2ecf20Sopenharmony_ci if (uwrite(ehdr, sizeof(*ehdr)) < 0) 3468c2ecf20Sopenharmony_ci return -1; 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic unsigned get_mcountsym(Elf_Sym const *const sym0, 3518c2ecf20Sopenharmony_ci Elf_Rel const *relp, 3528c2ecf20Sopenharmony_ci char const *const str0) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci unsigned mcountsym = 0; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci Elf_Sym const *const symp = 3578c2ecf20Sopenharmony_ci &sym0[Elf_r_sym(relp)]; 3588c2ecf20Sopenharmony_ci char const *symname = &str0[w(symp->st_name)]; 3598c2ecf20Sopenharmony_ci char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; 3608c2ecf20Sopenharmony_ci char const *fentry = "__fentry__"; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (symname[0] == '.') 3638c2ecf20Sopenharmony_ci ++symname; /* ppc64 hack */ 3648c2ecf20Sopenharmony_ci if (strcmp(mcount, symname) == 0 || 3658c2ecf20Sopenharmony_ci (altmcount && strcmp(altmcount, symname) == 0) || 3668c2ecf20Sopenharmony_ci (strcmp(fentry, symname) == 0)) 3678c2ecf20Sopenharmony_ci mcountsym = Elf_r_sym(relp); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci return mcountsym; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic void get_sym_str_and_relp(Elf_Shdr const *const relhdr, 3738c2ecf20Sopenharmony_ci Elf_Ehdr const *const ehdr, 3748c2ecf20Sopenharmony_ci Elf_Sym const **sym0, 3758c2ecf20Sopenharmony_ci char const **str0, 3768c2ecf20Sopenharmony_ci Elf_Rel const **relp) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 3798c2ecf20Sopenharmony_ci + (void *)ehdr); 3808c2ecf20Sopenharmony_ci unsigned const symsec_sh_link = w(relhdr->sh_link); 3818c2ecf20Sopenharmony_ci Elf_Shdr const *const symsec = &shdr0[symsec_sh_link]; 3828c2ecf20Sopenharmony_ci Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)]; 3838c2ecf20Sopenharmony_ci Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset) 3848c2ecf20Sopenharmony_ci + (void *)ehdr); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset) 3878c2ecf20Sopenharmony_ci + (void *)ehdr); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci *str0 = (char const *)(_w(strsec->sh_offset) 3908c2ecf20Sopenharmony_ci + (void *)ehdr); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci *relp = rel0; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* 3968c2ecf20Sopenharmony_ci * Look at the relocations in order to find the calls to mcount. 3978c2ecf20Sopenharmony_ci * Accumulate the section offsets that are found, and their relocation info, 3988c2ecf20Sopenharmony_ci * onto the end of the existing arrays. 3998c2ecf20Sopenharmony_ci */ 4008c2ecf20Sopenharmony_cistatic uint_t *sift_rel_mcount(uint_t *mlocp, 4018c2ecf20Sopenharmony_ci unsigned const offbase, 4028c2ecf20Sopenharmony_ci Elf_Rel **const mrelpp, 4038c2ecf20Sopenharmony_ci Elf_Shdr const *const relhdr, 4048c2ecf20Sopenharmony_ci Elf_Ehdr const *const ehdr, 4058c2ecf20Sopenharmony_ci unsigned const recsym, 4068c2ecf20Sopenharmony_ci uint_t const recval, 4078c2ecf20Sopenharmony_ci unsigned const reltype) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci uint_t *const mloc0 = mlocp; 4108c2ecf20Sopenharmony_ci Elf_Rel *mrelp = *mrelpp; 4118c2ecf20Sopenharmony_ci Elf_Sym const *sym0; 4128c2ecf20Sopenharmony_ci char const *str0; 4138c2ecf20Sopenharmony_ci Elf_Rel const *relp; 4148c2ecf20Sopenharmony_ci unsigned rel_entsize = _w(relhdr->sh_entsize); 4158c2ecf20Sopenharmony_ci unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 4168c2ecf20Sopenharmony_ci unsigned mcountsym = 0; 4178c2ecf20Sopenharmony_ci unsigned t; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci for (t = nrel; t; --t) { 4228c2ecf20Sopenharmony_ci if (!mcountsym) 4238c2ecf20Sopenharmony_ci mcountsym = get_mcountsym(sym0, relp, str0); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (mcountsym && mcountsym == Elf_r_sym(relp) && 4268c2ecf20Sopenharmony_ci !is_fake_mcount(relp)) { 4278c2ecf20Sopenharmony_ci uint_t const addend = 4288c2ecf20Sopenharmony_ci _w(_w(relp->r_offset) - recval + mcount_adjust); 4298c2ecf20Sopenharmony_ci mrelp->r_offset = _w(offbase 4308c2ecf20Sopenharmony_ci + ((void *)mlocp - (void *)mloc0)); 4318c2ecf20Sopenharmony_ci Elf_r_info(mrelp, recsym, reltype); 4328c2ecf20Sopenharmony_ci if (rel_entsize == sizeof(Elf_Rela)) { 4338c2ecf20Sopenharmony_ci ((Elf_Rela *)mrelp)->r_addend = addend; 4348c2ecf20Sopenharmony_ci *mlocp++ = 0; 4358c2ecf20Sopenharmony_ci } else 4368c2ecf20Sopenharmony_ci *mlocp++ = addend; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp); 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci relp = (Elf_Rel const *)(rel_entsize + (void *)relp); 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci *mrelpp = mrelp; 4438c2ecf20Sopenharmony_ci return mlocp; 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci/* 4478c2ecf20Sopenharmony_ci * Read the relocation table again, but this time its called on sections 4488c2ecf20Sopenharmony_ci * that are not going to be traced. The mcount calls here will be converted 4498c2ecf20Sopenharmony_ci * into nops. 4508c2ecf20Sopenharmony_ci */ 4518c2ecf20Sopenharmony_cistatic int nop_mcount(Elf_Shdr const *const relhdr, 4528c2ecf20Sopenharmony_ci Elf_Ehdr const *const ehdr, 4538c2ecf20Sopenharmony_ci const char *const txtname) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 4568c2ecf20Sopenharmony_ci + (void *)ehdr); 4578c2ecf20Sopenharmony_ci Elf_Sym const *sym0; 4588c2ecf20Sopenharmony_ci char const *str0; 4598c2ecf20Sopenharmony_ci Elf_Rel const *relp; 4608c2ecf20Sopenharmony_ci Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)]; 4618c2ecf20Sopenharmony_ci unsigned rel_entsize = _w(relhdr->sh_entsize); 4628c2ecf20Sopenharmony_ci unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; 4638c2ecf20Sopenharmony_ci unsigned mcountsym = 0; 4648c2ecf20Sopenharmony_ci unsigned t; 4658c2ecf20Sopenharmony_ci int once = 0; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci for (t = nrel; t; --t) { 4708c2ecf20Sopenharmony_ci int ret = -1; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (!mcountsym) 4738c2ecf20Sopenharmony_ci mcountsym = get_mcountsym(sym0, relp, str0); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { 4768c2ecf20Sopenharmony_ci if (make_nop) 4778c2ecf20Sopenharmony_ci ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset)); 4788c2ecf20Sopenharmony_ci if (warn_on_notrace_sect && !once) { 4798c2ecf20Sopenharmony_ci printf("Section %s has mcount callers being ignored\n", 4808c2ecf20Sopenharmony_ci txtname); 4818c2ecf20Sopenharmony_ci once = 1; 4828c2ecf20Sopenharmony_ci /* just warn? */ 4838c2ecf20Sopenharmony_ci if (!make_nop) 4848c2ecf20Sopenharmony_ci return 0; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* 4898c2ecf20Sopenharmony_ci * If we successfully removed the mcount, mark the relocation 4908c2ecf20Sopenharmony_ci * as a nop (don't do anything with it). 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci if (!ret) { 4938c2ecf20Sopenharmony_ci Elf_Rel rel; 4948c2ecf20Sopenharmony_ci rel = *(Elf_Rel *)relp; 4958c2ecf20Sopenharmony_ci Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop); 4968c2ecf20Sopenharmony_ci if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0) 4978c2ecf20Sopenharmony_ci return -1; 4988c2ecf20Sopenharmony_ci if (uwrite(&rel, sizeof(rel)) < 0) 4998c2ecf20Sopenharmony_ci return -1; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci relp = (Elf_Rel const *)(rel_entsize + (void *)relp); 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci return 0; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci/* 5078c2ecf20Sopenharmony_ci * Find a symbol in the given section, to be used as the base for relocating 5088c2ecf20Sopenharmony_ci * the table of offsets of calls to mcount. A local or global symbol suffices, 5098c2ecf20Sopenharmony_ci * but avoid a Weak symbol because it may be overridden; the change in value 5108c2ecf20Sopenharmony_ci * would invalidate the relocations of the offsets of the calls to mcount. 5118c2ecf20Sopenharmony_ci * Often the found symbol will be the unnamed local symbol generated by 5128c2ecf20Sopenharmony_ci * GNU 'as' for the start of each section. For example: 5138c2ecf20Sopenharmony_ci * Num: Value Size Type Bind Vis Ndx Name 5148c2ecf20Sopenharmony_ci * 2: 00000000 0 SECTION LOCAL DEFAULT 1 5158c2ecf20Sopenharmony_ci */ 5168c2ecf20Sopenharmony_cistatic int find_secsym_ndx(unsigned const txtndx, 5178c2ecf20Sopenharmony_ci char const *const txtname, 5188c2ecf20Sopenharmony_ci uint_t *const recvalp, 5198c2ecf20Sopenharmony_ci unsigned int *sym_index, 5208c2ecf20Sopenharmony_ci Elf_Shdr const *const symhdr, 5218c2ecf20Sopenharmony_ci Elf32_Word const *symtab, 5228c2ecf20Sopenharmony_ci Elf32_Word const *symtab_shndx, 5238c2ecf20Sopenharmony_ci Elf_Ehdr const *const ehdr) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset) 5268c2ecf20Sopenharmony_ci + (void *)ehdr); 5278c2ecf20Sopenharmony_ci unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize); 5288c2ecf20Sopenharmony_ci Elf_Sym const *symp; 5298c2ecf20Sopenharmony_ci unsigned t; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci for (symp = sym0, t = nsym; t; --t, ++symp) { 5328c2ecf20Sopenharmony_ci unsigned int const st_bind = ELF_ST_BIND(symp->st_info); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci if (txtndx == get_symindex(symp, symtab, symtab_shndx) 5358c2ecf20Sopenharmony_ci /* avoid STB_WEAK */ 5368c2ecf20Sopenharmony_ci && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) { 5378c2ecf20Sopenharmony_ci /* function symbols on ARM have quirks, avoid them */ 5388c2ecf20Sopenharmony_ci if (w2(ehdr->e_machine) == EM_ARM 5398c2ecf20Sopenharmony_ci && ELF_ST_TYPE(symp->st_info) == STT_FUNC) 5408c2ecf20Sopenharmony_ci continue; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci *recvalp = _w(symp->st_value); 5438c2ecf20Sopenharmony_ci *sym_index = symp - sym0; 5448c2ecf20Sopenharmony_ci return 0; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci fprintf(stderr, "Cannot find symbol for section %u: %s.\n", 5488c2ecf20Sopenharmony_ci txtndx, txtname); 5498c2ecf20Sopenharmony_ci return -1; 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */ 5538c2ecf20Sopenharmony_cistatic char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */ 5548c2ecf20Sopenharmony_ci Elf_Shdr const *const shdr0, 5558c2ecf20Sopenharmony_ci char const *const shstrtab, 5568c2ecf20Sopenharmony_ci char const *const fname) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci /* .sh_info depends on .sh_type == SHT_REL[,A] */ 5598c2ecf20Sopenharmony_ci Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)]; 5608c2ecf20Sopenharmony_ci char const *const txtname = &shstrtab[w(txthdr->sh_name)]; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (strcmp("__mcount_loc", txtname) == 0) { 5638c2ecf20Sopenharmony_ci fprintf(stderr, "warning: __mcount_loc already exists: %s\n", 5648c2ecf20Sopenharmony_ci fname); 5658c2ecf20Sopenharmony_ci return already_has_rel_mcount; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci if (w(txthdr->sh_type) != SHT_PROGBITS || 5688c2ecf20Sopenharmony_ci !(_w(txthdr->sh_flags) & SHF_EXECINSTR)) 5698c2ecf20Sopenharmony_ci return NULL; 5708c2ecf20Sopenharmony_ci return txtname; 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic char const *has_rel_mcount(Elf_Shdr const *const relhdr, 5748c2ecf20Sopenharmony_ci Elf_Shdr const *const shdr0, 5758c2ecf20Sopenharmony_ci char const *const shstrtab, 5768c2ecf20Sopenharmony_ci char const *const fname) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA) 5798c2ecf20Sopenharmony_ci return NULL; 5808c2ecf20Sopenharmony_ci return __has_rel_mcount(relhdr, shdr0, shstrtab, fname); 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic unsigned tot_relsize(Elf_Shdr const *const shdr0, 5858c2ecf20Sopenharmony_ci unsigned nhdr, 5868c2ecf20Sopenharmony_ci const char *const shstrtab, 5878c2ecf20Sopenharmony_ci const char *const fname) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci unsigned totrelsz = 0; 5908c2ecf20Sopenharmony_ci Elf_Shdr const *shdrp = shdr0; 5918c2ecf20Sopenharmony_ci char const *txtname; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci for (; nhdr; --nhdr, ++shdrp) { 5948c2ecf20Sopenharmony_ci txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname); 5958c2ecf20Sopenharmony_ci if (txtname == already_has_rel_mcount) { 5968c2ecf20Sopenharmony_ci totrelsz = 0; 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci if (txtname && is_mcounted_section_name(txtname)) 6008c2ecf20Sopenharmony_ci totrelsz += _w(shdrp->sh_size); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci return totrelsz; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci/* Overall supervision for Elf32 ET_REL file. */ 6068c2ecf20Sopenharmony_cistatic int do_func(Elf_Ehdr *const ehdr, char const *const fname, 6078c2ecf20Sopenharmony_ci unsigned const reltype) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) 6108c2ecf20Sopenharmony_ci + (void *)ehdr); 6118c2ecf20Sopenharmony_ci unsigned const nhdr = get_shnum(ehdr, shdr0); 6128c2ecf20Sopenharmony_ci Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)]; 6138c2ecf20Sopenharmony_ci char const *const shstrtab = (char const *)(_w(shstr->sh_offset) 6148c2ecf20Sopenharmony_ci + (void *)ehdr); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci Elf_Shdr const *relhdr; 6178c2ecf20Sopenharmony_ci unsigned k; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci Elf32_Word *symtab; 6208c2ecf20Sopenharmony_ci Elf32_Word *symtab_shndx; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Upper bound on space: assume all relevant relocs are for mcount. */ 6238c2ecf20Sopenharmony_ci unsigned totrelsz; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci Elf_Rel * mrel0; 6268c2ecf20Sopenharmony_ci Elf_Rel * mrelp; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci uint_t * mloc0; 6298c2ecf20Sopenharmony_ci uint_t * mlocp; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci unsigned rel_entsize = 0; 6328c2ecf20Sopenharmony_ci unsigned symsec_sh_link = 0; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci int result = 0; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname); 6378c2ecf20Sopenharmony_ci if (totrelsz == 0) 6388c2ecf20Sopenharmony_ci return 0; 6398c2ecf20Sopenharmony_ci mrel0 = umalloc(totrelsz); 6408c2ecf20Sopenharmony_ci mrelp = mrel0; 6418c2ecf20Sopenharmony_ci if (!mrel0) 6428c2ecf20Sopenharmony_ci return -1; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* 2*sizeof(address) <= sizeof(Elf_Rel) */ 6458c2ecf20Sopenharmony_ci mloc0 = umalloc(totrelsz>>1); 6468c2ecf20Sopenharmony_ci mlocp = mloc0; 6478c2ecf20Sopenharmony_ci if (!mloc0) { 6488c2ecf20Sopenharmony_ci free(mrel0); 6498c2ecf20Sopenharmony_ci return -1; 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { 6558c2ecf20Sopenharmony_ci char const *const txtname = has_rel_mcount(relhdr, shdr0, 6568c2ecf20Sopenharmony_ci shstrtab, fname); 6578c2ecf20Sopenharmony_ci if (txtname == already_has_rel_mcount) { 6588c2ecf20Sopenharmony_ci result = 0; 6598c2ecf20Sopenharmony_ci file_updated = 0; 6608c2ecf20Sopenharmony_ci goto out; /* Nothing to be done; don't append! */ 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci if (txtname && is_mcounted_section_name(txtname)) { 6638c2ecf20Sopenharmony_ci unsigned int recsym; 6648c2ecf20Sopenharmony_ci uint_t recval = 0; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci symsec_sh_link = w(relhdr->sh_link); 6678c2ecf20Sopenharmony_ci result = find_secsym_ndx(w(relhdr->sh_info), txtname, 6688c2ecf20Sopenharmony_ci &recval, &recsym, 6698c2ecf20Sopenharmony_ci &shdr0[symsec_sh_link], 6708c2ecf20Sopenharmony_ci symtab, symtab_shndx, 6718c2ecf20Sopenharmony_ci ehdr); 6728c2ecf20Sopenharmony_ci if (result) 6738c2ecf20Sopenharmony_ci goto out; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci rel_entsize = _w(relhdr->sh_entsize); 6768c2ecf20Sopenharmony_ci mlocp = sift_rel_mcount(mlocp, 6778c2ecf20Sopenharmony_ci (void *)mlocp - (void *)mloc0, &mrelp, 6788c2ecf20Sopenharmony_ci relhdr, ehdr, recsym, recval, reltype); 6798c2ecf20Sopenharmony_ci } else if (txtname && (warn_on_notrace_sect || make_nop)) { 6808c2ecf20Sopenharmony_ci /* 6818c2ecf20Sopenharmony_ci * This section is ignored by ftrace, but still 6828c2ecf20Sopenharmony_ci * has mcount calls. Convert them to nops now. 6838c2ecf20Sopenharmony_ci */ 6848c2ecf20Sopenharmony_ci if (nop_mcount(relhdr, ehdr, txtname) < 0) { 6858c2ecf20Sopenharmony_ci result = -1; 6868c2ecf20Sopenharmony_ci goto out; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci if (!result && mloc0 != mlocp) 6918c2ecf20Sopenharmony_ci result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp, 6928c2ecf20Sopenharmony_ci rel_entsize, symsec_sh_link); 6938c2ecf20Sopenharmony_ciout: 6948c2ecf20Sopenharmony_ci free(mrel0); 6958c2ecf20Sopenharmony_ci free(mloc0); 6968c2ecf20Sopenharmony_ci return result; 6978c2ecf20Sopenharmony_ci} 698