diff options
Diffstat (limited to 'arch/x86/tools/relocs.c')
-rw-r--r-- | arch/x86/tools/relocs.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index a5efb21d5228..0c2fae8d929d 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -20,7 +20,10 @@ struct relocs { | |||
20 | 20 | ||
21 | static struct relocs relocs16; | 21 | static struct relocs relocs16; |
22 | static struct relocs relocs32; | 22 | static struct relocs relocs32; |
23 | #if ELF_BITS == 64 | ||
24 | static struct relocs relocs32neg; | ||
23 | static struct relocs relocs64; | 25 | static struct relocs relocs64; |
26 | #endif | ||
24 | 27 | ||
25 | struct section { | 28 | struct section { |
26 | Elf_Shdr shdr; | 29 | Elf_Shdr shdr; |
@@ -762,11 +765,16 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, | |||
762 | 765 | ||
763 | switch (r_type) { | 766 | switch (r_type) { |
764 | case R_X86_64_NONE: | 767 | case R_X86_64_NONE: |
768 | /* NONE can be ignored. */ | ||
769 | break; | ||
770 | |||
765 | case R_X86_64_PC32: | 771 | case R_X86_64_PC32: |
766 | /* | 772 | /* |
767 | * NONE can be ignored and PC relative relocations don't | 773 | * PC relative relocations don't need to be adjusted unless |
768 | * need to be adjusted. | 774 | * referencing a percpu symbol. |
769 | */ | 775 | */ |
776 | if (is_percpu_sym(sym, symname)) | ||
777 | add_reloc(&relocs32neg, offset); | ||
770 | break; | 778 | break; |
771 | 779 | ||
772 | case R_X86_64_32: | 780 | case R_X86_64_32: |
@@ -986,7 +994,10 @@ static void emit_relocs(int as_text, int use_real_mode) | |||
986 | /* Order the relocations for more efficient processing */ | 994 | /* Order the relocations for more efficient processing */ |
987 | sort_relocs(&relocs16); | 995 | sort_relocs(&relocs16); |
988 | sort_relocs(&relocs32); | 996 | sort_relocs(&relocs32); |
997 | #if ELF_BITS == 64 | ||
998 | sort_relocs(&relocs32neg); | ||
989 | sort_relocs(&relocs64); | 999 | sort_relocs(&relocs64); |
1000 | #endif | ||
990 | 1001 | ||
991 | /* Print the relocations */ | 1002 | /* Print the relocations */ |
992 | if (as_text) { | 1003 | if (as_text) { |
@@ -1007,14 +1018,21 @@ static void emit_relocs(int as_text, int use_real_mode) | |||
1007 | for (i = 0; i < relocs32.count; i++) | 1018 | for (i = 0; i < relocs32.count; i++) |
1008 | write_reloc(relocs32.offset[i], stdout); | 1019 | write_reloc(relocs32.offset[i], stdout); |
1009 | } else { | 1020 | } else { |
1010 | if (ELF_BITS == 64) { | 1021 | #if ELF_BITS == 64 |
1011 | /* Print a stop */ | 1022 | /* Print a stop */ |
1012 | write_reloc(0, stdout); | 1023 | write_reloc(0, stdout); |
1013 | 1024 | ||
1014 | /* Now print each relocation */ | 1025 | /* Now print each relocation */ |
1015 | for (i = 0; i < relocs64.count; i++) | 1026 | for (i = 0; i < relocs64.count; i++) |
1016 | write_reloc(relocs64.offset[i], stdout); | 1027 | write_reloc(relocs64.offset[i], stdout); |
1017 | } | 1028 | |
1029 | /* Print a stop */ | ||
1030 | write_reloc(0, stdout); | ||
1031 | |||
1032 | /* Now print each inverse 32-bit relocation */ | ||
1033 | for (i = 0; i < relocs32neg.count; i++) | ||
1034 | write_reloc(relocs32neg.offset[i], stdout); | ||
1035 | #endif | ||
1018 | 1036 | ||
1019 | /* Print a stop */ | 1037 | /* Print a stop */ |
1020 | write_reloc(0, stdout); | 1038 | write_reloc(0, stdout); |