|
From: Kacper K. <kac...@gm...> - 2017-08-31 14:19:32
|
Hi! By default valgrind is not selectable in menuconfig for IMX6 platform when cross compiling for Openwrt, but this platform is based on ARM Cortex A9 core which is implementing ARMv7 architecture. This architecture is supported by valgrind, so I made little changes in Makefile of valgrind package to make the package selectable from menuconfig and compilable. I'm using GCC-5.3 and uClibc-0.9.33.2 (can't proceed to musl for now because it is very expensive). The problem is that valgrind is not working properly even for /bin/true: > valgrind --leak-check=yes /bin/true Output: ==19124== Memcheck, a memory error detector ==19124== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==19124== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==19124== Command: /bin/true ==19124== ==19124== Invalid read of size 4 ==19124== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so) ==19124== Address 0x7df01864 is on thread 1's stack ==19124== 20 bytes below stack pointer ==19124== ==19124== Invalid read of size 4 ==19124== at 0x48B8CD4: ??? (in /lib/libuClibc-0.9.33.2.so) ==19124== Address 0x7df01a5c is on thread 1's stack ==19124== 20 bytes below stack pointer ==19124== ==19124== Invalid read of size 4 ==19124== at 0x48B8AC0: ??? (in /lib/libuClibc-0.9.33.2.so) ==19124== Address 0x7df01a04 is on thread 1's stack ==19124== 20 bytes below stack pointer ==19124== ==19124== Invalid read of size 4 ==19124== at 0x4000E54: ??? (in /lib/ld-uClibc-0.9.33.2.so) ==19124== Address 0x7df019f4 is on thread 1's stack ==19124== 20 bytes below stack pointer ==19124== ==19124== ==19124== HEAP SUMMARY: ==19124== in use at exit: 0 bytes in 0 blocks ==19124== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==19124== ==19124== All heap blocks were freed -- no leaks are possible ==19124== ==19124== For counts of detected and suppressed errors, rerun with: -v ==19124== ERROR SUMMARY: 64 errors from 4 contexts (suppressed: 0 from 0) I found that "-D__UCLIBC__" flag should be applied when compiling valgrind, but that didn't help, the output is the same. |
|
From: John R. <jr...@bi...> - 2017-08-31 15:28:09
|
> By default valgrind is not selectable in menuconfig for IMX6 platform when cross compiling for Openwrt, but this platform is based on ARM Cortex A9 core which is implementing ARMv7 architecture. This architecture is supported by valgrind, so I made little changes in Makefile of valgrind package to > make the package selectable from menuconfig and compilable. > I'm using GCC-5.3 and uClibc-0.9.33.2 (can't proceed to musl for now because it is very expensive). > The problem is that valgrind is not working properly even for |/bin/true|: > > | > valgrind --leak-check=yes /bin/true | > > |Output: > | > ==19124== Memcheck, a memory error detector > ==19124== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. > ==19124== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info > ==19124== Command: /bin/true > ==19124== > ==19124== Invalid read of size 4 > ==19124== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so <http://ld-uClibc-0.9.33.2.so>) > ==19124== Address 0x7df01864 is on thread 1's stack > ==19124== 20 bytes below stack pointer How do you know that memcheck's complaint is incorrect? At times in the past messages such as these were valid complaints, particularly for uClibc and some compilers for ARM and MIPS. Find some way to look at register values and instruction stream in the context of the error. If the valgrind gdb server is installed and working, then one good way is to invoke via valgrind --vgdb-error=0 /bin/true and follow the directions. (gdb) continue ## to get started Then at the point of complaint by memcheck: (gdb) info reg ## values of all registers (gdb) x/9i $pc-4*4 ## probable instruction stream It would also help to install the debuginfo package for uClibc (compiled with -g) so that you could get a meaningful backtrace via the "bt" command to gdb, but that might be a lot of work. Please tell us the target operating system version ("uname -a"), and which ELF program INTERP (readelf --segments /bin/true | grep interpreter). -- |
|
From: John R. <jr...@bi...> - 2017-09-02 12:14:54
|
From valgrind(memcheck): > ==2418== Invalid read of size 4 > ==2418== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so) > ==2418== Address 0x7d87a664 is on thread 1's stack > ==2418== 20 bytes below stack pointer > Program received signal SIGTRAP, Trace/breakpoint trap. > 0x040054ec in ?? () From the vgdb server: > (gdb) info reg > r10 0x7d87aa48 2106042952 > r11 0x7d87a674 2106041972 > r12 0x7d87a678 2106041976 > sp 0x7d87a678 0x7d87a678 > pc 0x40054ec 0x40054ec So the description "20 bytes below stack pointer" is correct, because ($sp - 0x7d87a664) = (0x7d87a678 - 0x7d87a664) = 0x14 = 20. What was the instruction stream? Where is the output from the next command that was requested in my earlier message: (gdb) x/9i $pc-4*4 If the instruction at 0x040054ec is a 'ldr' fetch from memory which uses address -996(r10), -16(r11), -20(r12), or -20(sp), then that is the culprit, and it is a compiler error (or a logic error if indexing an array with an index less than zero, or a programmer error if the code was inlined assembly language.) Also, were you able to install the debuginfo symbols for /lib/ld-uClibc-0.9.33.2.so ? (or, not strip the symbols from ld-uClibc ?) It would be nice to correlate the instruction stream with the source code: (gdb) bt which should show function names, source file names, and line numbers. This would make it easier to confirm the exact cause of the error. -- |
|
From: Kacper K. <kac...@gm...> - 2017-09-05 09:09:33
|
Ok. Sorry, I overlooked it
GDB:
1.
(gdb) info reg
r0 0x4007148 67137864
r1 0x0 0
r2 0x49ba000 77307904
r3 0x49bd90c 77322508
r4 0x4015f78 67198840
r5 0x4006054 67133524
r6 0xa 10
r7 0x4006ac0 67136192
r8 0x24 36
r9 0x401602c 67199020
r10 0x7dbb6a48 2109434440
r11 0x7dbb6674 2109433460
r12 0x7dbb6678 2109433464
sp 0x7dbb6678 0x7dbb6678
lr 0x40054ec 67130604
pc 0x40054ec 0x40054ec
cpsr 0x20000010 536870928
(gdb) x/9i $pc-4*4
0x40054dc: beq 0x40054ec
0x40054e0: ldr r2, [r7]
0x40054e4: add r3, r3, r2
0x40054e8: blx r3
=> 0x40054ec: mov r0, r7
0x40054f0: bl 0x4001440
0x40054f4: b 0x40054b8
0x40054f8: ldr r1, [r6, #88] ; 0x58
0x40054fc: sub sp, sp, #16
2.
(gdb) info reg
r0 0x7dbb6d21 2109435169
r1 0x4a2b000 77770752
r2 0x10680 67200
r3 0x4a2f494 77788308
r4 0x7dbb6d03 2109435139
r5 0x104d8 66776
r6 0x7dbb6a60 2109434464
r7 0x8 8
r8 0x0 0
r9 0x0 0
r10 0x4015f78 67198840
r11 0x7dbb6a4c 2109434444
r12 0x7dbb6a50 2109434448
sp 0x7dbb6a50 0x7dbb6a50
lr 0x4a15cd4 77683924
pc 0x4a15cd4 0x4a15cd4
cpsr 0x20000010 536870928
(gdb) x/9i $pc-4*4
0x4a15cc4: add r3, pc, r3
0x4a15cc8: str r2, [r3]
0x4a15ccc: beq 0x4a15cd4
0x4a15cd0: blx r5
=> 0x4a15cd4: bl 0x49ddf00
0x4a15cd8: ldr r3, [pc, #288] ; 0x4a15e00
0x4a15cdc: ldr r2, [sp]
0x4a15ce0: ldr r3, [r2, r3]
0x4a15ce4: cmp r3, #0
3.
(gdb) info reg
r0 0x207d8 133080
r1 0x1 1
r2 0x0 0
r3 0x10680 67200
r4 0x4a2b000 77770752
r5 0x0 0
r6 0x7dbb6a60 2109434464
r7 0x4a2b400 77771776
r8 0x0 0
r9 0x0 0
r10 0x4015f78 67198840
r11 0x7dbb6a2c 2109434412
r12 0x7dbb6a30 2109434416
sp 0x7dbb6a30 0x7dbb6a30
lr 0x4a15ac0 77683392
pc 0x4a15ac0 0x4a15ac0
cpsr 0x20000010 536870928
(gdb) x/9i $pc-4*4
0x4a15ab0: ldr r3, [r3]
0x4a15ab4: cmp r3, #0
0x4a15ab8: beq 0x4a15ac0
0x4a15abc: blx r3
=> 0x4a15ac0: ldr r3, [pc, #24] ; 0x4a15ae0
0x4a15ac4: add r3, pc, r3
0x4a15ac8: ldr r3, [r3]
0x4a15acc: cmp r3, #0
0x4a15ad0: popeq {r4, pc}
4.
(gdb) info reg
r0 0x482778c 75659148
r1 0x1 1
r2 0x4817000 75591680
r3 0x4817678 75593336
r4 0x4006178 67133816
r5 0x0 0
r6 0x4016034 67199028
r7 0x401602c 67199020
r8 0x0 0
r9 0x0 0
r10 0x4015f78 67198840
r11 0x7dbb6a1c 2109434396
r12 0x7dbb6a20 2109434400
sp 0x7dbb6a20 0x7dbb6a20
lr 0x4000e54 67112532
pc 0x4000e54 0x4000e54
cpsr 0x20000010 536870928
(gdb) x/9i $pc-4*4
0x4000e44: beq 0x4000e54
0x4000e48: ldr r2, [r4]
0x4000e4c: add r3, r3, r2
0x4000e50: blx r3
=> 0x4000e54: add r5, r5, #1
0x4000e58: b 0x4000e0c
0x4000e5c: pop {r4, r5, r6, r7, r11, pc}
0x4000e60: andeq r5, r1, r8, lsr #4
0x4000e64: andeq r5, r1, r12, lsl r2
Corresponding GDB server messages:
1.
==4996== Invalid read of size 4
==4996== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so)
==4996== Address 0x7dbb6664 is on thread 1's stack
==4996== 20 bytes below stack pointer
2.
==4996== Invalid read of size 4
==4996== at 0x4A15CD4: ??? (in /lib/libuClibc-0.9.33.2.so)
==4996== Address 0x7dbb6a3c is on thread 1's stack
==4996== 20 bytes below stack pointer
3.
==4996== Invalid read of size 4
==4996== at 0x4A15AC0: ??? (in /lib/libuClibc-0.9.33.2.so)
==4996== Address 0x7dbb6a1c is on thread 1's stack
==4996== 20 bytes below stack pointer
4.
==4996== Invalid read of size 4
==4996== at 0x4000E54: ??? (in /lib/ld-uClibc-0.9.33.2.so)
==4996== Address 0x7dbb6a0c is on thread 1's stack
==4996== 20 bytes below stack pointer
uname -a:
Linux XXX 3.18.23 #6 SMP Tue Jul 11 16:35:20 CEST 2017 armv7l GNU/Linux
readelf --segments /bin/true | grep interpreter:
[Requesting program interpreter: /lib/ld-uClibc.so.0]
Changing uClibc package to compile with debugging symbols can result in
rebuilding whole buildroot and reflashing my embedded device. It could last
a few days, so I think that it will be last step I will take if any of
solutions won't work.
2017-09-02 14:14 GMT+02:00 John Reiser <jr...@bi...>:
> From valgrind(memcheck):
>
>> ==2418== Invalid read of size 4
>> ==2418== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so)
>> ==2418== Address 0x7d87a664 is on thread 1's stack
>> ==2418== 20 bytes below stack pointer
>>
>
> Program received signal SIGTRAP, Trace/breakpoint trap.
>> 0x040054ec in ?? ()
>>
>
> From the vgdb server:
>
>> (gdb) info reg
>>
>
> r10 0x7d87aa48 2106042952
>> r11 0x7d87a674 2106041972
>> r12 0x7d87a678 2106041976
>> sp 0x7d87a678 0x7d87a678
>>
>
> pc 0x40054ec 0x40054ec
>>
>
> So the description "20 bytes below stack pointer" is correct,
> because ($sp - 0x7d87a664) = (0x7d87a678 - 0x7d87a664) = 0x14 = 20.
>
> What was the instruction stream? Where is the output from
> the next command that was requested in my earlier message:
> (gdb) x/9i $pc-4*4
>
> If the instruction at 0x040054ec is a 'ldr' fetch from memory
> which uses address -996(r10), -16(r11), -20(r12), or -20(sp),
> then that is the culprit, and it is a compiler error (or a logic
> error if indexing an array with an index less than zero,
> or a programmer error if the code was inlined assembly language.)
>
> Also, were you able to install the debuginfo symbols for /lib/
> ld-uClibc-0.9.33.2.so ?
> (or, not strip the symbols from ld-uClibc ?)
> It would be nice to correlate the instruction stream with the source code:
> (gdb) bt
> which should show function names, source file names, and line numbers.
> This would make it easier to confirm the exact cause of the error.
>
>
> --
>
> ------------------------------------------------------------
> ------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Valgrind-users mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-users
>
|
|
From: John R. <jr...@bi...> - 2017-09-05 16:36:00
|
> 1. > ==4996== Invalid read of size 4 > ==4996== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so <http://ld-uClibc-0.9.33.2.so>) > ==4996== Address 0x7dbb6664 is on thread 1's stack > ==4996== 20 bytes below stack pointer > GDB: > 1. > (gdb) info reg > r0 0x4007148 67137864 > r1 0x0 0 > r2 0x49ba000 77307904 > r3 0x49bd90c 77322508 > r4 0x4015f78 67198840 > r5 0x4006054 67133524 > r6 0xa 10 > r7 0x4006ac0 67136192 > r8 0x24 36 > r9 0x401602c 67199020 > r10 0x7dbb6a48 2109434440 > r11 0x7dbb6674 2109433460 > r12 0x7dbb6678 2109433464 > sp 0x7dbb6678 0x7dbb6678 > lr 0x40054ec 67130604 > pc 0x40054ec 0x40054ec > cpsr 0x20000010 536870928 > (gdb) x/9i $pc-4*4 > 0x40054dc: beq 0x40054ec > 0x40054e0: ldr r2, [r7] > 0x40054e4: add r3, r3, r2 > 0x40054e8: blx r3 > => 0x40054ec: mov r0, r7 > 0x40054f0: bl 0x4001440 > 0x40054f4: b 0x40054b8 > 0x40054f8: ldr r1, [r6, #88] ; 0x58 > 0x40054fc: sub sp, sp, #16 > This is strange. None of the instructions (in any of the four cases) that are designated by the address in "at 0x..." is a memory fetch 'ldr' which would be necessary to correspond to the complaint "Invalid read of size 4". However, I see that each of the 4 complaints is immediately after a 'blx' instruction. 'blx' has a history of problems in both hardware and software. Exactly what hardware are you running? Please report the output of "lscpu" and "cat /proc/cpuinfo". Also, please tell us which Linux distribution, and the exact package name of the compiled binary package for uClibc, and where anyone can download a copy of the package (both compiled binary and source code). Meanwhile, please invoke with these diagnostic flags: valgrind --trace-notbelow=0 --trace-flags=10000000 /bin/true 2>vgtrace.txt The re-directed stderr vgtrace.txt will be an instruction-by-instruction trace [it will be large, probably about 5 MB or so] where the individual blocks look like ***** [This example was generated on x86_64.] ==== SB 0 (evchecks 0) [tid 1] 0x4000c50 UNKNOWN_FUNCTION /usr/lib64/ld-2.24.so+0xc50 ------------------------ Front end ------------------------ 0x4000C50: movq %rsp,%rdi ------ IMark(0x4000C50, 3, 0) ------ PUT(72) = GET:I64(48) PUT(184) = 0x4000C53:I64 ***** where the "SB 0" is a serial number of the block. Find the 'blx' instruction and its enclosing "SB nnnnn". Then look forward until you find the SB for the pc that is specified in the complaint from memcheck. Select the entire range of SB (from the 'blx' to the complaint) into a file, gzip it, and upload it somewhere that anyone interested can download it. The idea is to find out how memcheck got the address that it is complaining about. -- |
|
From: Kacper K. <kac...@gm...> - 2017-09-06 11:29:17
|
Openwrt does not have lscpu command available (nor in any package). cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 10 (v7l) BogoMIPS : 132.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 10 processor : 1 model name : ARMv7 Processor rev 10 (v7l) BogoMIPS : 132.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 10 Hardware : Freescale i.MX6 Quad/DualLite (Device Tree) Revision : 0000 Serial : 0000000000000000 Operating system info: cat /etc/openwrt_release DISTRIB_ID='OpenWrt' DISTRIB_RELEASE='15.05' DISTRIB_REVISION='r48153' DISTRIB_CODENAME='chaos_calmer' DISTRIB_TARGET='imx6/generic' DISTRIB_DESCRIPTION='OpenWrt Chaos Calmer 15.05' DISTRIB_TAINTS='no-all busybox' cat /proc/version Linux version 3.18.23 (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r48153) ) #6 SMP Tue Jul 11 16:35:20 CEST 2017 Source code could be downloaded from: https://uclibc.org/downloads/uClibc-0.9.33.2.tar.bz2 Extracted chunks from trace output can be downloaded from: https://github.com/KKoovalsky/Valgrind-problems The file is called vgtrace-shortened.txt. Full trace available in vgtrace.txt file. In this repo I also included compiled uClibc library. I am wondering if GCC update could have caused such behavior. I've been running image compiled with GCC-4.8-Linaro, then I bumped the GCC package version to use GCC-5.3, run firmware update and then installed valgrind and other software which was compiled with buildroot which uses GCC-5.3. I will try to check if this problem is reproducible by flashing from image which was initially compiled with GCC-5.3. 2017-09-05 18:35 GMT+02:00 John Reiser <jr...@bi...>: > > 1. > > ==4996== Invalid read of size 4 > > ==4996== at 0x40054EC: ??? (in /lib/ld-uClibc-0.9.33.2.so < > http://ld-uClibc-0.9.33.2.so>) > > ==4996== Address 0x7dbb6664 is on thread 1's stack > > ==4996== 20 bytes below stack pointer > >> GDB: >> >> 1. >> (gdb) info reg >> r0 0x4007148 67137864 >> r1 0x0 0 >> r2 0x49ba000 77307904 >> r3 0x49bd90c 77322508 >> r4 0x4015f78 67198840 >> r5 0x4006054 67133524 >> r6 0xa 10 >> r7 0x4006ac0 67136192 >> r8 0x24 36 >> r9 0x401602c 67199020 >> r10 0x7dbb6a48 2109434440 >> r11 0x7dbb6674 2109433460 >> r12 0x7dbb6678 2109433464 >> sp 0x7dbb6678 0x7dbb6678 >> lr 0x40054ec 67130604 >> pc 0x40054ec 0x40054ec >> cpsr 0x20000010 536870928 >> (gdb) x/9i $pc-4*4 >> 0x40054dc: beq 0x40054ec >> 0x40054e0: ldr r2, [r7] >> 0x40054e4: add r3, r3, r2 >> 0x40054e8: blx r3 >> => 0x40054ec: mov r0, r7 >> 0x40054f0: bl 0x4001440 >> 0x40054f4: b 0x40054b8 >> 0x40054f8: ldr r1, [r6, #88] ; 0x58 >> 0x40054fc: sub sp, sp, #16 >> >> > This is strange. None of the instructions (in any of the four cases) > that are designated by the address in "at 0x..." is a memory fetch 'ldr' > which would be necessary to correspond to the complaint "Invalid read of > size 4". > > However, I see that each of the 4 complaints is immediately after a 'blx' > instruction. > 'blx' has a history of problems in both hardware and software. > Exactly what hardware are you running? Please report the output of > "lscpu" and "cat /proc/cpuinfo". > Also, please tell us which Linux distribution, and the exact package name > of the > compiled binary package for uClibc, and where anyone can download a copy > of the package > (both compiled binary and source code). > > Meanwhile, please invoke with these diagnostic flags: > valgrind --trace-notbelow=0 --trace-flags=10000000 /bin/true > 2>vgtrace.txt > > The re-directed stderr vgtrace.txt will be an instruction-by-instruction > trace > [it will be large, probably about 5 MB or so] where the individual blocks > look like > ***** [This example was generated on x86_64.] > ==== SB 0 (evchecks 0) [tid 1] 0x4000c50 UNKNOWN_FUNCTION /usr/lib64/ > ld-2.24.so+0xc50 > > ------------------------ Front end ------------------------ > > 0x4000C50: movq %rsp,%rdi > > ------ IMark(0x4000C50, 3, 0) ------ > PUT(72) = GET:I64(48) > PUT(184) = 0x4000C53:I64 > ***** > where the "SB 0" is a serial number of the block. Find the 'blx' > instruction > and its enclosing "SB nnnnn". Then look forward until you find the SB for > the > pc that is specified in the complaint from memcheck. Select the entire > range of SB > (from the 'blx' to the complaint) into a file, gzip it, and upload it > somewhere > that anyone interested can download it. The idea is to find out how > memcheck > got the address that it is complaining about. > > > -- > > ------------------------------------------------------------ > ------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > Valgrind-users mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-users > |
|
From: John R. <jr...@bi...> - 2017-09-06 17:33:13
|
> cat /proc/cpuinfo [[snip]] > processor : 1 > model name : ARMv7 Processor rev 10 (v7l) > BogoMIPS : 132.00 > Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 > CPU implementer : 0x41 > CPU architecture: 7 > CPU variant : 0x2 > CPU part : 0xc09 > CPU revision : 10 > > Hardware : Freescale i.MX6 Quad/DualLite (Device Tree) > Revision : 0000 > Serial : 0000000000000000 > > Operating system info: > cat /etc/openwrt_release > DISTRIB_ID='OpenWrt' > DISTRIB_RELEASE='15.05' > DISTRIB_REVISION='r48153' > DISTRIB_CODENAME='chaos_calmer' > DISTRIB_TARGET='imx6/generic' > DISTRIB_DESCRIPTION='OpenWrt Chaos Calmer 15.05' > DISTRIB_TAINTS='no-all busybox' > > cat /proc/version > Linux version 3.18.23 (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r48153) ) #6 SMP Tue Jul 11 16:35:20 CEST 2017 > > Source code could be downloaded from: > https://uclibc.org/downloads/uClibc-0.9.33.2.tar.bz2 > > Extracted chunks from trace output can be downloaded from: > https://github.com/KKoovalsky/Valgrind-problems > > The file is called vgtrace-shortened.txt. Full trace available in vgtrace.txt file. In this repo I also included compiled uClibc library. Thank you for the detailed information, particularly the vgtrace*.txt. It's a compiler "bug", and a "bug" in the memcheck implementation, and a definite bug in the memcheck error reporting. The workaround is to invoke valgrind(memcheck) with "--ignore-range-below-sp=0x0-0x14". The problem can be seen here: ===== vgtrace-shortened.txt line 8308 (arm) 0x4817678: mov r12, r13 ## copy r12 from r13(==sp) ------ IMark(0x4817678, 4, 0) ------ t1 = GET:I32(60) t0 = t1 t2 = t0 PUT(56) = t2 PUT(68) = 0x481767C:I32 (arm) 0x481767C: stmdb r13!, {0xDFF0} ## push r15(==pc),r14(==lr),r12,r11-r4 onto stack (sp===r13) *in that order* ------ IMark(0x481767C, 4, 0) ------ t3 = GET:I32(60) t4 = t3 PUT(60) = Sub32(t3,0x2C:I32) STle(Sub32(t4,0x4:I32)) = 0x4817684:I32 STle(Sub32(t4,0x8:I32)) = GET:I32(64) STle(Sub32(t4,0xC:I32)) = GET:I32(56) STle(Sub32(t4,0x10:I32)) = GET:I32(52) STle(Sub32(t4,0x14:I32)) = GET:I32(48) STle(Sub32(t4,0x18:I32)) = GET:I32(44) STle(Sub32(t4,0x1C:I32)) = GET:I32(40) STle(Sub32(t4,0x20:I32)) = GET:I32(36) STle(Sub32(t4,0x24:I32)) = GET:I32(32) STle(Sub32(t4,0x28:I32)) = GET:I32(28) STle(Sub32(t4,0x2C:I32)) = GET:I32(24) PUT(68) = 0x4817680:I32 (arm) 0x4817680: sub r11, r12, #0x4 ## r12 has same value as sp before the 'stmdb' ------ IMark(0x4817680, 4, 0) ------ t5 = GET:I32(56) t6 = 0x4:I32 t7 = Sub32(t5,t6) PUT(52) = t7 PUT(68) = 0x4817684:I32 (arm) 0x4817684: ldmdb r11, {0xAFF0} ## load r15(==pc) from stored lr, r13(==sp) from stored r12, r11-r4 from stored original values ------ IMark(0x4817684, 4, 0) ------ t8 = GET:I32(52) t9 = t8 PUT(68) = LDle:I32(Sub32(t9,0x4:I32)) PUT(60) = LDle:I32(Sub32(t9,0x8:I32)) PUT(48) = LDle:I32(Sub32(t9,0x10:I32)) PUT(44) = LDle:I32(Sub32(t9,0x14:I32)) PUT(40) = LDle:I32(Sub32(t9,0x18:I32)) PUT(36) = LDle:I32(Sub32(t9,0x1C:I32)) PUT(32) = LDle:I32(Sub32(t9,0x20:I32)) PUT(28) = LDle:I32(Sub32(t9,0x24:I32)) PUT(24) = LDle:I32(Sub32(t9,0x28:I32)) PUT(52) = LDle:I32(Sub32(t9,0xC:I32)) PUT(68) = GET:I32(68) PUT(68) = GET:I32(68); exit-Boring GuestBytes 4817678 16 0D C0 A0 E1 F0 DF 2D E9 04 B0 4C E2 F0 AF 1B E9 0028F343 VexExpansionRatio 16 952 595 :10 ==26904== Invalid read of size 4 ==26904== at 0x4000E54: ??? (in /lib/ld-uClibc-0.9.33.2.so) ==26904== Address 0x7dad09fc is on thread 1's stack ==26904== 20 bytes below stack pointer ===== The net effect of those 3 instructions is: r0-r3 do not change; none of them was written r4-r10 do not change; each value is stored and fetched to/from the same (corresponding) address r11 = (r12 - 4) from the 'sub' r12 gets the original (and final) value of r13(==sp) r13(==sp) does not change. It was decremented by 44 (11 registers times 4 bytes per register) but then loaded from the location which was written with the value of r12, which is the same as the original sp r14(==lr) does not change; it never was written r15(==pc) is loaded from the original value in r14(==lr) which is the return address memcheck's bug is reporting the location "at 0x..." using the new value that was loaded into pc, instead of the original value of the pc of the instruction which suffered the complaint. The compiler bug is relying on a particular implementation of poorly-specified hardware. The "ldmdb r11, {0xAFF0}" reads 10 words from memory, and changes the value of r13(==sp) among other registers. The compiler assumes that the change to r13 does not become visible until the entire instruction has completed, yet this is not guaranteed explicitly. It is conceivable that the 'ldmdb' could be interrupted immediately after writing r13(==sp), save internal state as part of servicing the interrupt, and resume state upon return. If so, then the fetches to load the remaining registers are outside the boundary of the stack (namely, less than the downward-growing sp), and that's a memcheck error. On the other hand, all known hardware does not allow such an interrupt (all side effects are "atomic") so the memcheck implementation is not faithful because it uses the new value of r13(==sp) to check subsequent memory fetches for other registers before the 'lmdb' instruction ends. The compiler's choice of storing and re-loading r4-r11 is horribly inefficient: 8 writes and 8 reads that only waste time. The value stored from r15(==pc) via the 'stmdb' never is read. The entire sequence could be replaced by "bx lr" or "mov pc,lr", (possibly preceded by "mov r12,sp"); except that 'bx' is not implemented in some early hardware, and "mov pc,lr" is frowned upon in hardware that does have 'bx'. One possible solution that works everywhere is to use "blx lr" and just ignore the value that is written to lr. -- |
|
From: John R. <jr...@bi...> - 2017-09-06 18:20:25
|
> memcheck's bug is reporting the location "at 0x..." using the new value that was loaded into pc, > instead of the original value of the pc of the instruction which suffered the complaint. https://bugs.kde.org/show_bug.cgi?id=384442 "ARM: bad pc in complaint if instruction changes pc" -- |