https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61577

--- Comment #193 from dave.anglin at bell dot net ---
On 2020-02-21 7:36 p.m., peter.bisroev at groundlabs dot com wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61577
>
> --- Comment #192 from Peter Bisroev <peter.bisroev at groundlabs dot com> ---
> (In reply to dave.anglin from comment #191)
>> On 2020-02-19 9:50 p.m., peter.bisroev at groundlabs dot com wrote:
>> The problem seems to be that HP ld doesn't handle the PCREL21B relocation
>> correctly when it refers
>> to a weak function (i.e., it doesn't direct the call through the PLT).  At
>> the same time, weak references
>> don't seem to work with aCC.
>>
>> As far as I can tell, the PCREL21B is generated by gas in
>> gas/config/tc-ia64.c at line 5919.  You could try
>> changing it to PCREL21BI to see if that helps (run binutils testsuite before
>> installing) but the change doesn't
>> seem correct.  We might need to generate a 32-bit branch to weak functions
>> in gcc.
> Hi Dave, thanks for the hint! I have patched by binutils 2.32 as shown in the
> diff below.
> ------------------------------
> *** ./gas/config/tc-ia64.c.orig Fri Feb 21 23:52:59 2020
> --- ./gas/config/tc-ia64.c      Fri Feb 21 23:54:04 2020
> ***************
> *** 5919,5925 ****
>           else if (opnd == IA64_OPND_TGT25b)
>             fix->code = BFD_RELOC_IA64_PCREL21M;
>           else if (opnd == IA64_OPND_TGT25c)
> !           fix->code = BFD_RELOC_IA64_PCREL21B;
>           else if (opnd == IA64_OPND_TGT64)
>             fix->code = BFD_RELOC_IA64_PCREL60B;
>           else
> --- 5919,5925 ----
>           else if (opnd == IA64_OPND_TGT25b)
>             fix->code = BFD_RELOC_IA64_PCREL21M;
>           else if (opnd == IA64_OPND_TGT25c)
> !           fix->code = BFD_RELOC_IA64_PCREL21BI;
>           else if (opnd == IA64_OPND_TGT64)
>             fix->code = BFD_RELOC_IA64_PCREL60B;
>           else
> ------------------------------
>
> After recompiling binutils gas failed only two more unit tests than before:
> ------------------------------
> FAIL: ia64 tls
> FAIL: ia64 relocations
> ------------------------------
> After looking at both of these I guess it is expected as both of them expect
> PCREL21B instead of PCREL21BI.
>
> I have then attempted to recompile gcc 4.7.4 with this patched gas.
> Unfortunately that fails during linking when xgcc tries to build
> hpux64/libgcc_s.so.0.tmp in 64bit mode during stage 1. An example of an error
> is:
> ------------------------------
> ld: Unsatisfied symbol"calloc" in file "emutls_s.o": Expect to be defined in
> the load module.
> ------------------------------
>
> Taking a quick look at emutls_s.o I can see the expected reallocation
> ------------------------------
> $ readelf -r ./ia64-hp-hpux11.31/hpux64/libgcc/emutls_s.o | grep calloc
> 0000000004d2  002200000079 R_IA64_PCREL21BI  0000000000000000 calloc + 0
> ------------------------------
>
> But I have not dug dipper as to why the HP linker is unhappy there. Please let
> me know if you want me to do so.
This was expected.  R_IA64_PCREL21BI is only supposed to be used for local
symbols.
This test confirms it.

Changing gas isn't going to help.
>
>> It would be useful to find out why weak doesn't work with aCC.
> I wanted to see if there is some offical docs on this from HP.
>
> Going through aCC's programmers guide
> (https://support.hpe.com/hpesc/public/docDisplay?docLocale=en_US&docId=emr_na-c05054285)
> for my version of aCC ("HP C/aC++ B3910B A.06.29 [Oct 18 2016]", "as: HP
> Itanium Assembler B.11.31 (HP-UX/itanium)", "ld: 92453-07 linker ld HP
> Itanium(R) B.12.65  IPF/IPF"). I cannot find anything relevant to 'weak' in
> section 3, or generally in that reference guide.
>
> "Intel(R) Itanium(R) Architecture Assembly Language Reference Guide"
> (https://software.intel.com/sites/default/files/m/d/4/1/d/8/asm_lan.pdf) does
> mention weak symbols. This is also the same syntax that HP's as seems to
> accept.
>
> However in "HP-UX Linker and Libraries User Guide"
> (https://support.hpe.com/hpesc/public/docDisplay?docLocale=en_US&docId=a00055697en_us)
> on page 59, for nm, it states:
> ------------------------------
> Distinguish between weak and global symbols by appending * to the key letterof
> weak symbols. 
> ------------------------------
>
> So it looks like HP's as and ld should support weak symbols so I have decided
> to test it.
>
> ------------------------------
> // main.cc
>
> extern "C" {
>     void hello() __attribute__ ((weak));
> }
>
> int main() {
>     hello();
>     return 0;
> }
> ------------------------------
>
> ------------------------------
> // hello.s
> //   Adapted from "Hello World" Function Without
> //   Unwind Directives from Intel Itanium Architecture
> //   Assembly Language Reference Guide.
>
> .section .rdata, "a", "progbits"
> .align 8
> .STRING1:
> stringz "Hello World!!!\n"
>
>
> .text
> .global hello
> .proc hello
> hello: alloc loc2 = ar.pfs, 0, 4, 1, 0
> mov loc3 = sp
> mov loc1 = b0
> addl out0 = @ltoff(.STRING1), gp
> ;;
> ld8 out0 = [out0]
> mov loc0 = gp
> br.call.sptk.many b0 = printf
> ;;
> mov gp = loc0
> mov ar.pfs = loc2
> mov b0 = loc1
> mov sp = loc3
> br.ret.sptk.many b0
> .endp hello
>
> .weak printf
> .type printf, @function
> ------------------------------
>
> ------------------------------
> $ aCC +w -g0 +O0 +d -c -o main.o main.cc
> $ aCC +w -g0 +O0 +d -S -o main.s main.cc
I presume that if you compile main.cc with g++, hello() becomes weak.  You
could test with
a second instance of hello.
> $ as -o hello.o hello.s
> $ aCC +w -g0 +O0 +d -o hello main.o hello.o
> ------------------------------
>
> Now if I dump hello.o I get printf as a weak symbol as expected:
> ------------------------------
> $ readelf -s -r hello.o 
>
> Relocation section '.rela.text' at offset 0xa0 contains 2 entries:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000010  00000232 R_IA64_LTOFF22    00000000   .rdata + 0
> 00000020  00000449 R_IA64_PCREL21B   00000000   printf + 0
>
> Symbol table '.symtab' contains 5 entries:
>    Num:    Value  Size Type    Bind   Vis      Ndx Name
>      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
>      1: 00000000     0 FILE    LOCAL  DEFAULT  ABS hello.s
>      2: 00000000     0 SECTION LOCAL  DEFAULT    1 .rdata
>      3: 00000000    80 FUNC    GLOBAL DEFAULT    2 hello
>      4: 00000000     0 FUNC    WEAK   DEFAULT  UND printf
> ------------------------------
>
> Now the same for main.o, but that that shows that 'hello' is a global symbol
> instead of weak as expected.
> ------------------------------
> $ readelf -s -r main.o
>
> Relocation section '.rela.IA_64.unwind' at offset 0x40 contains 3 entries:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000000  0000045c R_IA64_SEGREL32MS 00000000   .text + 0
> 00000004  0000045c R_IA64_SEGREL32MS 00000000   .text + 70
> 00000008  0000095c R_IA64_SEGREL32MS 00000000   .IA_64.unwind_info + 4
>
> Relocation section '.rela.IA_64.unwind_info' at offset 0x7c contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000000  00000a5c R_IA64_SEGREL32MS 00000000   .HP.opt_annot + 0
>
> Relocation section '.rela.text' at offset 0x100 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000022  00000b49 R_IA64_PCREL21B   00000000   hello + 0
>
> Relocation section '.rela.debug_info' at offset 0x538 contains 6 entries:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000006  00000564 R_IA64_SECREL32MS 00000000   .debug_abbrev + 0
> 0000000c  00000264 R_IA64_SECREL32MS 00000000   .debug_line + 0
> 00000010  00000364 R_IA64_SECREL32MS 00000000   .debug_actual + 0
> 00000014  00000764 R_IA64_SECREL32MS 00000000   .debug_macinfo + 0
> 0000038d  00000424 R_IA64_DIR32MSB   00000000   .text + 0
> 00000391  00000424 R_IA64_DIR32MSB   00000000   .text + 70
>
> Relocation section '.rela.debug_procs_info' at offset 0x5d4 contains 5 
> entries:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 00000006  00000864 R_IA64_SECREL32MS 00000000   .debug_procs_abbrev + 0
> 0000000c  00000264 R_IA64_SECREL32MS 00000000   .debug_line + 0
> 00000010  00000364 R_IA64_SECREL32MS 00000000   .debug_actual + 0
> 00000049  00000424 R_IA64_DIR32MSB   00000000   .text + 0
> 0000004d  00000424 R_IA64_DIR32MSB   00000000   .text + 70
>
> Relocation section '.rela.debug_line' at offset 0x680 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 0000002b  00000424 R_IA64_DIR32MSB   00000000   .text + 0
>
> Relocation section '.rela.debug_actual' at offset 0x6c0 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 0000001b  00000424 R_IA64_DIR32MSB   00000000   .text + 0
>
> Symbol table '.symtab' contains 13 entries:
>    Num:    Value  Size Type    Bind   Vis      Ndx Name
>      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
>      1: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.cc
>      2: 00000000     0 SECTION LOCAL  DEFAULT   14 .debug_line
>      3: 00000000     0 SECTION LOCAL  DEFAULT   16 .debug_actual
>      4: 00000000     0 SECTION LOCAL  DEFAULT    5 .text
>      5: 00000000     0 SECTION LOCAL  DEFAULT    8 .debug_abbrev
>      6: 00000000     0 SECTION LOCAL  DEFAULT   18 .objdebug_file
>      7: 00000000     0 SECTION LOCAL  DEFAULT   19 .debug_macinfo
>      8: 00000000     0 SECTION LOCAL  DEFAULT   13 .debug_procs_abbrev
>      9: 00000000     0 SECTION LOCAL  DEFAULT    3 .IA_64.unwind_info
>     10: 00000000     0 SECTION LOCAL  DEFAULT    7 .HP.opt_annot
>     11: 00000000     0 FUNC    GLOBAL DEFAULT  UND hello
>     12: 00000000   112 FUNC    GLOBAL DEFAULT    5 main
> ------------------------------
>
> Looking at main.s there is:
> ------------------------------
> ...
>         .type   hello,@function
>         .global hello
> ...
>         br.call.dptk.many rp = hello#
> ------------------------------
> So it looks like even though aCC accepted weak attribute it generated a global
> symbol.
>
> Now some interesting dumps from final executable linked by HP's ld:
> ------------------------------
> $ readelf -s hello
>
> Symbol table '.dynsym' contains 32 entries:
>    Num:    Value  Size Type    Bind   Vis      Ndx Name
> ...
>     10: 10252e40     0 FUNC    WEAK   DEFAULT  UND printf
>     25: 04000970    80 FUNC    GLOBAL DEFAULT   15 hello
> ...
>     45: 10252e40     0 FUNC    WEAK   DEFAULT  UND printf
>     60: 04000970    80 FUNC    GLOBAL DEFAULT   15 hello
> ...
>
> $ objdump --disassemble=main hello
> ...
> Disassembly of section .text:
>
> 040008e0 <main>:
>  40008e0:       03 08 0d 06 80 05       [MII]       alloc r33=ar.pfs,3,3,0
>  40008e6:       00 00 00 02 00 00                   nop.i 0x0;;
>  40008ec:       04 08 00 84                         mov r32=r1;;
>  40008f0:       01 00 00 00 01 00       [MII]       nop.m 0x0
>  40008f6:       20 02 00 62 00 00                   mov r34=b0
>  40008fc:       00 00 04 00                         nop.i 0x0;;
>  4000900:       19 00 00 00 01 00       [MMB]       nop.m 0x0
>  4000906:       00 00 00 02 00 00                   nop.m 0x0
>  400090c:       78 00 00 52                         br.call.dptk.many
> b0=4000970 <hello>;;
>  4000910:       03 08 00 40 00 21       [MII]       mov r1=r32
>  4000916:       00 00 00 02 00 20                   nop.i 0x0;;
>  400091c:       01 00 00 90                         mov r9=0;;
>  4000920:       03 40 00 12 00 21       [MII]       mov r8=r9
>  4000926:       00 00 00 02 00 00                   nop.i 0x0;;
>  400092c:       20 0a 00 07                         mov b0=r34;;
>  4000930:       02 00 00 00 01 00       [MII]       nop.m 0x0
>  4000936:       00 08 01 55 00 00                   mov.i ar.pfs=r33;;
>  400093c:       00 00 04 00                         nop.i 0x0
>  4000940:       19 00 00 00 01 00       [MMB]       nop.m 0x0
>  4000946:       00 00 00 02 00 80                   nop.m 0x0
>  400094c:       08 00 84 02                         br.ret.dptk.many b0;;
>
> $ objdump --disassemble=hello hello
> ...
> Disassembly of section .text:
>
> 04000970 <hello>:
>  4000970:       08 10 15 08 80 05       [MMI]       alloc r34=ar.pfs,5,4,0
>  4000976:       30 02 30 00 42 20                   mov r35=r12
>  400097c:       04 00 c4 00                         mov r33=b0
>  4000980:       0a 20 e1 fb ff 27       [MMI]       addl r36=-8,r1;;
>  4000986:       40 02 90 30 20 00                   ld8 r36=[r36]
>  400098c:       04 08 00 84                         mov r32=r1
>  4000990:       17 00 f2 ff 3f 16       [BBB]       br.call.sptk.many
> b0=4000950 <.stub>
>  4000996:       00 00 00 00 10 00                   nop.b 0x0
>  400099c:       00 00 00 20                         nop.b 0x0;;
>  40009a0:       00 08 00 40 00 21       [MII]       mov r1=r32
>  40009a6:       00 10 01 55 00 00                   mov.i ar.pfs=r34
>  40009ac:       10 0a 00 07                         mov b0=r33
>  40009b0:       12 60 00 46 00 21       [MBB]       mov r12=r35
>  40009b6:       40 04 00 42 00 00                   br.ret.sptk.many b0
>  40009bc:       00 00 00 20                         nop.b 0x0
>
> $ objdump --disassemble=.stub hello
> ...
> Disassembly of section .text:
>
> 04000950 <.stub>:
>  4000950:       0b 78 a0 fb ff 27       [MMI]       addl r15=-24,r1;;
>  4000956:       00 41 3c 30 28 c0                   ld8 r16=[r15],8
>  400095c:       01 08 00 84                         mov r14=r1;;
>  4000960:       11 08 00 1e 18 10       [MIB]       ld8 r1=[r15]
>  4000966:       60 80 04 80 03 00                   mov b6=r16
>  400096c:       60 00 80 00                         br.few b6;;
>
> $ readelf -r hello
>
> Relocation section '.rela.plt' at offset 0x7e4 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name + Addend
> 40010000  00000a80 R_IA64_IPLTMSB    10252e40   printf + 0
> ------------------------------
>
> And that R_IA64_IPLTMSB relocation seems to be expected since printf is in
> shared lib. So I guess we need to figure out how to force aCC to actually
> respect __attribute__((weak)).
>
> What do you think?
It is clear aCC doesn't support although I think HP as and ld do with some
caveats.  HP's weak
support evolved from secondary definition symbols (sdef).  This was never well
documented and
the use we make of these symbols on 32-bit pa came from looking at HP's linker
code.

I'm thinking that the call to printf goes through PLT because it is resolved in
a shared library.

The R_IA64_PCREL21B relocation works except for code size issues.  HP ld
doesn't remove unnecessary
weak instances and for some reason it doesn't do calls to weak functions
through the PLT when they
aren't resolved in a shared library.

So, I think we either need to use a long branch (brl) to weak functions or we
need to change the define
of MAKE_DECL_ONE_ONLY to avoid the use of weak.  We can try replacing weak
functions with comdat
functions, etc.  Currently, we have

#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)

The latter is probably the better solution as it will result in smaller code,
but it's trickier.  I'm not sure about
using brl in the 32-bit hpux runtime.

Dave

Reply via email to