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