diff options
-rw-r--r-- | scripts/recordmcount.c | 5 | ||||
-rw-r--r-- | scripts/recordmcount.h | 56 |
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. */ |
108 | static int fn_is_fake_mcount(Elf_Rel const *rp) | ||
109 | { | ||
110 | return 0; | ||
111 | } | ||
112 | static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount; | ||
113 | |||
96 | static uint_t fn_ELF_R_SYM(Elf_Rel const *rp) | 114 | static 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 | } |
106 | static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; | 124 | static 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 | |||
147 | static 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. */ |
110 | static void append_func(Elf_Ehdr *const ehdr, | 161 | static 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 |