I'm seeing runtime failures (segfaults) when running the g++ tests g++.dg/ipa/pr61160-2.C and g++.dg/ipa/pr61160-3 on arm-none-linux-gnueabi with -mthumb. I think this is a linker problem, or possibly a bad relocation being emitted by the assembler. For pr61160-2.C, GCC is producing this assembly output: main: .fnstart .LFB12: push {lr} ldr r3, .L17 sub sp, sp, #28 str r3, [sp, #4] add r3, r3, #16 str r3, [sp, #8] mov r3, #0 ldr r2, .L17+4 add r0, sp, #8 str r3, [sp, #12] str r2, [sp, #16] str r3, [sp, #20] bl _ZThn4_N8CExample9MixinFuncEiPv.artificial_thunk.1 mov r0, #0 add sp, sp, #28 @ sp needed pop {pc} .L18: .align 2 .L17: .word _ZTV8CExample+8 .word 48879 .cantunwind .fnend .size main, .-main Disassembling the .o file: 00000000 <main>: 0: b500 push {lr} 2: 4b08 ldr r3, [pc, #32] ; (24 <main+0x24>) 4: b087 sub sp, #28 6: 9301 str r3, [sp, #4] 8: 3310 adds r3, #16 a: 9302 str r3, [sp, #8] c: 2300 movs r3, #0 e: 4a06 ldr r2, [pc, #24] ; (28 <main+0x28>) 10: a802 add r0, sp, #8 12: 9303 str r3, [sp, #12] 14: 9204 str r2, [sp, #16] 16: 9305 str r3, [sp, #20] 18: f000 f808 bl 28 <main+0x28> 18: R_ARM_THM_CALL _ZThn4_N8CExample9MixinFuncEiPv.artificial_thunk.1 1c: 2000 movs r0, #0 1e: b007 add sp, #28 20: bd00 pop {pc} 22: 46c0 nop ; (mov r8, r8) 24: 00000008 .word 0x00000008 24: R_ARM_ABS32 _ZTV8CExample 28: 0000beef .word 0x0000beef And disassembling the .exe: 00010610 <main>: 10610: b500 push {lr} 10612: 4b08 ldr r3, [pc, #32] ; (10634 <main+0x24>) 10614: b087 sub sp, #28 10616: 9301 str r3, [sp, #4] 10618: 3310 adds r3, #16 1061a: 9302 str r3, [sp, #8] 1061c: 2300 movs r3, #0 1061e: 4a06 ldr r2, [pc, #24] ; (10638 <main+0x28>) 10620: a802 add r0, sp, #8 10622: 9303 str r3, [sp, #12] 10624: 9204 str r2, [sp, #16] 10626: 9305 str r3, [sp, #20] 10628: f000 f90c bl 10844 <_ZTS5CBase> 1062c: 2000 movs r0, #0 1062e: b007 add sp, #28 10630: bd00 pop {pc} 10632: 46c0 nop ; (mov r8, r8) 10634: 00010898 .word 0x00010898 10638: 0000beef .word 0x0000beef So the original "bl _ZThn4_N8CExample9MixinFuncEiPv.artificial_thunk.1" has been turned into "bl 10844 <_ZTS5CBase>", which is data, not code. :-( Problem was confirmed with a fresh build with both binutils and gcc from mainline head today.
Hi Sandra, I am unable to reproduce this bug. Does it still exist ? If so, please could you upload a .o file and the linker command line used so that I can have another go at reproducing the problem. Cheers Nick
Created attachment 8175 [details] tarred -save-temps output for pr61160-2.C Yes, the problem still reproduces exactly as previously described. My toolchain is configured with host=i686-pc-linux-gnu and target=arm-none-linux-gnueabi. The attached tar file is the -save-temps output from the following command: arm-none-linux-gnueabi-g++ /scratch/sandra/arm-linux-fsf/src/gcc-mainline/gcc/testsuite/g++.dg/ipa/pr61160-2.C -std=gnu++98 -O3 --param ipa-cp-eval-threshold=1 -mthumb -o ./pr61160-2.exe -save-temps
Hi Sandra, Thanks - I can now reproduce the problem. Interestingly this turns out to be a gas bug, not a linker bug. The problem is that the relocation generated by gas for the call to ...artificial_thunk.1 is wrong. It has an offset of 0x14 built in to the relocation when in fact it should be 0. GAS is doing this because the ...artifical_thunk.1 symbol is a local symbol not a global symbol. You can see this for yourself by editing the pr61160-2.s file and adding the line: .global _ZThn4_N8CExample9MixinFuncEiPv.artificial_thunk.1 just after the function is declared. Assembling and linking this version of the pr61160-2.s file will result in a working binary. This is where I am currently stumped. I do not see why GAS should be treating a local function symbol any differently from a global function symbol. Unfortunately the weekend is here and I have to drop this for now. But I will pick up the case again next week. Cheers Nick
Created attachment 8182 [details] Proposed patch - avoids applying symbol value twice Hi Sandra, Please could you try out this patch and let me know if it works for you. Cheers Nick
My test results on mainline head are very "noisy" right now due to ubsan failures, but ignoring all those, it looks like the patch is good. I'm seeing no regressions, and that these tests now all pass: FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-3.C -std=gnu++11 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-3.C -std=gnu++14 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-3.C -std=gnu++98 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-4.C -std=gnu++11 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-4.C -std=gnu++14 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr60640-4.C -std=gnu++98 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-2.C -std=gnu++11 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-2.C -std=gnu++14 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-2.C -std=gnu++98 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-3.C -std=gnu++11 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-3.C -std=gnu++14 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/ipa/pr61160-3.C -std=gnu++98 execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/torture/covariant-1.C -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/torture/covariant-1.C -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/torture/pr45699.C -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL -> PASS: mthumb/g++.sum:g++.dg/torture/pr46287.C -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test
The master branch has been updated by Nick Clifton <nickc@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=93ef582debb0a179916965a882f4344223569219 commit 93ef582debb0a179916965a882f4344223569219 Author: Nick Clifton <nickc@redhat.com> Date: Thu Mar 12 15:58:37 2015 +0000 Fixes a problem generating relocs for thumb function calls to local symbols defined in other sections. PR gas/17444 * config/tc-arm.h (MD_APPLY_SYM_VALUE): Pass the current segment to arm_apply_sym_value. Update prototype. * config/tc-arm.c (arm_apply_sym_value): Add segment argument. Do not apply the value if the symbol is in a different segment to the current segment.
Patch applied.