aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorJohn Reiser <jreiser@BitWagon.com>2010-10-27 06:59:07 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:54 -0400
commita2d49358ba9bc93204dc001d5568c5bdb299b77d (patch)
treea9f70362c6aba75f56ad4a808473ae961cff957b /scripts
parent949e51bea342da838be5295628e4a7ada8bae833 (diff)
ftrace/MIPS: Add MIPS64 support for C version of recordmcount
MIPS64 has 'weird' Elf64_Rel.r_info[1,2], which must be used instead of the generic Elf64_Rel.r_info, otherwise, the C version of recordmcount will not work for "segmentation fault". Usage of "union mips_r_info" and the functions MIPS64_r_sym() and MIPS64_r_info() written by Maciej W. Rozycki <macro@linux-mips.org> ---- [1] http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf [2] arch/mips/include/asm/module.h Tested-by: Wu Zhangjin <wuzhangjin@gmail.com> Signed-off-by: John Reiser <jreiser@BitWagon.com> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> LKML-Reference: <AANLkTinwXjLAYACUfhLYaocHD_vBbiErLN3NjwN8JqSy@mail.gmail.com> LKML-Reference: <910dc2d5ae1ed042df4f96815fe4a433078d1c2a.1288176026.git.wuzhangjin@gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/recordmcount.c41
-rw-r--r--scripts/recordmcount.h34
2 files changed, 71 insertions, 4 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 26e1271259b..2d32b9ced20 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,8 @@ 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;
294 do32(ehdr, fname, reltype); 330 do32(ehdr, fname, reltype);
295 } break; 331 } break;
296 case ELFCLASS64: { 332 case ELFCLASS64: {
@@ -303,6 +339,11 @@ do_file(char const *const fname)
303 } 339 }
304 if (EM_S390 == w2(ghdr->e_machine)) 340 if (EM_S390 == w2(ghdr->e_machine))
305 reltype = R_390_64; 341 reltype = R_390_64;
342 if (EM_MIPS == w2(ghdr->e_machine)) {
343 reltype = R_MIPS_64;
344 Elf64_r_sym = MIPS64_r_sym;
345 Elf64_r_info = MIPS64_r_info;
346 }
306 do64(ghdr, fname, reltype); 347 do64(ghdr, fname, reltype);
307 } break; 348 } break;
308 } /* end switch */ 349 } /* end switch */
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 7f39d0943d2..190fd18dc85 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -31,8 +31,12 @@
31#undef Elf_Rela 31#undef Elf_Rela
32#undef Elf_Sym 32#undef Elf_Sym
33#undef ELF_R_SYM 33#undef ELF_R_SYM
34#undef Elf_r_sym
34#undef ELF_R_INFO 35#undef ELF_R_INFO
36#undef Elf_r_info
35#undef ELF_ST_BIND 37#undef ELF_ST_BIND
38#undef fn_ELF_R_SYM
39#undef fn_ELF_R_INFO
36#undef uint_t 40#undef uint_t
37#undef _w 41#undef _w
38#undef _align 42#undef _align
@@ -52,8 +56,12 @@
52# define Elf_Rela Elf64_Rela 56# define Elf_Rela Elf64_Rela
53# define Elf_Sym Elf64_Sym 57# define Elf_Sym Elf64_Sym
54# define ELF_R_SYM ELF64_R_SYM 58# define ELF_R_SYM ELF64_R_SYM
59# define Elf_r_sym Elf64_r_sym
55# define ELF_R_INFO ELF64_R_INFO 60# define ELF_R_INFO ELF64_R_INFO
61# define Elf_r_info Elf64_r_info
56# define ELF_ST_BIND ELF64_ST_BIND 62# define ELF_ST_BIND ELF64_ST_BIND
63# define fn_ELF_R_SYM fn_ELF64_R_SYM
64# define fn_ELF_R_INFO fn_ELF64_R_INFO
57# define uint_t uint64_t 65# define uint_t uint64_t
58# define _w w8 66# define _w w8
59# define _align 7u 67# define _align 7u
@@ -72,14 +80,32 @@
72# define Elf_Rela Elf32_Rela 80# define Elf_Rela Elf32_Rela
73# define Elf_Sym Elf32_Sym 81# define Elf_Sym Elf32_Sym
74# define ELF_R_SYM ELF32_R_SYM 82# define ELF_R_SYM ELF32_R_SYM
83# define Elf_r_sym Elf32_r_sym
75# define ELF_R_INFO ELF32_R_INFO 84# define ELF_R_INFO ELF32_R_INFO
85# define Elf_r_info Elf32_r_info
76# define ELF_ST_BIND ELF32_ST_BIND 86# define ELF_ST_BIND ELF32_ST_BIND
87# define fn_ELF_R_SYM fn_ELF32_R_SYM
88# define fn_ELF_R_INFO fn_ELF32_R_INFO
77# define uint_t uint32_t 89# define uint_t uint32_t
78# define _w w 90# define _w w
79# define _align 3u 91# define _align 3u
80# define _size 4 92# define _size 4
81#endif 93#endif
82 94
95/* Functions and pointers that 64-bit EM_MIPS can override. */
96static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
97{
98 return ELF_R_SYM(_w(rp->r_info));
99}
100static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
101
102static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
103{
104 rp->r_info = ELF_R_INFO(sym, type);
105}
106static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
107
108
83/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ 109/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
84static void append_func(Elf_Ehdr *const ehdr, 110static void append_func(Elf_Ehdr *const ehdr,
85 Elf_Shdr *const shstr, 111 Elf_Shdr *const shstr,
@@ -197,22 +223,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
197 for (t = nrel; t; --t) { 223 for (t = nrel; t; --t) {
198 if (!mcountsym) { 224 if (!mcountsym) {
199 Elf_Sym const *const symp = 225 Elf_Sym const *const symp =
200 &sym0[ELF_R_SYM(_w(relp->r_info))]; 226 &sym0[Elf_r_sym(relp)];
201 char const *symname = &str0[w(symp->st_name)]; 227 char const *symname = &str0[w(symp->st_name)];
202 228
203 if ('.' == symname[0]) 229 if ('.' == symname[0])
204 ++symname; /* ppc64 hack */ 230 ++symname; /* ppc64 hack */
205 if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"), 231 if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
206 symname)) 232 symname))
207 mcountsym = ELF_R_SYM(_w(relp->r_info)); 233 mcountsym = Elf_r_sym(relp);
208 } 234 }
209 235
210 if (mcountsym == ELF_R_SYM(_w(relp->r_info))) { 236 if (mcountsym == Elf_r_sym(relp)) {
211 uint_t const addend = _w(_w(relp->r_offset) - recval); 237 uint_t const addend = _w(_w(relp->r_offset) - recval);
212 238
213 mrelp->r_offset = _w(offbase 239 mrelp->r_offset = _w(offbase
214 + ((void *)mlocp - (void *)mloc0)); 240 + ((void *)mlocp - (void *)mloc0));
215 mrelp->r_info = _w(ELF_R_INFO(recsym, reltype)); 241 Elf_r_info(mrelp, recsym, reltype);
216 if (sizeof(Elf_Rela) == rel_entsize) { 242 if (sizeof(Elf_Rela) == rel_entsize) {
217 ((Elf_Rela *)mrelp)->r_addend = addend; 243 ((Elf_Rela *)mrelp)->r_addend = addend;
218 *mlocp++ = 0; 244 *mlocp++ = 0;