[PATCH] VAX: PIC: Use GOT for pointer for global function
Maciej W. Rozycki
macro@orcam.me.uk
Mon May 5 21:31:23 GMT 2025
On Mon, 5 May 2025, Rin Okuyama wrote:
> in same file, instead of PLT
>
> This fixes the problem reported as Bug 32941:
> https://sourceware.org/bugzilla/show_bug.cgi?id=32941
>
> Consider the following C source, main.c:
>
> ```
>
> void func(void) {
> }
>
> int main(void) {
> printf("%s: %p\n", func);
> return 0;
> }
> ```
>
> Before this patch applied, `func` argument for printf(3) points PLT:
>
> ```
> % /somewhere/vax--netbsdelf-gcc -S -fPIC -O2 main.c
> % /usr/local/vax--netbsdelf/bin/as -pic main.s -o main.o
> % readelf -r main.o
>
> Relocation section '.rela.text.startup' at offset 0x14c contains 3 entries:
> Offset Info Type Sym.Value Sym. Name + Addend
> 0000000d 00000504 R_VAX_PC32 00000000 .rodata.str1.1 + 0
> 00000007 0000080d R_VAX_PLT32 00000000 func + 0
> 00000014 00000a0d R_VAX_PLT32 00000000 printf + 0
> ```
>
> After this patch applied, it points GOT as done for other platforms:
>
> ```
> % /usr/local/vax--netbsdelf/bin/as -pic main.s -o main.o
> % readelf -r main.o
>
> Relocation section '.rela.text.startup' at offset 0x14c contains 3 entries:
> Offset Info Type Sym.Value Sym. Name + Addend
> 0000000d 00000504 R_VAX_PC32 00000000 .rodata.str1.1 + 0
> 00000007 00000807 R_VAX_GOT32 00000000 func + 0
> 00000014 00000a0d R_VAX_PLT32 00000000 printf + 0
> ```
Thank you for your submission and the bug report.
I've glanced over and while technically GAS might be doing an odd thing
here, the bug is clearly in the linker, which doesn't handle pointer
equality correctly.
Taking lazy binding and pointer equality into account here there are two
approaches at the high level either of which the linker can take:
1. In the presence of any PLT relocations create a lazy binding stub
(incorrectly called a PLT entry for the VAX target[*]) in the module
containing the ultimate symbol definition and refer all GOT symbol
references to it, ensuring pointer equality in the presence of lazy
binding.
2. In the presence of any GOT relocations refrain from creating a lazy
binding stub and refer all symbol references to the GOT entry in the
module containing the reference, ensuring pointer equality via
immediate binding.
Most platforms choose #1, in turn causing issues with protected symbols
(I'd have to dig out the details either from my memory or the Internet;
it's been discussed before), while traditional SVR4 MIPS targets choose
#2 at the price of using longer PIC code sequences even in absolute
executables (#1 has been an option for MIPS/Linux targets for a while
now).
The reason most targets choose #1 is they require a longer instruction
encoding for indirect memory references than they do for direct ones. For
example an indirect x86 CALL instruction requires an extra byte comparing
to a direct one. This isn't a problem for VAX code as long as PC-relative
addressing is used for direct memory references.
So I think we ought to choose #2, though of course at the expense of
losing lazy binding for such a symbol. More investigation might be
required though, and we'll need to make a bunch of testsuite cases (which
the VAX port regrettably has a poor choice of at the moment) to make sure
we don't break one case with a fix for another.
NB it would be good to have support for explicit relocations in assembly
too, but I guess it's unlikely to happen. It would avoid issues with GAS
such as one discussed.
Maciej
[*] A PLT entry is a piece of code that is always executed via a direct
call in the course of invoking a lazily bound function, whether the
binding has yet to be done or have been completed already. Conversely
a lazy binding stub is called indirectly and can at most executed
once, in the course of resolving the binding, and any later calls pass
control to the function called right away, which is exactly what
happens on VAX.
More information about the Binutils
mailing list