/* SPDX-License-Identifier: GPL-2.0-only */ /* * recordmcount.h * * This code was taken out of recordmcount.c written by * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. * * The original code had the same algorithms for both 32bit * and 64bit ELF files, but the code was duplicated to support * the difference in structures that were used. This * file creates a macro of everything that is different between * the 64 and 32 bit code, such that by including this header * twice we can create both sets of functions by including this * header once with RECORD_MCOUNT_64 undefined, and again with * it defined. * * This conversion to macros was done by: * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
*/ #undef append_func #undef is_fake_mcount #undef fn_is_fake_mcount #undef MIPS_is_fake_mcount #undef mcount_adjust #undef sift_rel_mcount #undef nop_mcount #undef find_secsym_ndx #undef __has_rel_mcount #undef has_rel_mcount #undef tot_relsize #undef get_mcountsym #undef find_symtab #undef get_shnum #undef set_shnum #undef get_shstrndx #undef get_symindex #undef get_sym_str_and_relp #undef do_func #undef Elf_Addr #undef Elf_Ehdr #undef Elf_Shdr #undef Elf_Rel #undef Elf_Rela #undef Elf_Sym #undef ELF_R_SYM #undef Elf_r_sym #undef ELF_R_INFO #undef Elf_r_info #undef ELF_ST_BIND #undef ELF_ST_TYPE #undef fn_ELF_R_SYM #undef fn_ELF_R_INFO #undef uint_t #undef _w #undef _align #undef _size
/* * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st * _mcount symbol is needed for dynamic function tracer, with it, to disable * tracing(ftrace_make_nop), the instruction in the position is replaced with * the "b label" instruction, to enable tracing(ftrace_make_call), replace the * instruction back. So, here, we set the 2nd one as fake and filter it. * * c: 3c030000 lui v1,0x0 <--> b label * c: R_MIPS_HI16 _mcount * c: R_MIPS_NONE *ABS* * c: R_MIPS_NONE *ABS* * 10: 64630000 daddiu v1,v1,0 * 10: R_MIPS_LO16 _mcount * 10: R_MIPS_NONE *ABS* * 10: R_MIPS_NONE *ABS* * 14: 03e0082d move at,ra * 18: 0060f809 jalr v1 * label:
*/ #define MIPS_FAKEMCOUNT_OFFSET 4
/* * Read the relocation table again, but this time its called on sections * that are not going to be traced. The mcount calls here will be converted * into nops.
*/ staticint nop_mcount(Elf_Shdr const *const relhdr,
Elf_Ehdr const *const ehdr, constchar *const txtname)
{
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+ (void *)ehdr);
Elf_Sym const *sym0; charconst *str0;
Elf_Rel const *relp;
Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)]; unsigned rel_entsize = _w(relhdr->sh_entsize); unsignedconst nrel = _w(relhdr->sh_size) / rel_entsize; unsigned mcountsym = 0; unsigned t; int once = 0;
if (!mcountsym)
mcountsym = get_mcountsym(sym0, relp, str0);
if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { if (make_nop)
ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset)); if (warn_on_notrace_sect && !once) {
printf("Section %s has mcount callers being ignored\n",
txtname);
once = 1; /* just warn? */ if (!make_nop) return 0;
}
}
/* * If we successfully removed the mcount, mark the relocation * as a nop (don't do anything with it).
*/ if (!ret) {
Elf_Rel rel;
rel = *(Elf_Rel *)relp;
Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop); if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0) return -1; if (uwrite(&rel, sizeof(rel)) < 0) return -1;
}
relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
} return 0;
}
/* * Find a symbol in the given section, to be used as the base for relocating * the table of offsets of calls to mcount. A local or global symbol suffices, * but avoid a Weak symbol because it may be overridden; the change in value * would invalidate the relocations of the offsets of the calls to mcount. * Often the found symbol will be the unnamed local symbol generated by * GNU 'as' for the start of each section. For example: * Num: Value Size Type Bind Vis Ndx Name * 2: 00000000 0 SECTION LOCAL DEFAULT 1
*/ staticint find_secsym_ndx(unsignedconst txtndx, charconst *const txtname,
uint_t *const recvalp, unsignedint *sym_index,
Elf_Shdr const *const symhdr,
Elf32_Word const *symtab,
Elf32_Word const *symtab_shndx,
Elf_Ehdr const *const ehdr)
{
Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
+ (void *)ehdr); unsignedconst nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
Elf_Sym const *symp; unsigned t;
for (symp = sym0, t = nsym; t; --t, ++symp) { unsignedintconst st_bind = ELF_ST_BIND(symp->st_info);
if (txtndx == get_symindex(symp, symtab, symtab_shndx) /* avoid STB_WEAK */
&& (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) { /* function symbols on ARM have quirks, avoid them */ if (w2(ehdr->e_machine) == EM_ARM
&& ELF_ST_TYPE(symp->st_info) == STT_FUNC) continue;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.