diff options
Diffstat (limited to 'scripts/recordmcount.h')
-rw-r--r-- | scripts/recordmcount.h | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 7f39d0943d2d..58e933a20544 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h | |||
@@ -19,20 +19,28 @@ | |||
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 |
31 | #undef Elf_Rela | 35 | #undef Elf_Rela |
32 | #undef Elf_Sym | 36 | #undef Elf_Sym |
33 | #undef ELF_R_SYM | 37 | #undef ELF_R_SYM |
38 | #undef Elf_r_sym | ||
34 | #undef ELF_R_INFO | 39 | #undef ELF_R_INFO |
40 | #undef Elf_r_info | ||
35 | #undef ELF_ST_BIND | 41 | #undef ELF_ST_BIND |
42 | #undef fn_ELF_R_SYM | ||
43 | #undef fn_ELF_R_INFO | ||
36 | #undef uint_t | 44 | #undef uint_t |
37 | #undef _w | 45 | #undef _w |
38 | #undef _align | 46 | #undef _align |
@@ -46,14 +54,22 @@ | |||
46 | # define has_rel_mcount has64_rel_mcount | 54 | # define has_rel_mcount has64_rel_mcount |
47 | # define tot_relsize tot64_relsize | 55 | # define tot_relsize tot64_relsize |
48 | # 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 | ||
49 | # define Elf_Ehdr Elf64_Ehdr | 61 | # define Elf_Ehdr Elf64_Ehdr |
50 | # define Elf_Shdr Elf64_Shdr | 62 | # define Elf_Shdr Elf64_Shdr |
51 | # define Elf_Rel Elf64_Rel | 63 | # define Elf_Rel Elf64_Rel |
52 | # define Elf_Rela Elf64_Rela | 64 | # define Elf_Rela Elf64_Rela |
53 | # define Elf_Sym Elf64_Sym | 65 | # define Elf_Sym Elf64_Sym |
54 | # define ELF_R_SYM ELF64_R_SYM | 66 | # define ELF_R_SYM ELF64_R_SYM |
67 | # define Elf_r_sym Elf64_r_sym | ||
55 | # define ELF_R_INFO ELF64_R_INFO | 68 | # define ELF_R_INFO ELF64_R_INFO |
69 | # define Elf_r_info Elf64_r_info | ||
56 | # define ELF_ST_BIND ELF64_ST_BIND | 70 | # define ELF_ST_BIND ELF64_ST_BIND |
71 | # define fn_ELF_R_SYM fn_ELF64_R_SYM | ||
72 | # define fn_ELF_R_INFO fn_ELF64_R_INFO | ||
57 | # define uint_t uint64_t | 73 | # define uint_t uint64_t |
58 | # define _w w8 | 74 | # define _w w8 |
59 | # define _align 7u | 75 | # define _align 7u |
@@ -66,20 +82,81 @@ | |||
66 | # define has_rel_mcount has32_rel_mcount | 82 | # define has_rel_mcount has32_rel_mcount |
67 | # define tot_relsize tot32_relsize | 83 | # define tot_relsize tot32_relsize |
68 | # 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 | ||
69 | # define Elf_Ehdr Elf32_Ehdr | 89 | # define Elf_Ehdr Elf32_Ehdr |
70 | # define Elf_Shdr Elf32_Shdr | 90 | # define Elf_Shdr Elf32_Shdr |
71 | # define Elf_Rel Elf32_Rel | 91 | # define Elf_Rel Elf32_Rel |
72 | # define Elf_Rela Elf32_Rela | 92 | # define Elf_Rela Elf32_Rela |
73 | # define Elf_Sym Elf32_Sym | 93 | # define Elf_Sym Elf32_Sym |
74 | # define ELF_R_SYM ELF32_R_SYM | 94 | # define ELF_R_SYM ELF32_R_SYM |
95 | # define Elf_r_sym Elf32_r_sym | ||
75 | # define ELF_R_INFO ELF32_R_INFO | 96 | # define ELF_R_INFO ELF32_R_INFO |
97 | # define Elf_r_info Elf32_r_info | ||
76 | # define ELF_ST_BIND ELF32_ST_BIND | 98 | # define ELF_ST_BIND ELF32_ST_BIND |
99 | # define fn_ELF_R_SYM fn_ELF32_R_SYM | ||
100 | # define fn_ELF_R_INFO fn_ELF32_R_INFO | ||
77 | # define uint_t uint32_t | 101 | # define uint_t uint32_t |
78 | # define _w w | 102 | # define _w w |
79 | # define _align 3u | 103 | # define _align 3u |
80 | # define _size 4 | 104 | # define _size 4 |
81 | #endif | 105 | #endif |
82 | 106 | ||
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 | |||
114 | static uint_t fn_ELF_R_SYM(Elf_Rel const *rp) | ||
115 | { | ||
116 | return ELF_R_SYM(_w(rp->r_info)); | ||
117 | } | ||
118 | static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; | ||
119 | |||
120 | static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type) | ||
121 | { | ||
122 | rp->r_info = ELF_R_INFO(sym, type); | ||
123 | } | ||
124 | static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; | ||
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 | } | ||
159 | |||
83 | /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ | 160 | /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ |
84 | static void append_func(Elf_Ehdr *const ehdr, | 161 | static void append_func(Elf_Ehdr *const ehdr, |
85 | Elf_Shdr *const shstr, | 162 | Elf_Shdr *const shstr, |
@@ -157,7 +234,6 @@ static void append_func(Elf_Ehdr *const ehdr, | |||
157 | uwrite(fd_map, ehdr, sizeof(*ehdr)); | 234 | uwrite(fd_map, ehdr, sizeof(*ehdr)); |
158 | } | 235 | } |
159 | 236 | ||
160 | |||
161 | /* | 237 | /* |
162 | * 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. |
163 | * Accumulate the section offsets that are found, and their relocation info, | 239 | * Accumulate the section offsets that are found, and their relocation info, |
@@ -197,22 +273,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp, | |||
197 | for (t = nrel; t; --t) { | 273 | for (t = nrel; t; --t) { |
198 | if (!mcountsym) { | 274 | if (!mcountsym) { |
199 | Elf_Sym const *const symp = | 275 | Elf_Sym const *const symp = |
200 | &sym0[ELF_R_SYM(_w(relp->r_info))]; | 276 | &sym0[Elf_r_sym(relp)]; |
201 | char const *symname = &str0[w(symp->st_name)]; | 277 | char const *symname = &str0[w(symp->st_name)]; |
202 | 278 | ||
203 | if ('.' == symname[0]) | 279 | if ('.' == symname[0]) |
204 | ++symname; /* ppc64 hack */ | 280 | ++symname; /* ppc64 hack */ |
205 | if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"), | 281 | if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"), |
206 | symname)) | 282 | symname)) |
207 | mcountsym = ELF_R_SYM(_w(relp->r_info)); | 283 | mcountsym = Elf_r_sym(relp); |
208 | } | 284 | } |
209 | 285 | ||
210 | if (mcountsym == ELF_R_SYM(_w(relp->r_info))) { | 286 | if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) { |
211 | uint_t const addend = _w(_w(relp->r_offset) - recval); | 287 | uint_t const addend = _w(_w(relp->r_offset) - recval); |
212 | 288 | ||
213 | mrelp->r_offset = _w(offbase | 289 | mrelp->r_offset = _w(offbase |
214 | + ((void *)mlocp - (void *)mloc0)); | 290 | + ((void *)mlocp - (void *)mloc0)); |
215 | mrelp->r_info = _w(ELF_R_INFO(recsym, reltype)); | 291 | Elf_r_info(mrelp, recsym, reltype); |
216 | if (sizeof(Elf_Rela) == rel_entsize) { | 292 | if (sizeof(Elf_Rela) == rel_entsize) { |
217 | ((Elf_Rela *)mrelp)->r_addend = addend; | 293 | ((Elf_Rela *)mrelp)->r_addend = addend; |
218 | *mlocp++ = 0; | 294 | *mlocp++ = 0; |