Bug 25179 - ld fails to resolve R_PPC_ADDR16_HA relocations in the .data section
Summary: ld fails to resolve R_PPC_ADDR16_HA relocations in the .data section
Status: RESOLVED WONTFIX
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.31
: P2 minor
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-11-09 16:17 UTC by Valery Ushakov
Modified: 2019-11-10 09:00 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Valery Ushakov 2019-11-09 16:17:05 UTC
On PowerPC ld fails to resolve R_PPC_ADDR16_HA relocations in the
.data section if the symbol was not previously referred in the .text
section.

$ cat ha.S
        .machine ppc
        .section .text.startup,"ax",@progbits
        .align 2
        .globl main
        .type main, @function
main:
        li      3, 0
        blr
#ifdef FIXME
        .long   memset          // mention symbol in the .text section
#endif

        .data
BUG:
        lis     0, memset@ha
        la      0, memset@l(0)

$ cc -DFIXME ha.S && ./a.out 
$ cc ha.S && ./a.out
Comment 1 Valery Ushakov 2019-11-09 16:22:28 UTC
I see this on NetBSD/macppc 8-stable with 

$ ld --version
GNU ld (NetBSD Binutils nb1) 2.27

and current with

$ ld --version
GNU ld (NetBSD Binutils nb1) 2.31.1

This used to work before I've upgraded from NetBSD 6-stable that (from
the look at the repository) had ld 2.21

The actual code is a small toy Forth I was playing with that has code
in the .data section
Comment 2 Valery Ushakov 2019-11-09 16:26:46 UTC
I managed to misedit the original submission and sent it too early it
seems.  Sorry.

$ cc ha.S && ./a.out 
./a.out: Unsupported relocation type 6 in non-PLT relocations

where the error message is printed by ld.so that refuses to run the
resulting binary.

$ objdump -DrR a.out | grep BUG -A5
01810ab8 <BUG>:
 1810ab8:       3c 00 00 00     lis     r0,0
                        1810aba: R_PPC_ADDR16_HA        memset
 1810abc:       38 00 00 00     li      r0,0
                        1810abe: R_PPC_ADDR16_LO        memset
Comment 3 Andreas Schwab 2019-11-09 17:17:04 UTC
FWIW, on ppc-linux the dynamic linker can handle these relocations.
Comment 4 Valery Ushakov 2019-11-09 18:18:09 UTC
Yes, ld.so can be changed to resolve them, but they can and should be
resolved at link time.  They are resolved at link time for text.  In
older versions they were always resolved for data too.  Now they are
resolved at link time for data only if text previously referred to the
same symbol (I've encountered this bug when os upgrade brought in the
newer binutils).  So I still think it's newly introduced bug in ld.
Comment 5 Andreas Schwab 2019-11-09 18:35:18 UTC
But then, it doesn't make much sense to put code in a non-executable section.
Comment 6 Valery Ushakov 2019-11-09 18:56:49 UTC
Change that .data to

  .section ".forth", "awx", @progbits

and the bug still happens.

(IIRC, PPC doesn't have separate "executable" permission in the MMU, so
"can read" implies "can execute" and so abusing read/write .data
happens to work)
Comment 7 Andreas Schwab 2019-11-09 20:04:01 UTC
Remove the writable bit.
Comment 8 Valery Ushakov 2019-11-09 20:31:38 UTC
Why?  I do know about W^X and everything, but why does the linker care?
Comment 9 Alan Modra 2019-11-10 09:00:23 UTC
This isn't a bug, it's a feature.  The linker has a choice when all the references in an executable to a function defined in a shared library are in read-write sections.  It can create a plt call stub as is done if there is a reference in a read-only section and define that function symbol on the plt call stub code, or it can emit dynamic relocations.  Both solutions result in a valid executable.  However, dynamic relocations have better runtime performance:  Calls to the function don't need to bounce through the plt call stub code.

Normally the only references in read-write sections are to initialise function pointers with an R_PPC_ADDR32 relocation.  Which is probably why your ld.so doesn't handle R_PPC_ADDR16*.

You could argue, and I'd agree, that the linker should not emit dynamic relocations that are not supported by ld.so.  It isn't a trivial task, but I'm happy to accept patches to do that for powerpc on netbsd.