Blame view
scripts/recordmcount.h
17.1 KB
4317cf95c treewide: Replace... |
1 |
/* SPDX-License-Identifier: GPL-2.0-only */ |
c28d5077f ftrace: Remove du... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * 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. |
c28d5077f ftrace: Remove du... |
19 20 |
*/ #undef append_func |
412910cd0 ftrace/MIPS: Add ... |
21 22 23 |
#undef is_fake_mcount #undef fn_is_fake_mcount #undef MIPS_is_fake_mcount |
07d8b595f ftrace/recordmcou... |
24 |
#undef mcount_adjust |
c28d5077f ftrace: Remove du... |
25 |
#undef sift_rel_mcount |
ffd618fa3 ftrace/recordmcou... |
26 |
#undef nop_mcount |
c28d5077f ftrace: Remove du... |
27 28 29 30 |
#undef find_secsym_ndx #undef __has_rel_mcount #undef has_rel_mcount #undef tot_relsize |
37762cb99 ftrace/recordmcou... |
31 |
#undef get_mcountsym |
41b402a20 ftrace/recordmcou... |
32 |
#undef get_sym_str_and_relp |
c28d5077f ftrace: Remove du... |
33 |
#undef do_func |
412910cd0 ftrace/MIPS: Add ... |
34 |
#undef Elf_Addr |
c28d5077f ftrace: Remove du... |
35 36 37 38 39 40 |
#undef Elf_Ehdr #undef Elf_Shdr #undef Elf_Rel #undef Elf_Rela #undef Elf_Sym #undef ELF_R_SYM |
a2d49358b ftrace/MIPS: Add ... |
41 |
#undef Elf_r_sym |
c28d5077f ftrace: Remove du... |
42 |
#undef ELF_R_INFO |
a2d49358b ftrace/MIPS: Add ... |
43 |
#undef Elf_r_info |
c28d5077f ftrace: Remove du... |
44 |
#undef ELF_ST_BIND |
9905ce8ad ftrace/recordmcou... |
45 |
#undef ELF_ST_TYPE |
a2d49358b ftrace/MIPS: Add ... |
46 47 |
#undef fn_ELF_R_SYM #undef fn_ELF_R_INFO |
c28d5077f ftrace: Remove du... |
48 49 50 51 52 53 54 55 |
#undef uint_t #undef _w #undef _align #undef _size #ifdef RECORD_MCOUNT_64 # define append_func append64 # define sift_rel_mcount sift64_rel_mcount |
ffd618fa3 ftrace/recordmcou... |
56 |
# define nop_mcount nop_mcount_64 |
c28d5077f ftrace: Remove du... |
57 58 59 60 |
# define find_secsym_ndx find64_secsym_ndx # define __has_rel_mcount __has64_rel_mcount # define has_rel_mcount has64_rel_mcount # define tot_relsize tot64_relsize |
41b402a20 ftrace/recordmcou... |
61 |
# define get_sym_str_and_relp get_sym_str_and_relp_64 |
c28d5077f ftrace: Remove du... |
62 |
# define do_func do64 |
37762cb99 ftrace/recordmcou... |
63 |
# define get_mcountsym get_mcountsym_64 |
412910cd0 ftrace/MIPS: Add ... |
64 65 66 |
# define is_fake_mcount is_fake_mcount64 # define fn_is_fake_mcount fn_is_fake_mcount64 # define MIPS_is_fake_mcount MIPS64_is_fake_mcount |
07d8b595f ftrace/recordmcou... |
67 |
# define mcount_adjust mcount_adjust_64 |
412910cd0 ftrace/MIPS: Add ... |
68 |
# define Elf_Addr Elf64_Addr |
c28d5077f ftrace: Remove du... |
69 70 71 72 73 74 |
# define Elf_Ehdr Elf64_Ehdr # define Elf_Shdr Elf64_Shdr # define Elf_Rel Elf64_Rel # define Elf_Rela Elf64_Rela # define Elf_Sym Elf64_Sym # define ELF_R_SYM ELF64_R_SYM |
a2d49358b ftrace/MIPS: Add ... |
75 |
# define Elf_r_sym Elf64_r_sym |
c28d5077f ftrace: Remove du... |
76 |
# define ELF_R_INFO ELF64_R_INFO |
a2d49358b ftrace/MIPS: Add ... |
77 |
# define Elf_r_info Elf64_r_info |
c28d5077f ftrace: Remove du... |
78 |
# define ELF_ST_BIND ELF64_ST_BIND |
9905ce8ad ftrace/recordmcou... |
79 |
# define ELF_ST_TYPE ELF64_ST_TYPE |
a2d49358b ftrace/MIPS: Add ... |
80 81 |
# define fn_ELF_R_SYM fn_ELF64_R_SYM # define fn_ELF_R_INFO fn_ELF64_R_INFO |
c28d5077f ftrace: Remove du... |
82 83 84 85 86 87 88 |
# define uint_t uint64_t # define _w w8 # define _align 7u # define _size 8 #else # define append_func append32 # define sift_rel_mcount sift32_rel_mcount |
ffd618fa3 ftrace/recordmcou... |
89 |
# define nop_mcount nop_mcount_32 |
c28d5077f ftrace: Remove du... |
90 91 92 93 |
# define find_secsym_ndx find32_secsym_ndx # define __has_rel_mcount __has32_rel_mcount # define has_rel_mcount has32_rel_mcount # define tot_relsize tot32_relsize |
41b402a20 ftrace/recordmcou... |
94 |
# define get_sym_str_and_relp get_sym_str_and_relp_32 |
c28d5077f ftrace: Remove du... |
95 |
# define do_func do32 |
37762cb99 ftrace/recordmcou... |
96 |
# define get_mcountsym get_mcountsym_32 |
412910cd0 ftrace/MIPS: Add ... |
97 98 99 |
# define is_fake_mcount is_fake_mcount32 # define fn_is_fake_mcount fn_is_fake_mcount32 # define MIPS_is_fake_mcount MIPS32_is_fake_mcount |
07d8b595f ftrace/recordmcou... |
100 |
# define mcount_adjust mcount_adjust_32 |
412910cd0 ftrace/MIPS: Add ... |
101 |
# define Elf_Addr Elf32_Addr |
c28d5077f ftrace: Remove du... |
102 103 104 105 106 107 |
# define Elf_Ehdr Elf32_Ehdr # define Elf_Shdr Elf32_Shdr # define Elf_Rel Elf32_Rel # define Elf_Rela Elf32_Rela # define Elf_Sym Elf32_Sym # define ELF_R_SYM ELF32_R_SYM |
a2d49358b ftrace/MIPS: Add ... |
108 |
# define Elf_r_sym Elf32_r_sym |
c28d5077f ftrace: Remove du... |
109 |
# define ELF_R_INFO ELF32_R_INFO |
a2d49358b ftrace/MIPS: Add ... |
110 |
# define Elf_r_info Elf32_r_info |
c28d5077f ftrace: Remove du... |
111 |
# define ELF_ST_BIND ELF32_ST_BIND |
9905ce8ad ftrace/recordmcou... |
112 |
# define ELF_ST_TYPE ELF32_ST_TYPE |
a2d49358b ftrace/MIPS: Add ... |
113 114 |
# define fn_ELF_R_SYM fn_ELF32_R_SYM # define fn_ELF_R_INFO fn_ELF32_R_INFO |
c28d5077f ftrace: Remove du... |
115 116 117 118 119 |
# define uint_t uint32_t # define _w w # define _align 3u # define _size 4 #endif |
412910cd0 ftrace/MIPS: Add ... |
120 121 122 123 124 125 |
/* Functions and pointers that do_file() may override for specific e_machine. */ static int fn_is_fake_mcount(Elf_Rel const *rp) { return 0; } static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount; |
a2d49358b ftrace/MIPS: Add ... |
126 127 128 129 130 131 132 133 |
static uint_t fn_ELF_R_SYM(Elf_Rel const *rp) { return ELF_R_SYM(_w(rp->r_info)); } static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type) { |
e63233f75 ftrace: Have reco... |
134 |
rp->r_info = _w(ELF_R_INFO(sym, type)); |
a2d49358b ftrace/MIPS: Add ... |
135 136 |
} static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; |
07d8b595f ftrace/recordmcou... |
137 |
static int mcount_adjust = 0; |
412910cd0 ftrace/MIPS: Add ... |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
/* * 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 static int MIPS_is_fake_mcount(Elf_Rel const *rp) { |
91ad11d7c recordmcount/MIPS... |
161 |
static Elf_Addr old_r_offset = ~(Elf_Addr)0; |
412910cd0 ftrace/MIPS: Add ... |
162 163 |
Elf_Addr current_r_offset = _w(rp->r_offset); int is_fake; |
91ad11d7c recordmcount/MIPS... |
164 |
is_fake = (old_r_offset != ~(Elf_Addr)0) && |
412910cd0 ftrace/MIPS: Add ... |
165 166 167 168 169 |
(current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET); old_r_offset = current_r_offset; return is_fake; } |
a2d49358b ftrace/MIPS: Add ... |
170 |
|
c28d5077f ftrace: Remove du... |
171 |
/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ |
3f1df1201 recordmcount: Rew... |
172 |
static int append_func(Elf_Ehdr *const ehdr, |
c28d5077f ftrace: Remove du... |
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
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) { /* Begin constructing output file */ Elf_Shdr mcsec; char const *mc_name = (sizeof(Elf_Rela) == rel_entsize) ? ".rela__mcount_loc" : ".rel__mcount_loc"; unsigned const old_shnum = w2(ehdr->e_shnum); uint_t const old_shoff = _w(ehdr->e_shoff); uint_t const old_shstr_sh_size = _w(shstr->sh_size); uint_t const old_shstr_sh_offset = _w(shstr->sh_offset); uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size); uint_t new_e_shoff; shstr->sh_size = _w(t); shstr->sh_offset = _w(sb.st_size); t += sb.st_size; t += (_align & -t); /* word-byte align */ new_e_shoff = t; /* body for new shstrtab */ |
3f1df1201 recordmcount: Rew... |
200 201 202 203 204 205 |
if (ulseek(sb.st_size, SEEK_SET) < 0) return -1; if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0) return -1; if (uwrite(mc_name, 1 + strlen(mc_name)) < 0) return -1; |
c28d5077f ftrace: Remove du... |
206 207 |
/* old(modified) Elf_Shdr table, word-byte aligned */ |
3f1df1201 recordmcount: Rew... |
208 209 |
if (ulseek(t, SEEK_SET) < 0) return -1; |
c28d5077f ftrace: Remove du... |
210 |
t += sizeof(Elf_Shdr) * old_shnum; |
3f1df1201 recordmcount: Rew... |
211 212 213 |
if (uwrite(old_shoff + (void *)ehdr, sizeof(Elf_Shdr) * old_shnum) < 0) return -1; |
c28d5077f ftrace: Remove du... |
214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
/* new sections __mcount_loc and .rel__mcount_loc */ t += 2*sizeof(mcsec); mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel") + old_shstr_sh_size); mcsec.sh_type = w(SHT_PROGBITS); mcsec.sh_flags = _w(SHF_ALLOC); mcsec.sh_addr = 0; mcsec.sh_offset = _w(t); mcsec.sh_size = _w((void *)mlocp - (void *)mloc0); mcsec.sh_link = 0; mcsec.sh_info = 0; mcsec.sh_addralign = _w(_size); mcsec.sh_entsize = _w(_size); |
3f1df1201 recordmcount: Rew... |
228 229 |
if (uwrite(&mcsec, sizeof(mcsec)) < 0) return -1; |
c28d5077f ftrace: Remove du... |
230 231 232 233 234 235 236 237 238 239 240 241 242 |
mcsec.sh_name = w(old_shstr_sh_size); mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize) ? w(SHT_RELA) : w(SHT_REL); mcsec.sh_flags = 0; mcsec.sh_addr = 0; mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t); mcsec.sh_size = _w((void *)mrelp - (void *)mrel0); mcsec.sh_link = w(symsec_sh_link); mcsec.sh_info = w(old_shnum); mcsec.sh_addralign = _w(_size); mcsec.sh_entsize = _w(rel_entsize); |
c28d5077f ftrace: Remove du... |
243 |
|
3f1df1201 recordmcount: Rew... |
244 245 246 247 248 249 250 |
if (uwrite(&mcsec, sizeof(mcsec)) < 0) return -1; if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0) return -1; if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0) return -1; |
c28d5077f ftrace: Remove du... |
251 252 253 |
ehdr->e_shoff = _w(new_e_shoff); ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */ |
3f1df1201 recordmcount: Rew... |
254 255 256 257 258 |
if (ulseek(0, SEEK_SET) < 0) return -1; if (uwrite(ehdr, sizeof(*ehdr)) < 0) return -1; return 0; |
c28d5077f ftrace: Remove du... |
259 |
} |
37762cb99 ftrace/recordmcou... |
260 261 262 263 264 265 266 267 268 269 |
static unsigned get_mcountsym(Elf_Sym const *const sym0, Elf_Rel const *relp, char const *const str0) { unsigned mcountsym = 0; Elf_Sym const *const symp = &sym0[Elf_r_sym(relp)]; char const *symname = &str0[w(symp->st_name)]; char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; |
48bb5dc6c ftrace: Make reco... |
270 |
char const *fentry = "__fentry__"; |
37762cb99 ftrace/recordmcou... |
271 272 273 274 |
if (symname[0] == '.') ++symname; /* ppc64 hack */ if (strcmp(mcount, symname) == 0 || |
48bb5dc6c ftrace: Make reco... |
275 276 |
(altmcount && strcmp(altmcount, symname) == 0) || (strcmp(fentry, symname) == 0)) |
37762cb99 ftrace/recordmcou... |
277 278 279 280 |
mcountsym = Elf_r_sym(relp); return mcountsym; } |
41b402a20 ftrace/recordmcou... |
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
static void 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) { Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) + (void *)ehdr); unsigned const symsec_sh_link = w(relhdr->sh_link); Elf_Shdr const *const symsec = &shdr0[symsec_sh_link]; Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)]; Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset) + (void *)ehdr); *sym0 = (Elf_Sym const *)(_w(symsec->sh_offset) + (void *)ehdr); *str0 = (char const *)(_w(strsec->sh_offset) + (void *)ehdr); *relp = rel0; } |
c28d5077f ftrace: Remove du... |
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
/* * Look at the relocations in order to find the calls to mcount. * Accumulate the section offsets that are found, and their relocation info, * onto the end of the existing arrays. */ static uint_t *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) { uint_t *const mloc0 = mlocp; Elf_Rel *mrelp = *mrelpp; |
41b402a20 ftrace/recordmcou... |
319 320 321 |
Elf_Sym const *sym0; char const *str0; Elf_Rel const *relp; |
c28d5077f ftrace: Remove du... |
322 323 |
unsigned rel_entsize = _w(relhdr->sh_entsize); unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; |
c28d5077f ftrace: Remove du... |
324 325 |
unsigned mcountsym = 0; unsigned t; |
41b402a20 ftrace/recordmcou... |
326 |
get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); |
c28d5077f ftrace: Remove du... |
327 |
for (t = nrel; t; --t) { |
37762cb99 ftrace/recordmcou... |
328 329 |
if (!mcountsym) mcountsym = get_mcountsym(sym0, relp, str0); |
c28d5077f ftrace: Remove du... |
330 |
|
80e5302e4 recordmcount: Fix... |
331 332 |
if (mcountsym && mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { |
07d8b595f ftrace/recordmcou... |
333 334 |
uint_t const addend = _w(_w(relp->r_offset) - recval + mcount_adjust); |
c28d5077f ftrace: Remove du... |
335 336 |
mrelp->r_offset = _w(offbase + ((void *)mlocp - (void *)mloc0)); |
a2d49358b ftrace/MIPS: Add ... |
337 |
Elf_r_info(mrelp, recsym, reltype); |
dd5477ff3 ftrace/trivial: C... |
338 |
if (rel_entsize == sizeof(Elf_Rela)) { |
c28d5077f ftrace: Remove du... |
339 340 341 342 343 344 345 346 347 348 349 350 |
((Elf_Rela *)mrelp)->r_addend = addend; *mlocp++ = 0; } else *mlocp++ = addend; mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp); } relp = (Elf_Rel const *)(rel_entsize + (void *)relp); } *mrelpp = mrelp; return mlocp; } |
ffd618fa3 ftrace/recordmcou... |
351 352 353 354 355 |
/* * 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. */ |
3f1df1201 recordmcount: Rew... |
356 357 358 |
static int nop_mcount(Elf_Shdr const *const relhdr, Elf_Ehdr const *const ehdr, const char *const txtname) |
ffd618fa3 ftrace/recordmcou... |
359 360 361 |
{ Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) + (void *)ehdr); |
41b402a20 ftrace/recordmcou... |
362 363 364 365 |
Elf_Sym const *sym0; char const *str0; Elf_Rel const *relp; Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)]; |
ffd618fa3 ftrace/recordmcou... |
366 367 |
unsigned rel_entsize = _w(relhdr->sh_entsize); unsigned const nrel = _w(relhdr->sh_size) / rel_entsize; |
ffd618fa3 ftrace/recordmcou... |
368 369 |
unsigned mcountsym = 0; unsigned t; |
dfad3d598 ftrace/recordmcou... |
370 |
int once = 0; |
ffd618fa3 ftrace/recordmcou... |
371 |
|
41b402a20 ftrace/recordmcou... |
372 |
get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp); |
ffd618fa3 ftrace/recordmcou... |
373 374 |
for (t = nrel; t; --t) { int ret = -1; |
37762cb99 ftrace/recordmcou... |
375 376 |
if (!mcountsym) mcountsym = get_mcountsym(sym0, relp, str0); |
ffd618fa3 ftrace/recordmcou... |
377 |
|
dfad3d598 ftrace/recordmcou... |
378 |
if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { |
7f8557b88 recordmcount: Fix... |
379 |
if (make_nop) |
c84da8b9a recordmcount: Fix... |
380 |
ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset)); |
dfad3d598 ftrace/recordmcou... |
381 382 383 384 385 386 387 |
if (warn_on_notrace_sect && !once) { printf("Section %s has mcount callers being ignored ", txtname); once = 1; /* just warn? */ if (!make_nop) |
3f1df1201 recordmcount: Rew... |
388 |
return 0; |
dfad3d598 ftrace/recordmcou... |
389 390 |
} } |
ffd618fa3 ftrace/recordmcou... |
391 392 393 394 395 396 397 398 399 |
/* * 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); |
3f1df1201 recordmcount: Rew... |
400 401 402 403 |
if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0) return -1; if (uwrite(&rel, sizeof(rel)) < 0) return -1; |
ffd618fa3 ftrace/recordmcou... |
404 405 406 |
} relp = (Elf_Rel const *)(rel_entsize + (void *)relp); } |
3f1df1201 recordmcount: Rew... |
407 |
return 0; |
ffd618fa3 ftrace/recordmcou... |
408 |
} |
c28d5077f ftrace: Remove du... |
409 410 411 412 413 414 415 416 417 418 |
/* * 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 */ |
3f1df1201 recordmcount: Rew... |
419 |
static int find_secsym_ndx(unsigned const txtndx, |
c28d5077f ftrace: Remove du... |
420 421 |
char const *const txtname, uint_t *const recvalp, |
3f1df1201 recordmcount: Rew... |
422 |
unsigned int *sym_index, |
c28d5077f ftrace: Remove du... |
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
Elf_Shdr const *const symhdr, Elf_Ehdr const *const ehdr) { Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset) + (void *)ehdr); unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize); Elf_Sym const *symp; unsigned t; for (symp = sym0, t = nsym; t; --t, ++symp) { unsigned int const st_bind = ELF_ST_BIND(symp->st_info); if (txtndx == w2(symp->st_shndx) /* avoid STB_WEAK */ && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) { |
9905ce8ad ftrace/recordmcou... |
438 439 440 441 |
/* function symbols on ARM have quirks, avoid them */ if (w2(ehdr->e_machine) == EM_ARM && ELF_ST_TYPE(symp->st_info) == STT_FUNC) continue; |
c28d5077f ftrace: Remove du... |
442 |
*recvalp = _w(symp->st_value); |
3f1df1201 recordmcount: Rew... |
443 444 |
*sym_index = symp - sym0; return 0; |
c28d5077f ftrace: Remove du... |
445 446 |
} } |
ac5db1fc8 scripts: Fixed pr... |
447 448 |
fprintf(stderr, "Cannot find symbol for section %u: %s. ", |
c28d5077f ftrace: Remove du... |
449 |
txtndx, txtname); |
3f1df1201 recordmcount: Rew... |
450 |
return -1; |
c28d5077f ftrace: Remove du... |
451 |
} |
c28d5077f ftrace: Remove du... |
452 |
/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */ |
3aec86382 recordmcount: Ker... |
453 454 455 456 |
static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */ Elf_Shdr const *const shdr0, char const *const shstrtab, char const *const fname) |
c28d5077f ftrace: Remove du... |
457 458 459 460 |
{ /* .sh_info depends on .sh_type == SHT_REL[,A] */ Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)]; char const *const txtname = &shstrtab[w(txthdr->sh_name)]; |
dd5477ff3 ftrace/trivial: C... |
461 |
if (strcmp("__mcount_loc", txtname) == 0) { |
c28d5077f ftrace: Remove du... |
462 463 464 |
fprintf(stderr, "warning: __mcount_loc already exists: %s ", fname); |
3f1df1201 recordmcount: Rew... |
465 |
return already_has_rel_mcount; |
c28d5077f ftrace: Remove du... |
466 |
} |
dd5477ff3 ftrace/trivial: C... |
467 |
if (w(txthdr->sh_type) != SHT_PROGBITS || |
2e885057b recordmcount: Fix... |
468 |
!(_w(txthdr->sh_flags) & SHF_EXECINSTR)) |
c28d5077f ftrace: Remove du... |
469 470 471 472 473 474 475 476 477 |
return NULL; return txtname; } static char const *has_rel_mcount(Elf_Shdr const *const relhdr, Elf_Shdr const *const shdr0, char const *const shstrtab, char const *const fname) { |
dd5477ff3 ftrace/trivial: C... |
478 |
if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA) |
c28d5077f ftrace: Remove du... |
479 480 481 482 483 484 485 486 487 488 489 490 |
return NULL; return __has_rel_mcount(relhdr, shdr0, shstrtab, fname); } static unsigned tot_relsize(Elf_Shdr const *const shdr0, unsigned nhdr, const char *const shstrtab, const char *const fname) { unsigned totrelsz = 0; Elf_Shdr const *shdrp = shdr0; |
ffd618fa3 ftrace/recordmcou... |
491 |
char const *txtname; |
c28d5077f ftrace: Remove du... |
492 493 |
for (; nhdr; --nhdr, ++shdrp) { |
ffd618fa3 ftrace/recordmcou... |
494 |
txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname); |
3f1df1201 recordmcount: Rew... |
495 496 497 498 |
if (txtname == already_has_rel_mcount) { totrelsz = 0; break; } |
ffd618fa3 ftrace/recordmcou... |
499 |
if (txtname && is_mcounted_section_name(txtname)) |
c28d5077f ftrace: Remove du... |
500 501 502 503 504 505 506 |
totrelsz += _w(shdrp->sh_size); } return totrelsz; } /* Overall supervision for Elf32 ET_REL file. */ |
3aec86382 recordmcount: Ker... |
507 508 |
static int do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype) |
c28d5077f ftrace: Remove du... |
509 510 511 512 513 514 515 516 517 518 519 520 |
{ Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) + (void *)ehdr); unsigned const nhdr = w2(ehdr->e_shnum); Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)]; char const *const shstrtab = (char const *)(_w(shstr->sh_offset) + (void *)ehdr); Elf_Shdr const *relhdr; unsigned k; /* Upper bound on space: assume all relevant relocs are for mcount. */ |
3f1df1201 recordmcount: Rew... |
521 |
unsigned totrelsz; |
c28d5077f ftrace: Remove du... |
522 |
|
3f1df1201 recordmcount: Rew... |
523 524 525 526 527 |
Elf_Rel * mrel0; Elf_Rel * mrelp; uint_t * mloc0; uint_t * mlocp; |
c28d5077f ftrace: Remove du... |
528 529 530 |
unsigned rel_entsize = 0; unsigned symsec_sh_link = 0; |
3f1df1201 recordmcount: Rew... |
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
int result = 0; totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname); if (totrelsz == 0) return 0; mrel0 = umalloc(totrelsz); mrelp = mrel0; if (!mrel0) return -1; /* 2*sizeof(address) <= sizeof(Elf_Rel) */ mloc0 = umalloc(totrelsz>>1); mlocp = mloc0; if (!mloc0) { free(mrel0); return -1; } |
c28d5077f ftrace: Remove du... |
548 549 550 |
for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { char const *const txtname = has_rel_mcount(relhdr, shdr0, shstrtab, fname); |
3f1df1201 recordmcount: Rew... |
551 552 553 554 555 |
if (txtname == already_has_rel_mcount) { result = 0; file_updated = 0; goto out; /* Nothing to be done; don't append! */ } |
ffd618fa3 ftrace/recordmcou... |
556 |
if (txtname && is_mcounted_section_name(txtname)) { |
3f1df1201 recordmcount: Rew... |
557 |
unsigned int recsym; |
c28d5077f ftrace: Remove du... |
558 |
uint_t recval = 0; |
3f1df1201 recordmcount: Rew... |
559 560 561 562 563 564 565 566 |
symsec_sh_link = w(relhdr->sh_link); result = find_secsym_ndx(w(relhdr->sh_info), txtname, &recval, &recsym, &shdr0[symsec_sh_link], ehdr); if (result) goto out; |
c28d5077f ftrace: Remove du... |
567 568 569 570 571 |
rel_entsize = _w(relhdr->sh_entsize); mlocp = sift_rel_mcount(mlocp, (void *)mlocp - (void *)mloc0, &mrelp, relhdr, ehdr, recsym, recval, reltype); |
dfad3d598 ftrace/recordmcou... |
572 |
} else if (txtname && (warn_on_notrace_sect || make_nop)) { |
ffd618fa3 ftrace/recordmcou... |
573 574 575 576 |
/* * This section is ignored by ftrace, but still * has mcount calls. Convert them to nops now. */ |
3f1df1201 recordmcount: Rew... |
577 578 579 580 |
if (nop_mcount(relhdr, ehdr, txtname) < 0) { result = -1; goto out; } |
c28d5077f ftrace: Remove du... |
581 582 |
} } |
3f1df1201 recordmcount: Rew... |
583 584 585 586 |
if (!result && mloc0 != mlocp) result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp, rel_entsize, symsec_sh_link); out: |
c28d5077f ftrace: Remove du... |
587 588 |
free(mrel0); free(mloc0); |
3f1df1201 recordmcount: Rew... |
589 |
return result; |
c28d5077f ftrace: Remove du... |
590 |
} |