diff options
author | Willy Tarreau <w@1wt.eu> | 2023-01-09 08:54:41 +0100 |
---|---|---|
committer | Paul E. McKenney <paulmck@kernel.org> | 2023-01-09 09:36:05 -0800 |
commit | 1bfbe1f3e96720daf185f03d101f072d69753f88 (patch) | |
tree | db3ab114fa9e2671aa31226a16a76920caf69ffc /tools | |
parent | 55abdd1f5e1e07418bf4a46c233a92f83cb5ae97 (diff) | |
download | lwn-1bfbe1f3e96720daf185f03d101f072d69753f88.tar.gz lwn-1bfbe1f3e96720daf185f03d101f072d69753f88.zip |
tools/nolibc: prevent gcc from making memset() loop over itself
When building on ARM in thumb mode with gcc-11.3 at -O2 or -O3,
nolibc-test segfaults during the select() tests. It turns out that at
this level, gcc recognizes an opportunity for using memset() to zero
the fd_set, but it miscompiles it because it also recognizes a memset
pattern as well, and decides to call memset() from the memset() code:
000122bc <memset>:
122bc: b510 push {r4, lr}
122be: 0004 movs r4, r0
122c0: 2a00 cmp r2, #0
122c2: d003 beq.n 122cc <memset+0x10>
122c4: 23ff movs r3, #255 ; 0xff
122c6: 4019 ands r1, r3
122c8: f7ff fff8 bl 122bc <memset>
122cc: 0020 movs r0, r4
122ce: bd10 pop {r4, pc}
Simply placing an empty asm() statement inside the loop suffices to
avoid this.
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/include/nolibc/string.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h index 0932db3817d2..fffdaf6ff467 100644 --- a/tools/include/nolibc/string.h +++ b/tools/include/nolibc/string.h @@ -88,8 +88,11 @@ void *memset(void *dst, int b, size_t len) { char *p = dst; - while (len--) + while (len--) { + /* prevent gcc from recognizing memset() here */ + asm volatile(""); *(p++) = b; + } return dst; } |