|
@@ -20,7 +20,10 @@ struct relocs {
|
|
|
|
|
|
static struct relocs relocs16;
|
|
|
static struct relocs relocs32;
|
|
|
+#if ELF_BITS == 64
|
|
|
+static struct relocs relocs32neg;
|
|
|
static struct relocs relocs64;
|
|
|
+#endif
|
|
|
|
|
|
struct section {
|
|
|
Elf_Shdr shdr;
|
|
@@ -762,11 +765,16 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
|
|
|
|
|
|
switch (r_type) {
|
|
|
case R_X86_64_NONE:
|
|
|
+ /* NONE can be ignored. */
|
|
|
+ break;
|
|
|
+
|
|
|
case R_X86_64_PC32:
|
|
|
/*
|
|
|
- * NONE can be ignored and PC relative relocations don't
|
|
|
- * need to be adjusted.
|
|
|
+ * PC relative relocations don't need to be adjusted unless
|
|
|
+ * referencing a percpu symbol.
|
|
|
*/
|
|
|
+ if (is_percpu_sym(sym, symname))
|
|
|
+ add_reloc(&relocs32neg, offset);
|
|
|
break;
|
|
|
|
|
|
case R_X86_64_32:
|
|
@@ -986,7 +994,10 @@ static void emit_relocs(int as_text, int use_real_mode)
|
|
|
/* Order the relocations for more efficient processing */
|
|
|
sort_relocs(&relocs16);
|
|
|
sort_relocs(&relocs32);
|
|
|
+#if ELF_BITS == 64
|
|
|
+ sort_relocs(&relocs32neg);
|
|
|
sort_relocs(&relocs64);
|
|
|
+#endif
|
|
|
|
|
|
/* Print the relocations */
|
|
|
if (as_text) {
|
|
@@ -1007,14 +1018,21 @@ static void emit_relocs(int as_text, int use_real_mode)
|
|
|
for (i = 0; i < relocs32.count; i++)
|
|
|
write_reloc(relocs32.offset[i], stdout);
|
|
|
} else {
|
|
|
- if (ELF_BITS == 64) {
|
|
|
- /* Print a stop */
|
|
|
- write_reloc(0, stdout);
|
|
|
+#if ELF_BITS == 64
|
|
|
+ /* Print a stop */
|
|
|
+ write_reloc(0, stdout);
|
|
|
|
|
|
- /* Now print each relocation */
|
|
|
- for (i = 0; i < relocs64.count; i++)
|
|
|
- write_reloc(relocs64.offset[i], stdout);
|
|
|
- }
|
|
|
+ /* Now print each relocation */
|
|
|
+ for (i = 0; i < relocs64.count; i++)
|
|
|
+ write_reloc(relocs64.offset[i], stdout);
|
|
|
+
|
|
|
+ /* Print a stop */
|
|
|
+ write_reloc(0, stdout);
|
|
|
+
|
|
|
+ /* Now print each inverse 32-bit relocation */
|
|
|
+ for (i = 0; i < relocs32neg.count; i++)
|
|
|
+ write_reloc(relocs32neg.offset[i], stdout);
|
|
|
+#endif
|
|
|
|
|
|
/* Print a stop */
|
|
|
write_reloc(0, stdout);
|