On 19 July 2012 06:29, Ulrich Weigand Ulrich.Weigand@de.ibm.com wrote:
Michael Hope michael.hope@linaro.org wrote:
Hi Ramana, Ulrich. Could I have some help with an unexpected testsuite failure while backporting Carrot's adddi patch? testsuite/gcc.misc-tests/gcov-7.c builds and runs but aborts during leave() due to unexpected results.
The failing and working versions are on tcpanda02 as ~/gcov-7.exe and ~/gcov-7-ok.
OK, so I understand why ~/gcov-7.exe aborts. What actually happens is:
- The program runs through its test sucessfully, until the final exit.
- Within exit, gcov_exit processing is done.
- Within the gcov_exit subroutine __gcov_rewrite, a *tail* call to fseek is done (which is translated into a branch).
- This branch is supposed to go to a PLT stub, but instead goes haywire.
- Execution gets rerouted to somewhere in the main code.
- This is turn leads it to *again* check its proper exit conditions.
- This test now fails, leading to the abort.
In the good case ~/gcov-7-ok, the fseek PLT is called correctly. This (good case) looks like:
00008f70 <__gcov_rewrite>: 8f70: b538 push {r3, r4, r5, lr} 8f72: 4b0a ldr r3, [pc, #40] ; (8f9c <__gcov_rewrite+0x2c>) 8f74: 447b add r3, pc 8f76: 699a ldr r2, [r3, #24] 8f78: 2a00 cmp r2, #0 8f7a: dd0c ble.n 8f96 <__gcov_rewrite+0x26> 8f7c: 2400 movs r4, #0 8f7e: f04f 35ff mov.w r5, #4294967295 8f82: 4621 mov r1, r4 8f84: 6818 ldr r0, [r3, #0] 8f86: 4622 mov r2, r4 8f88: 605c str r4, [r3, #4] 8f8a: 609c str r4, [r3, #8] 8f8c: 619d str r5, [r3, #24] 8f8e: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} 8f92: f7ff bc1d b.w 87d0 <_init+0xc4> 8f96: f7ff ebd6 blx 8744 <_init+0x38>
00008718 <.plt>: 8718: e52de004 push {lr} ; (str lr, [sp, #-4]!) 871c: e59fe004 ldr lr, [pc, #4] ; 8728 <_init+0x1c> 8720: e08fe00e add lr, pc, lr 8724: e5bef008 ldr pc, [lr, #8]! 8728: 000099d8 ldrdeq r9, [r0], -r8 [snip] 87d0: 4778 bx pc 87d2: 46c0 nop ; (mov r8, r8) 87d4: e28fc600 add ip, pc, #0 87d8: e28cca09 add ip, ip, #36864 ; 0x9000 87dc: e5bcf964 ldr pc, [ip, #2404]! ; 0x964
Note how at 0x8f92 (Thumb mode!) we have a branch to 0x87d0, which is a Thumb stub that switches to ARM mode and calls into the main ARM PLT stub at 0x87d4.
In the bad case we have instead:
00008fdc <__gcov_rewrite>: 8fdc: b538 push {r3, r4, r5, lr} 8fde: 4b0a ldr r3, [pc, #40] ; (9008 <__gcov_rewrite+0x2c>) 8fe0: 447b add r3, pc 8fe2: 699a ldr r2, [r3, #24] 8fe4: 2a00 cmp r2, #0 8fe6: dd0c ble.n 9002 <__gcov_rewrite+0x26> 8fe8: 2400 movs r4, #0 8fea: f04f 35ff mov.w r5, #4294967295 8fee: 4621 mov r1, r4 8ff0: 6818 ldr r0, [r3, #0] 8ff2: 4622 mov r2, r4 8ff4: 605c str r4, [r3, #4] 8ff6: 609c str r4, [r3, #8] 8ff8: 619d str r5, [r3, #24] 8ffa: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} 8ffe: f000 bec7 b.w 9d90 <__fstat+0x10> 9002: f7ff ebd6 blx 87b0 <_init+0x38>
9d90: f7fe bd56 b.w 8840 <_init+0xc8>
00008784 <.plt>: 8784: e52de004 push {lr} ; (str lr, [sp, #-4]!) 8788: e59fe004 ldr lr, [pc, #4] ; 8794 <_init+0x1c> 878c: e08fe00e add lr, pc, lr 8790: e5bef008 ldr pc, [lr, #8]! [snip] 883c: 4778 bx pc 883e: 46c0 nop ; (mov r8, r8) 8840: e28fc600 add ip, pc, #0 8844: e28cca09 add ip, ip, #36864 ; 0x9000 8848: e5bcf94c ldr pc, [ip, #2380]! ; 0x94c
Here, the branch at 0x8ffe first goes to an extra stub at 0x9d90, which in turn branches directly to 0x8840 -- but this is the ARM version of the PLT stub, which now gets executed in Thumb mode!
The reason for this extra stub turns out to be a Cortex-A8 chip erratum: note how the b.w is a Thumb-2 4-byte instruction where its first two bytes are in a different page than its last two?
Such instructions are apparently not executed correctly if the branch goes to a target in the first of those pages. The linker therefore has code to check for this case, and insert an extra branch stub to compensate for this problem. When adding this extra stub, in the special case that the target was a PLT stub, the code forgot to check whether we need to also compensate for Thumb mode.
This bug actually was fixed by Richard Sandiford here: http://cygwin.com/ml/binutils/2011-04/msg00177.html
The fix got included into mainline here:
2011-05-06 Richard Sandiford richard.sandiford@linaro.org
* elf32-arm.c (cortex_a8_erratum_scan): If the stub is a Thumb branch to a PLT entry, redirect it to the PLT's Thumb entry point.
binutils 2.21 still has the bug, but binutils 2.22 is fixed.
Good, that's what I expected. Adding a --tool_opts '-Wl,-no-fix-cortex-a8' makes the test pass.
Therefore I don't understand this:
- The fault persists with binutils 2.22
Did you perform the final link step creating the gcov-7.exe with the linker from binutils 2.22 ?
I must have missed the collect-ld wrapper. Changing the absolute path to the new temporary binutils lets the test pass.
We have an explanation for the fault. I don't know why I can't reproduce it from the command line but will have to live with that.
-- Michael