The current linker has
/* With the local symbol, foo, we convert
mov foo@GOTPCREL(%rip), %reg
to
lea foo(%rip), %reg
and convert
call/jmp *foo@GOTPCREL(%rip)
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg, foo@GOTPCREL(%rip)
to
test $foo, %reg
and convert
binop foo@GOTPCREL(%rip), %reg
to
binop $foo, %reg
where binop is one of adc, add, and, cmp, or, sbb, sub, xor
instructions. */
static bool
elf_x86_64_convert_load_reloc (bfd *abfd,
bfd_byte *contents,
unsigned int *r_type_p,
Elf_Internal_Rela *irel,
struct elf_link_hash_entry *h,
bool *converted,
struct bfd_link_info *link_info)
{
struct elf_x86_link_hash_table *htab;
bool is_pic;
bool no_overflow;
bool relocx;
bool to_reloc_pc32;
bool abs_symbol;
bool local_ref;
asection *tsec;
bfd_signed_vma raddend;
unsigned int opcode;
unsigned int modrm;
unsigned int r_type = *r_type_p;
unsigned int r_symndx;
bfd_vma roff = irel->r_offset;
bfd_vma abs_relocation;
if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
return true;
raddend = irel->r_addend;
/* Addend for 32-bit PC-relative relocation must be -4. */
if (raddend != -4)
return true;
If addend != -4, the linker optimization is disabled. I don't believe
that linker should optimize the addend != -4 case.
>
> Ciao,
> Michael.
>
> >
> > > into
> > >
> > > movl $foo+4, %eax
> > >
> > > Of course the checking for 32bit range needs to be applied to the full
> > > value of foo+4, i.e. including the addend, but that's not different from
> > > any other reloc processing. Even if the target insn is going to be lea,
> > > it's then:
> > >
> > > lea foo+4(%rip), %eax
> > >
> > > which still is fine (of course foo-P+4 needs to fit the memoffset field,
> > > like normally foo-4-P+4 needs to fit for the usual -4 addends).
> > >
> > > If you think there are issues with any of this I would appreciate a
> > > specific example of input instruction plus relocs, and candidate
> > > transformation that is not going to work.
> > >
> > >
> > > Ciao,
> > > Michael.
> >
> >
> >
> >
--
H.J.