https://sourceware.org/bugzilla/show_bug.cgi?id=20453
Bug ID: 20453 Summary: MIPS LA25 stub not bypassed in direct PIC-to-PIC jumps with incrementally linked code Product: binutils Version: 2.28 (HEAD) Status: UNCONFIRMED Severity: minor Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: ma...@linux-mips.org Target Milestone: --- Target: mips-*-* We have a special case in `mips_elf_relocation_needs_la25_stub' for direct jumps (and branches) between PIC functions which causes the LA25 stub to be bypassed under the principle that any need for $25 to be set up correctly shall be handled by code's originator: /* We specifically ignore branches and jumps from EF_PIC objects, where the onus is on the compiler or programmer to perform any necessary initialization of $25. Sometimes such initialization is unnecessary; for example, -mno-shared functions do not use the incoming value of $25, and may therefore be called directly. */ This works by checking the EF_MIPS_PIC flag of the incoming object file where the relocation associated with the jump comes from. This flag however is cleared for the outcoming object file in an incremental link which involves an incoming non-PIC object as well. Consequently when such an incrementally linked object file is used in the final link in place of the individual original object files the LA25 stub is not bypassed anymore where it would otherwise be, leading to different code produced from identical original objects and to a small run-time performance loss from the extraneous instructions executed. Additionally in the case where all direct jumps are PIC-to-PIC an LA25 stub would have not been produced if an incremental link wasn't done on the way, so the issue may cause a slight code size increase as well. This can be reproduced with these sources and steps: $ cat la25a.s .abicalls .global f1 .ent f1 f1: .set noreorder .cpload $25 .set reorder .option pic0 jal f2 .option pic2 jr $31 .end f1 .global f2 .ent f2 f2: jr $31 .end f2 $ cat la25b.s .abicalls .option pic0 .global __start .ent __start __start: jal f1 jal f2 .end __start $ as -32 -EB -o la25a.o la25a.s $ as -32 -EB -o la25b.o la25b.s $ ld -melf32btsmip -o la25 la25a.o la25b.o $ ld -melf32btsmip -r -o la25-r.o la25a.o la25b.o $ ld -melf32btsmip -o la25-r la25-r.o $ objdump -d la25 la25: file format elf32-tradbigmips Disassembly of section .text: 004000d0 <.pic.f2>: 4000d0: 3c190040 lui t9,0x40 4000d4: 08100043 j 40010c <f2> 4000d8: 2739010c addiu t9,t9,268 ... 004000e8 <.pic.f1>: 4000e8: 3c190040 lui t9,0x40 4000ec: 273900f0 addiu t9,t9,240 004000f0 <f1>: 4000f0: 3c1c0002 lui gp,0x2 4000f4: 279c8030 addiu gp,gp,-32720 4000f8: 0399e021 addu gp,gp,t9 4000fc: 0c100043 jal 40010c <f2> 400100: 00000000 nop 400104: 03e00008 jr ra 400108: 00000000 nop 0040010c <f2>: 40010c: 03e00008 jr ra 400110: 00000000 nop ... 00400120 <__start>: 400120: 0c10003a jal 4000e8 <.pic.f1> 400124: 00000000 nop 400128: 0c100034 jal 4000d0 <.pic.f2> 40012c: 00000000 nop $ objdump -d la25-r la25-r: file format elf32-tradbigmips Disassembly of section .text: 004000d0 <.pic.f2>: 4000d0: 3c190040 lui t9,0x40 4000d4: 08100043 j 40010c <f2> 4000d8: 2739010c addiu t9,t9,268 ... 004000e8 <.pic.f1>: 4000e8: 3c190040 lui t9,0x40 4000ec: 273900f0 addiu t9,t9,240 004000f0 <f1>: 4000f0: 3c1c0002 lui gp,0x2 4000f4: 279c8030 addiu gp,gp,-32720 4000f8: 0399e021 addu gp,gp,t9 4000fc: 0c100034 jal 4000d0 <.pic.f2> 400100: 00000000 nop 400104: 03e00008 jr ra 400108: 00000000 nop 0040010c <f2>: 40010c: 03e00008 jr ra 400110: 00000000 nop ... 00400120 <__start>: 400120: 0c10003a jal 4000e8 <.pic.f1> 400124: 00000000 nop 400128: 0c100034 jal 4000d0 <.pic.f2> 40012c: 00000000 nop $ diff -u la25 la25-r --- la25.dump 2016-08-09 13:45:33.435771000 +0100 +++ la25-r.dump 2016-08-09 13:45:40.734859000 +0100 @@ -1,5 +1,5 @@ -la25: file format elf32-tradbigmips +la25-r: file format elf32-tradbigmips Disassembly of section .text: @@ -18,7 +18,7 @@ 4000f0: 3c1c0002 lui gp,0x2 4000f4: 279c8030 addiu gp,gp,-32720 4000f8: 0399e021 addu gp,gp,t9 - 4000fc: 0c100043 jal 40010c <f2> + 4000fc: 0c100034 jal 4000d0 <.pic.f2> 400100: 00000000 nop 400104: 03e00008 jr ra 400108: 00000000 nop $ A potential way to fix this is to check for the STO_MIPS_PIC flag on the function symbol spanning the area containing the offending relocation, e.g. `f1' (vs `__start') in the example case above: $ readelf -s la25-r.o Symbol table '.symtab' contains 12 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 SECTION LOCAL DEFAULT 1 2: 00000000 0 SECTION LOCAL DEFAULT 2 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 5 5: 00000000 0 SECTION LOCAL DEFAULT 6 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 9 8: 00000000 0 OBJECT GLOBAL DEFAULT UND _gp_disp 9: 00000030 16 FUNC GLOBAL DEFAULT 3 __start 10: 0000001c 8 FUNC GLOBAL DEFAULT [MIPS PIC] 3 f2 11: 00000000 28 FUNC GLOBAL DEFAULT [MIPS PIC] 3 f1 $ This however might require scanning the symbol table every time such a problematic relocation is encountered and consequently be computationally too complex, or require setting up additional data structures to avoid this complexity and therefore take too much processing time elsewhere and/or memory to be justified for such a corner case. Marking as minor as this is a missed optimisation only and not a code correctness issue. -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils