On 10/23/2010, wu zhangjin wrote: > CC init/main.o > /bin/sh: line 1: 21835 Segmentation fault scripts/recordmcount "init/main.o" > make[1]: *** [init/main.o] Error 139 64-bit EM_MIPS has weird ELF64_Rela.info. Adjust recordmcount.[ch]. Signed-off-by: John Reiser <jreiser@xxxxxxxxxxxx> [I don't know where the git repository for recordmcount.h is, so I have used a temporary one.] --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -212,11 +212,26 @@ is_mcounted_section_name(char const *const txtname) 0 == strcmp(".text.unlikely", txtname); } + /* 32 bit and 64 bit are very similar */ #include "recordmcount.h" #define RECORD_MCOUNT_64 #include "recordmcount.h" +/* 64-bit EM_MIPS has weird ELF64_Rela.r_info */ +static uint64_t MIPS64_r_sym(Elf64_Xword xword) +{ + /* Perhaps this should be 40 bits, but kernel isn't that big. */ + return 0xffffffff & xword; +} + +static uint64_t MIPS64_r_info(Elf64_Xword sym, unsigned type) +{ + /* Type2 and Type3 are assumed zero. [See "readelf --relocs".] */ + return (((uint64_t)type)<<56) | sym; +} + + static void do_file(char const *const fname) { @@ -268,6 +283,7 @@ do_file(char const *const fname) case EM_386: reltype = R_386_32; break; case EM_ARM: reltype = R_ARM_ABS32; break; case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break; + case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break; case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break; case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break; case EM_S390: /* reltype: e_class */ gpfx = '_'; break; @@ -291,6 +307,8 @@ do_file(char const *const fname) } if (EM_S390 == w2(ehdr->e_machine)) reltype = R_390_32; + if (EM_MIPS == w2(ehdr->e_machine)) + reltype = R_MIPS_32; do32(ehdr, fname, reltype); } break; case ELFCLASS64: { @@ -303,6 +321,11 @@ do_file(char const *const fname) } if (EM_S390 == w2(ghdr->e_machine)) reltype = R_390_64; + if (EM_MIPS == w2(ghdr->e_machine)) { + reltype = R_MIPS_64; + Elf_r_sym = MIPS64_r_sym; + Elf_r_info = MIPS64_r_info; + } do64(ghdr, fname, reltype); } break; } /* end switch */ --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -31,8 +31,12 @@ #undef Elf_Rela #undef Elf_Sym #undef ELF_R_SYM +#undef Elf_r_sym #undef ELF_R_INFO +#undef Elf_r_info #undef ELF_ST_BIND +#undef fn_ELF_R_SYM +#undef fn_ELF_R_INFO #undef uint_t #undef _w #undef _align @@ -52,8 +56,12 @@ # define Elf_Rela Elf64_Rela # define Elf_Sym Elf64_Sym # define ELF_R_SYM ELF64_R_SYM +# define Elf_r_sym Elf64_r_sym # define ELF_R_INFO ELF64_R_INFO +# define Elf_r_info Elf64_r_info # define ELF_ST_BIND ELF64_ST_BIND +# define fn_ELF_R_SYM fn_ELF64_R_SYM +# define fn_ELF_R_INFO fn_ELF64_R_INFO # define uint_t uint64_t # define _w w8 # define _align 7u @@ -72,14 +80,32 @@ # define Elf_Rela Elf32_Rela # define Elf_Sym Elf32_Sym # define ELF_R_SYM ELF32_R_SYM +# define Elf_r_sym Elf32_r_sym # define ELF_R_INFO ELF32_R_INFO +# define Elf_r_info Elf32_r_info # define ELF_ST_BIND ELF32_ST_BIND +# define fn_ELF_R_SYM fn_ELF32_R_SYM +# define fn_ELF_R_INFO fn_ELF32_R_INFO # define uint_t uint32_t # define _w w # define _align 3u # define _size 4 #endif +/* Functions and pointers that 64-bit EM_MIPS can override. */ +static uint_t fn_ELF_R_SYM(uint_t info) +{ + return ELF_R_SYM(info); +} +static uint_t (*Elf_r_sym)(uint_t info) = fn_ELF_R_SYM; + +static uint_t fn_ELF_R_INFO(uint_t sym, unsigned type) +{ + return ELF_R_INFO(sym, type); +} +static uint_t (*Elf_r_info)(uint_t sym, unsigned type) = fn_ELF_R_INFO; + + /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ static void append_func(Elf_Ehdr *const ehdr, Elf_Shdr *const shstr, @@ -197,22 +223,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp, for (t = nrel; t; --t) { if (!mcountsym) { Elf_Sym const *const symp = - &sym0[ELF_R_SYM(_w(relp->r_info))]; + &sym0[Elf_r_sym(_w(relp->r_info))]; char const *symname = &str0[w(symp->st_name)]; if ('.' == symname[0]) ++symname; /* ppc64 hack */ if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"), symname)) - mcountsym = ELF_R_SYM(_w(relp->r_info)); + mcountsym = Elf_r_sym(_w(relp->r_info)); } - if (mcountsym == ELF_R_SYM(_w(relp->r_info))) { + if (mcountsym == Elf_r_sym(_w(relp->r_info))) { uint_t const addend = _w(_w(relp->r_offset) - recval); mrelp->r_offset = _w(offbase + ((void *)mlocp - (void *)mloc0)); - mrelp->r_info = _w(ELF_R_INFO(recsym, reltype)); + mrelp->r_info = _w(Elf_r_info(recsym, reltype)); if (sizeof(Elf_Rela) == rel_entsize) { ((Elf_Rela *)mrelp)->r_addend = addend; *mlocp++ = 0; -- John Reiser, jreiser@xxxxxxxxxxxx