aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/tools/relocs.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/tools/relocs.c')
-rw-r--r--arch/x86/tools/relocs.c36
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
21static struct relocs relocs16; 21static struct relocs relocs16;
22static struct relocs relocs32; 22static struct relocs relocs32;
23#if ELF_BITS == 64
24static struct relocs relocs32neg;
23static struct relocs relocs64; 25static struct relocs relocs64;
26#endif
24 27
25struct section { 28struct 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);