aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/recordmcount.c5
-rw-r--r--scripts/recordmcount.h56
2 files changed, 57 insertions, 4 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 2d32b9ced20a..f2f32eee2c5b 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -325,8 +325,10 @@ do_file(char const *const fname)
325 } 325 }
326 if (EM_S390 == w2(ehdr->e_machine)) 326 if (EM_S390 == w2(ehdr->e_machine))
327 reltype = R_390_32; 327 reltype = R_390_32;
328 if (EM_MIPS == w2(ehdr->e_machine)) 328 if (EM_MIPS == w2(ehdr->e_machine)) {
329 reltype = R_MIPS_32; 329 reltype = R_MIPS_32;
330 is_fake_mcount32 = MIPS32_is_fake_mcount;
331 }
330 do32(ehdr, fname, reltype); 332 do32(ehdr, fname, reltype);
331 } break; 333 } break;
332 case ELFCLASS64: { 334 case ELFCLASS64: {
@@ -343,6 +345,7 @@ do_file(char const *const fname)
343 reltype = R_MIPS_64; 345 reltype = R_MIPS_64;
344 Elf64_r_sym = MIPS64_r_sym; 346 Elf64_r_sym = MIPS64_r_sym;
345 Elf64_r_info = MIPS64_r_info; 347 Elf64_r_info = MIPS64_r_info;
348 is_fake_mcount64 = MIPS64_is_fake_mcount;
346 } 349 }
347 do64(ghdr, fname, reltype); 350 do64(ghdr, fname, reltype);
348 } break; 351 } break;
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 190fd18dc853..58e933a20544 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -19,12 +19,16 @@
19 * Licensed under the GNU General Public License, version 2 (GPLv2). 19 * Licensed under the GNU General Public License, version 2 (GPLv2).
20 */ 20 */
21#undef append_func 21#undef append_func
22#undef is_fake_mcount
23#undef fn_is_fake_mcount
24#undef MIPS_is_fake_mcount
22#undef sift_rel_mcount 25#undef sift_rel_mcount
23#undef find_secsym_ndx 26#undef find_secsym_ndx
24#undef __has_rel_mcount 27#undef __has_rel_mcount
25#undef has_rel_mcount 28#undef has_rel_mcount
26#undef tot_relsize 29#undef tot_relsize
27#undef do_func 30#undef do_func
31#undef Elf_Addr
28#undef Elf_Ehdr 32#undef Elf_Ehdr
29#undef Elf_Shdr 33#undef Elf_Shdr
30#undef Elf_Rel 34#undef Elf_Rel
@@ -50,6 +54,10 @@
50# define has_rel_mcount has64_rel_mcount 54# define has_rel_mcount has64_rel_mcount
51# define tot_relsize tot64_relsize 55# define tot_relsize tot64_relsize
52# define do_func do64 56# define do_func do64
57# define is_fake_mcount is_fake_mcount64
58# define fn_is_fake_mcount fn_is_fake_mcount64
59# define MIPS_is_fake_mcount MIPS64_is_fake_mcount
60# define Elf_Addr Elf64_Addr
53# define Elf_Ehdr Elf64_Ehdr 61# define Elf_Ehdr Elf64_Ehdr
54# define Elf_Shdr Elf64_Shdr 62# define Elf_Shdr Elf64_Shdr
55# define Elf_Rel Elf64_Rel 63# define Elf_Rel Elf64_Rel
@@ -74,6 +82,10 @@
74# define has_rel_mcount has32_rel_mcount 82# define has_rel_mcount has32_rel_mcount
75# define tot_relsize tot32_relsize 83# define tot_relsize tot32_relsize
76# define do_func do32 84# define do_func do32
85# define is_fake_mcount is_fake_mcount32
86# define fn_is_fake_mcount fn_is_fake_mcount32
87# define MIPS_is_fake_mcount MIPS32_is_fake_mcount
88# define Elf_Addr Elf32_Addr
77# define Elf_Ehdr Elf32_Ehdr 89# define Elf_Ehdr Elf32_Ehdr
78# define Elf_Shdr Elf32_Shdr 90# define Elf_Shdr Elf32_Shdr
79# define Elf_Rel Elf32_Rel 91# define Elf_Rel Elf32_Rel
@@ -92,7 +104,13 @@
92# define _size 4 104# define _size 4
93#endif 105#endif
94 106
95/* Functions and pointers that 64-bit EM_MIPS can override. */ 107/* Functions and pointers that do_file() may override for specific e_machine. */
108static int fn_is_fake_mcount(Elf_Rel const *rp)
109{
110 return 0;
111}
112static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount;
113
96static uint_t fn_ELF_R_SYM(Elf_Rel const *rp) 114static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
97{ 115{
98 return ELF_R_SYM(_w(rp->r_info)); 116 return ELF_R_SYM(_w(rp->r_info));
@@ -105,6 +123,39 @@ static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
105} 123}
106static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; 124static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
107 125
126/*
127 * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
128 * _mcount symbol is needed for dynamic function tracer, with it, to disable
129 * tracing(ftrace_make_nop), the instruction in the position is replaced with
130 * the "b label" instruction, to enable tracing(ftrace_make_call), replace the
131 * instruction back. So, here, we set the 2nd one as fake and filter it.
132 *
133 * c: 3c030000 lui v1,0x0 <--> b label
134 * c: R_MIPS_HI16 _mcount
135 * c: R_MIPS_NONE *ABS*
136 * c: R_MIPS_NONE *ABS*
137 * 10: 64630000 daddiu v1,v1,0
138 * 10: R_MIPS_LO16 _mcount
139 * 10: R_MIPS_NONE *ABS*
140 * 10: R_MIPS_NONE *ABS*
141 * 14: 03e0082d move at,ra
142 * 18: 0060f809 jalr v1
143 * label:
144 */
145#define MIPS_FAKEMCOUNT_OFFSET 4
146
147static int MIPS_is_fake_mcount(Elf_Rel const *rp)
148{
149 static Elf_Addr old_r_offset;
150 Elf_Addr current_r_offset = _w(rp->r_offset);
151 int is_fake;
152
153 is_fake = old_r_offset &&
154 (current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
155 old_r_offset = current_r_offset;
156
157 return is_fake;
158}
108 159
109/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ 160/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
110static void append_func(Elf_Ehdr *const ehdr, 161static void append_func(Elf_Ehdr *const ehdr,
@@ -183,7 +234,6 @@ static void append_func(Elf_Ehdr *const ehdr,
183 uwrite(fd_map, ehdr, sizeof(*ehdr)); 234 uwrite(fd_map, ehdr, sizeof(*ehdr));
184} 235}
185 236
186
187/* 237/*
188 * Look at the relocations in order to find the calls to mcount. 238 * Look at the relocations in order to find the calls to mcount.
189 * Accumulate the section offsets that are found, and their relocation info, 239 * Accumulate the section offsets that are found, and their relocation info,
@@ -233,7 +283,7 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
233 mcountsym = Elf_r_sym(relp); 283 mcountsym = Elf_r_sym(relp);
234 } 284 }
235 285
236 if (mcountsym == Elf_r_sym(relp)) { 286 if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
237 uint_t const addend = _w(_w(relp->r_offset) - recval); 287 uint_t const addend = _w(_w(relp->r_offset) - recval);
238 288
239 mrelp->r_offset = _w(offbase 289 mrelp->r_offset = _w(offbase