pc32 -> plt32 conversion and related questions
Jan Beulich
jbeulich@suse.com
Tue Jun 15 13:42:03 GMT 2021
H.J.,
alongside the question of what non-zero addends mean for certain
relocation types, I came to notice that this conversion may be
done in cases where it would better be avoided. I have the draft
patch below (still lacking a test case and ChangeLog entry), and
I particularly wonder whether the information propagation
approach to md_estimate_size_before_relax() is acceptable, or
whether you have other (better) suggestions.
While playing with this (and in particular the code that I mean
to convert into a testcase) I came to further notice that there
is an inconsistency in whether relocations for branches get
emitted for locally defined symbols:
.text
.global _start, func
_start:
call func # gets converted to PLT32 reloc (and would be subject to preemption even when left as PC32), ...
jc func # ... while this and ...
jmp func # ... this get resolved locally, unless ...
# ... this directive is enabled (or -mshared gets passed)
#.section .text.lib, "ax", @progbits
func:
ret
.type func, @function
.size func, .-func
In 2.30 (i.e. before the pc32 -> plt32 conversion) the CALL
yields a PC32 reloc, so the issue isn't directly related to that
change. But given the effect -mshared has on JMP and Jcc, do you
agree that CALL should be handled consistently with JMP/Jcc here?
Not the least to match the documentation of -mshared:
"On ELF target, the assembler normally optimizes out non-PLT
relocations against defined non-weak global branch targets with
default visibility."
It doesn't mention that there's a difference between different
kinds of branches.
And then, still in this same context, I did also notice that the
linker complains about e.g. PC32 relocs when building a shared
library even when that's a x32 one (suggesting to rebuild with
-fPIC). 32-bit relocations can't overflow in that ABI, so wouldn't
such errors better be suppressed there?
Thanks, Jan
x86-64: restrict PC32 -> PLT32 conversion
Neither non-64-bit code nor uses with a non-zero offset from a symbol
should be converted to PLT32, as an eventual PLT entry would not express
what was requested.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -8765,6 +8765,8 @@ output_branch (void)
off = 0;
}
+ frag_now->tc_frag_data.code64 = flag_code == CODE_64BIT;
+
/* 1 possible extra opcode + 4 byte displacement go in var part.
Pass reloc in fr_var. */
frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p);
@@ -8893,8 +8895,8 @@ output_jump (void)
}
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
- if (size == 4
- && jump_reloc == NO_RELOC
+ if (flag_code == CODE_64BIT && size == 4
+ && jump_reloc == NO_RELOC && i.op[0].disps->X_add_number == 0
&& need_plt32_p (i.op[0].disps->X_add_symbol))
jump_reloc = BFD_RELOC_X86_64_PLT32;
#endif
@@ -12191,7 +12193,8 @@ md_estimate_size_before_relax (fragS *fr
else if (size == 2)
reloc_type = BFD_RELOC_16_PCREL;
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
- else if (need_plt32_p (fragP->fr_symbol))
+ else if (fragP->tc_frag_data.code64 && fragP->fr_offset == 0
+ && need_plt32_p (fragP->fr_symbol))
reloc_type = BFD_RELOC_X86_64_PLT32;
#endif
else
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -280,6 +280,7 @@ struct i386_tc_frag_data
unsigned int mf_type : 3;
unsigned int classified : 1;
unsigned int branch_type : 3;
+ unsigned int code64 : 1; /* Only set by output_branch for now. */
};
/* We need to emit the right NOP pattern in .align frags. This is
More information about the Binutils
mailing list