aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 14:13:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 14:13:10 -0400
commitb77d643ced576bdd1e918aebda869de74696cde9 (patch)
treebb5d708f4bbb48461923a28e63a8cf8bdd477dd7 /scripts
parentb4020c1b198c0f0c0b0ff0cfdd824a26b93edd6f (diff)
parent64575f918f3279d8487cf670dbefa956ce16a526 (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus: (46 commits) ftrace/MIPS: Enable C Version of recordmcount ftrace/MIPS: Add module support for C version of recordmcount ftrace/MIPS: Add MIPS64 support for C version of recordmcount MIPS: Make TASK_SIZE reflect proper size for both 32 and 64 bit processes. MIPS: Allow UserLocal on MIPS_R1 processors MIPS: Honor L2 bypass bit MIPS: Add BMIPS CP0 register definitions MIPS: Add BMIPS processor types to Kconfig MIPS: Decouple BMIPS CPU support from bcm47xx/bcm63xx SoC code MIPS: Add support for hardware performance events (mipsxx) MIPS: Perf-events: Add callchain support MIPS: add support for hardware performance events (skeleton) MIPS: add support for software performance events MIPS: define local_xchg from xchg_local to atomic_long_xchg MIPS: AR7: Add support for Titan (TNETV10xx) SoC variant MIPS: AR7: Initialize GPIO earlier MIPS: Add platform device and Kconfig for Octeon USB EHCI / OHCI USB: Add EHCI and OHCH glue for OCTEON II SOCs. MIPS: Octeon: Add register definitions for EHCI / OHCI USB glue logic. MIPS: Octeon: Apply CN63XXP1 errata workarounds. ...
Diffstat (limited to 'scripts')
-rw-r--r--scripts/recordmcount.c44
-rw-r--r--scripts/recordmcount.h86
2 files changed, 125 insertions, 5 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 26e1271259ba..f2f32eee2c5b 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -217,6 +217,39 @@ is_mcounted_section_name(char const *const txtname)
217#define RECORD_MCOUNT_64 217#define RECORD_MCOUNT_64
218#include "recordmcount.h" 218#include "recordmcount.h"
219 219
220/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
221 * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
222 * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
223 * to imply the order of the members; the spec does not say so.
224 * typedef unsigned char Elf64_Byte;
225 * fails on MIPS64 because their <elf.h> already has it!
226 */
227
228typedef uint8_t myElf64_Byte; /* Type for a 8-bit quantity. */
229
230union mips_r_info {
231 Elf64_Xword r_info;
232 struct {
233 Elf64_Word r_sym; /* Symbol index. */
234 myElf64_Byte r_ssym; /* Special symbol. */
235 myElf64_Byte r_type3; /* Third relocation. */
236 myElf64_Byte r_type2; /* Second relocation. */
237 myElf64_Byte r_type; /* First relocation. */
238 } r_mips;
239};
240
241static uint64_t MIPS64_r_sym(Elf64_Rel const *rp)
242{
243 return w(((union mips_r_info){ .r_info = rp->r_info }).r_mips.r_sym);
244}
245
246static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
247{
248 rp->r_info = ((union mips_r_info){
249 .r_mips = { .r_sym = w(sym), .r_type = type }
250 }).r_info;
251}
252
220static void 253static void
221do_file(char const *const fname) 254do_file(char const *const fname)
222{ 255{
@@ -268,6 +301,7 @@ do_file(char const *const fname)
268 case EM_386: reltype = R_386_32; break; 301 case EM_386: reltype = R_386_32; break;
269 case EM_ARM: reltype = R_ARM_ABS32; break; 302 case EM_ARM: reltype = R_ARM_ABS32; break;
270 case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break; 303 case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
304 case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
271 case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break; 305 case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
272 case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break; 306 case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
273 case EM_S390: /* reltype: e_class */ gpfx = '_'; break; 307 case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
@@ -291,6 +325,10 @@ do_file(char const *const fname)
291 } 325 }
292 if (EM_S390 == w2(ehdr->e_machine)) 326 if (EM_S390 == w2(ehdr->e_machine))
293 reltype = R_390_32; 327 reltype = R_390_32;
328 if (EM_MIPS == w2(ehdr->e_machine)) {
329 reltype = R_MIPS_32;
330 is_fake_mcount32 = MIPS32_is_fake_mcount;
331 }
294 do32(ehdr, fname, reltype); 332 do32(ehdr, fname, reltype);
295 } break; 333 } break;
296 case ELFCLASS64: { 334 case ELFCLASS64: {
@@ -303,6 +341,12 @@ do_file(char const *const fname)
303 } 341 }
304 if (EM_S390 == w2(ghdr->e_machine)) 342 if (EM_S390 == w2(ghdr->e_machine))
305 reltype = R_390_64; 343 reltype = R_390_64;
344 if (EM_MIPS == w2(ghdr->e_machine)) {
345 reltype = R_MIPS_64;
346 Elf64_r_sym = MIPS64_r_sym;
347 Elf64_r_info = MIPS64_r_info;
348 is_fake_mcount64 = MIPS64_is_fake_mcount;
349 }
306 do64(ghdr, fname, reltype); 350 do64(ghdr, fname, reltype);
307 } break; 351 } break;
308 } /* end switch */ 352 } /* end switch */
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. */
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
114static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
115{
116 return ELF_R_SYM(_w(rp->r_info));
117}
118static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
119
120static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
121{
122 rp->r_info = ELF_R_INFO(sym, type);
123}
124static 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
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}
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. */
84static void append_func(Elf_Ehdr *const ehdr, 161static 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;