[PATCH] LoongArch: Use copy relocation for %pc_lo12 against external symbol

Xi Ruoyao xry111@xry111.site
Wed Aug 31 13:41:56 GMT 2022

Some self review:

On Wed, 2022-08-31 at 21:22 +0800, Xi Ruoyao wrote:
> -             /* For pcalau12i + jirl.  */
> -             h->needs_plt = 1;
> -             if (h->plt.refcount < 0)
> -               h->plt.refcount = 0;
> -             h->plt.refcount++;
> +             /* Check if it's a jirl instruction.  */
> +             bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
> +             uint32_t insn = 0;
> +
> +             if (contents || bfd_malloc_and_get_section (abfd, sec, &contents))
> +               memcpy(&insn, contents + rel->r_offset, sizeof(insn));
> +
> +             if ((insn & 0xfc000000) == 0x4c000000)

This is tricky.  But in commit 42bd525 we already started to rely on
undocumented %pc_{hi20,lo12} behavior: if you just apply them "as
documented" to the pcalau12i/jirl pairs the result will be absolutely
wrong.  And 42bd525 behavior is not fully correct: if you just write

pcalau12i $t0, %pc_hi20(data)
ld.d, $t0, $t0, %pc_lo12(data)

With 42bd525, the BFD linker generates a "PLT for data" (absolutely
nonsense), and destroys the ld.d instruction.  All of these buggy
behavior happens silently, the user will only find something wrong when
the linked program crashes.

I'm not sure if checking JIRL (i. e. the behavior of a relocation now
depends on the instruction where it's applied) is a good idea.  Maybe we
should use the following instead of pcalau12i/jirl:

pcaddu18i $t0, %b16_hi20(func)
jirl $ra, $t0, %b16(func)

("b16_hi20" is a hypothetical thing here.)  This will make things less
tricky, and also expand the range to 128 GiB.

Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

More information about the Binutils mailing list