diff options
Diffstat (limited to 'arch/x86/tools')
| -rw-r--r-- | arch/x86/tools/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/tools/relocs.c | 52 | ||||
| -rw-r--r-- | arch/x86/tools/relocs.h | 7 | ||||
| -rw-r--r-- | arch/x86/tools/relocs_common.c | 16 | 
4 files changed, 63 insertions, 14 deletions
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index e8120346903..604a37efd4d 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile @@ -40,4 +40,6 @@ $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/ina  HOST_EXTRACFLAGS += -I$(srctree)/tools/include  hostprogs-y	+= relocs  relocs-objs     := relocs_32.o relocs_64.o relocs_common.o +PHONY += relocs  relocs: $(obj)/relocs +	@: diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index f7bab68a4b8..bbb1d2259ec 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -69,8 +69,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {  	"__per_cpu_load|"  	"init_per_cpu__.*|"  	"__end_rodata_hpage_align|" -	"__vvar_page|"  #endif +	"__vvar_page|"  	"_end)$"  }; @@ -722,15 +722,25 @@ static void percpu_init(void)  /*   * Check to see if a symbol lies in the .data..percpu section. - * For some as yet not understood reason the "__init_begin" - * symbol which immediately preceeds the .data..percpu section - * also shows up as it it were part of it so we do an explict - * check for that symbol name and ignore it. + * + * The linker incorrectly associates some symbols with the + * .data..percpu section so we also need to check the symbol + * name to make sure that we classify the symbol correctly. + * + * The GNU linker incorrectly associates: + *	__init_begin + *	__per_cpu_load + * + * The "gold" linker incorrectly associates: + *	init_per_cpu__irq_stack_union + *	init_per_cpu__gdt_page   */  static int is_percpu_sym(ElfW(Sym) *sym, const char *symname)  {  	return (sym->st_shndx == per_cpu_shndx) && -		strcmp(symname, "__init_begin"); +		strcmp(symname, "__init_begin") && +		strcmp(symname, "__per_cpu_load") && +		strncmp(symname, "init_per_cpu_", 13);  } @@ -1015,6 +1025,29 @@ static void emit_relocs(int as_text, int use_real_mode)  	}  } +/* + * As an aid to debugging problems with different linkers + * print summary information about the relocs. + * Since different linkers tend to emit the sections in + * different orders we use the section names in the output. + */ +static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, +				const char *symname) +{ +	printf("%s\t%s\t%s\t%s\n", +		sec_name(sec->shdr.sh_info), +		rel_type(ELF_R_TYPE(rel->r_info)), +		symname, +		sec_name(sym->st_shndx)); +	return 0; +} + +static void print_reloc_info(void) +{ +	printf("reloc section\treloc type\tsymbol\tsymbol section\n"); +	walk_relocs(do_reloc_info); +} +  #if ELF_BITS == 64  # define process process_64  #else @@ -1022,7 +1055,8 @@ static void emit_relocs(int as_text, int use_real_mode)  #endif  void process(FILE *fp, int use_real_mode, int as_text, -	     int show_absolute_syms, int show_absolute_relocs) +	     int show_absolute_syms, int show_absolute_relocs, +	     int show_reloc_info)  {  	regex_init(use_real_mode);  	read_ehdr(fp); @@ -1040,5 +1074,9 @@ void process(FILE *fp, int use_real_mode, int as_text,  		print_absolute_relocs();  		return;  	} +	if (show_reloc_info) { +		print_reloc_info(); +		return; +	}  	emit_relocs(as_text, use_real_mode);  } diff --git a/arch/x86/tools/relocs.h b/arch/x86/tools/relocs.h index 07cdb1eca4f..f59590645b6 100644 --- a/arch/x86/tools/relocs.h +++ b/arch/x86/tools/relocs.h @@ -29,8 +29,9 @@ enum symtype {  };  void process_32(FILE *fp, int use_real_mode, int as_text, -		int show_absolute_syms, int show_absolute_relocs); +		int show_absolute_syms, int show_absolute_relocs, +		int show_reloc_info);  void process_64(FILE *fp, int use_real_mode, int as_text, -		int show_absolute_syms, int show_absolute_relocs); - +		int show_absolute_syms, int show_absolute_relocs, +		int show_reloc_info);  #endif /* RELOCS_H */ diff --git a/arch/x86/tools/relocs_common.c b/arch/x86/tools/relocs_common.c index 44d396823a5..acab636bcb3 100644 --- a/arch/x86/tools/relocs_common.c +++ b/arch/x86/tools/relocs_common.c @@ -11,12 +11,13 @@ void die(char *fmt, ...)  static void usage(void)  { -	die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); +	die("relocs [--abs-syms|--abs-relocs|--reloc-info|--text|--realmode]" \ +	    " vmlinux\n");  }  int main(int argc, char **argv)  { -	int show_absolute_syms, show_absolute_relocs; +	int show_absolute_syms, show_absolute_relocs, show_reloc_info;  	int as_text, use_real_mode;  	const char *fname;  	FILE *fp; @@ -25,6 +26,7 @@ int main(int argc, char **argv)  	show_absolute_syms = 0;  	show_absolute_relocs = 0; +	show_reloc_info = 0;  	as_text = 0;  	use_real_mode = 0;  	fname = NULL; @@ -39,6 +41,10 @@ int main(int argc, char **argv)  				show_absolute_relocs = 1;  				continue;  			} +			if (strcmp(arg, "--reloc-info") == 0) { +				show_reloc_info = 1; +				continue; +			}  			if (strcmp(arg, "--text") == 0) {  				as_text = 1;  				continue; @@ -67,10 +73,12 @@ int main(int argc, char **argv)  	rewind(fp);  	if (e_ident[EI_CLASS] == ELFCLASS64)  		process_64(fp, use_real_mode, as_text, -			   show_absolute_syms, show_absolute_relocs); +			   show_absolute_syms, show_absolute_relocs, +			   show_reloc_info);  	else  		process_32(fp, use_real_mode, as_text, -			   show_absolute_syms, show_absolute_relocs); +			   show_absolute_syms, show_absolute_relocs, +			   show_reloc_info);  	fclose(fp);  	return 0;  }  | 
