Bug 468575

Summary: Add support for RISC-V
Product: [Developer tools] valgrind Reporter: Petr Pavlu <petr.pavlu>
Component: generalAssignee: Julian Seward <jseward>
Status: CONFIRMED ---    
Severity: normal CC: jlp, laokz, mark, pjfloyd, rjiejie, rjones, sam
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Other   
OS: Linux   
See Also: https://sourceware.org/bugzilla/show_bug.cgi?id=32496
https://bugs.kde.org/show_bug.cgi?id=498103
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: v1-0001-riscv64-valgrind-new.patch
v1-0002-riscv64-vex-new.patch
v1-0003-riscv64-tests-new.patch
v1-0004-riscv64-valgrind-mod.patch
v1-0005-riscv64-vex-mod.patch
v1-0006-riscv64-tests-mod.patch
riscv64: Add initial support: new port-specific Valgrind files
riscv64: Add initial support: new port-specific VEX files
riscv64: Add initial support: new port-specific test
riscv64: Add initial support: Valgrind modifications
riscv64: Add initial support: VEX modifications
riscv64: Add initial support: test modifications
close_range fd as Int
VEX/priv/ir_opt.c: Also fold Iop_And1 expressions when possible
riscv64: Add initial support: new port-specific Valgrind files
riscv64: Add initial support: new port-specific VEX files
riscv64: Add initial support: new port-specific test
riscv64: Add initial support: Valgrind modifications
riscv64: Add initial support: VEX modifications
riscv64: Add initial support: test modifications
Disable none/tests/riscv64 compressed and integer builds and test
VEX/priv/guest_riscv64_toIR.c: Recognize both fence and fence.tso
integer.c: replace zero by a1
VEX/priv/guest_riscv64_toIR.c: Recognize both fence and fence.tso
riscv64: syswrap various shared linux syscalls
riscv64: Add hardwire for ld-linux-riscv64-lp64d.so.1 strcmp

Description Petr Pavlu 2023-04-16 14:25:50 UTC
RISC-V [1, 2] is a modern open-standard architecture which has seen increasing adoption lately.

I and a few other contributors have been working on adding support for this architecture in Valgrind, using a downstream repository [3]. The port has reached a state where I think it has a good quality to be added to the official Valgrind project and continued to be developed there.

The port adds supports for the 64-bit RISC-V architecture, specifically for the RV64GC instruction set which is what most Linux distributions currently target. Support for further extensions is expected to be incrementally implemented in the future, as more extensions get defined by architecture stewards and make it into hardware.

The work is cut into 6 patches. The first three add new files specific only to the port and they are split for Valgrind (Coregrind+tools), VEX and tests. The last three modify already present files and are split in the same way.

Implementation mostly tries to stay consistent with arm64 and mips64. No new Iops are currently added by the port but some new ones might be needed in the future. For instance, support for the Zfh extension (half-precision floating-point) will likely require a few additional Iops, although these should be needed for the complete Armv8.2-A FP16 support too.

The port passes almost completely the Valgrind test suite. A few tests still currently fail and need to be investigated.

The port gained some reasonable traction and a few other people contributed to it in the last year by implementing missing bits and fixing various bugs.

[1] https://riscv.org/
[2] https://en.wikipedia.org/wiki/RISC-V
[3] https://github.com/petrpavlu/valgrind-riscv64
Comment 1 Petr Pavlu 2023-04-16 14:26:44 UTC
Created attachment 158147 [details]
v1-0001-riscv64-valgrind-new.patch
Comment 2 Petr Pavlu 2023-04-16 14:27:03 UTC
Created attachment 158148 [details]
v1-0002-riscv64-vex-new.patch
Comment 3 Petr Pavlu 2023-04-16 14:27:26 UTC
Created attachment 158149 [details]
v1-0003-riscv64-tests-new.patch
Comment 4 Petr Pavlu 2023-04-16 14:27:39 UTC
Created attachment 158150 [details]
v1-0004-riscv64-valgrind-mod.patch
Comment 5 Petr Pavlu 2023-04-16 14:27:53 UTC
Created attachment 158151 [details]
v1-0005-riscv64-vex-mod.patch
Comment 6 Petr Pavlu 2023-04-16 14:28:05 UTC
Created attachment 158152 [details]
v1-0006-riscv64-tests-mod.patch
Comment 7 Petr Pavlu 2023-04-16 14:30:47 UTC
v1:
* attachment 158147 [details] v1-0001-riscv64-valgrind-new.patch,
* attachment 158148 [details] v1-0002-riscv64-vex-new.patch,
* attachment 158149 [details] v1-0003-riscv64-tests-new.patch,
* attachment 158150 [details] v1-0004-riscv64-valgrind-mod.patch,
* attachment 158151 [details] v1-0005-riscv64-vex-mod.patch,
* attachment 158152 [details] v1-0006-riscv64-tests-mod.patch.

Based on ab6d3928a ("regtest: warning cleanup").

Test suite results:
> == 675 tests, 4 stderr failures, 2 stdout failures, 1 stderrB failure, 1 stdoutB failure, 0 post failures ==
> gdbserver_tests/hginfo                   (stderrB)
> gdbserver_tests/hgtls                    (stdoutB)
> memcheck/tests/cdebug_zlib_gnu           (stderr)
> memcheck/tests/linux/stack_changes       (stdout)
> memcheck/tests/linux/stack_changes       (stderr)
> memcheck/tests/pointer-trace             (stderr)
> memcheck/tests/sh-mem-random             (stdout)
> memcheck/tests/sh-mem-random             (stderr)
Comment 8 Paul Floyd 2023-04-17 08:27:15 UTC
hginfo fails on several systems
TLS is, well, tricky

Are the other failures "reaonable"?
Comment 9 Petr Pavlu 2023-04-17 20:03:19 UTC
(In reply to Paul Floyd from comment #8)
> hginfo fails on several systems
> TLS is, well, tricky
> 
> Are the other failures "reaonable"?

The following is a short summary why the remaining tests fail. However, I'm not sure yet for any of them what is their underlying problem and still need to do proper investigation.

> gdbserver_tests/hginfo                   (stderrB)

The output has information about an extra lock inside _rtld_local. Likely a duplicate of bug 444487.

> gdbserver_tests/hgtls                    (stdoutB)

Fails because GDB is not able to determine an address of the variable 'local'. The test used to pass on my system, possibly something compiler-related.

> memcheck/tests/cdebug_zlib_gnu           (stderr)

Produced backtrace contains rubbish 'at 0x........: main (ng long int:3)' instead of 'at 0x........: main (cdebug.c:3)'.

> memcheck/tests/linux/stack_changes       (stdout)
> memcheck/tests/linux/stack_changes       (stderr)

Lots of unexpected invalid writes reported from hello() -> printf().

> memcheck/tests/pointer-trace             (stderr)

The second mmap() call in the test unexpectedly fails with -EINVAL.

> memcheck/tests/sh-mem-random             (stdout)
> memcheck/tests/sh-mem-random             (stderr)

Another unexpected mmap() failure.
Comment 10 JojoR 2023-04-20 01:42:13 UTC
(In reply to Petr Pavlu from comment #9)
> (In reply to Paul Floyd from comment #8)
> > hginfo fails on several systems
> > TLS is, well, tricky
> > 
> > Are the other failures "reaonable"?
> 
> > memcheck/tests/sh-mem-random             (stdout)
> > memcheck/tests/sh-mem-random             (stderr)
> 
> Another unexpected mmap() failure.

From our investigation, high address mmap is not supported by some riscv board/os if it support feature "Sv39" only,
so it is reasonable also :)
Comment 11 JojoR 2023-06-25 08:51:13 UTC
@Paul Floyd

Has anyone reviewed these patches ?

It has taken two months and there is not any feedback :)
Comment 12 laokz 2023-07-30 14:59:07 UTC
> > memcheck/tests/pointer-trace             (stderr)
> The second mmap() call in the test unexpectedly fails with -EINVAL.
The second mmap() is called with PROT_WRITE only. I'm pretty sure the result is 'resonable' because it is KERNEL relevant.

From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8aeb7b17f04ef40f620c763502e2b644c5c73efd , it shows that kernel would return EINVAL for mmap(PROT_WRITE only) if without this commit, or the call would be treated as with an implied PROT_READ like other architectures.

I tested on openEuler 22.03 with/without this commit and got expected success/failure result.

>> with the commit
> # perl tests/vg_regtest memcheck/tests/pointer-trace.vgtest
> pointer-trace:   valgrind   -q --leak-check=yes ./pointer-trace
> 
> == 1 test, 0 stderr failures, 0 stdout failures, 0 stderrB failures, 0 stdoutB failures, 0 post failures ==

>> without the commit
> # perl tests/vg_regtest memcheck/tests/pointer-trace.vgtest
> pointer-trace:   valgrind   -q --leak-check=yes ./pointer-trace
> *** pointer-trace failed (stderr) ***
> 
> == 1 test, 1 stderr failure, 0 stdout failures, 0 stderrB failures, 0 stdoutB failures, 0 post failures ==
> memcheck/tests/pointer-trace             (stderr)
> 
> # cat memcheck/tests/pointer-trace.stderr.out
> trap 2 failed: Invalid argument
> 1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
>    at 0x........: malloc (vg_replace_malloc.c:...)
>    by 0x........: main (pointer-trace.c:86)
Comment 13 JojoR 2024-06-17 02:23:11 UTC
@Paul Floyd

Has anyone reviewed these patches ?

It has taken long time and there is not any feedback :)

Could we review & push these basic ISAs (rv64gc) implementation first ?
other of extensions like Vector of RISCV depend on this, that will be the next steps :)
Comment 14 Paul Floyd 2024-06-17 08:24:11 UTC
I built and ran regtest on my github clone of https://github.com/petrpavlu/valgrind-riscv64 on FreeBSD amd64.

There were a couple of unexpected failures in memcheck/tests/freebsd (one of the scalars and eventfd2). I'll look into them and also try some more platforms.
Comment 15 JojoR 2024-06-18 01:35:30 UTC
(In reply to Paul Floyd from comment #14)
> I built and ran regtest on my github clone of
> https://github.com/petrpavlu/valgrind-riscv64 on FreeBSD amd64.
> 
> There were a couple of unexpected failures in memcheck/tests/freebsd (one of
> the scalars and eventfd2). I'll look into them and also try some more
> platforms.

Good news, thanks for your efforts, hope that will been fixed soon :)
Comment 16 Paul Floyd 2024-06-18 12:21:02 UTC
I think it's a regression that I added. Should be fixed. I'll check again when Petr rebases next, and I'll also give Linux amd64 a go and see if I can build and run regtest on riscv.
Comment 17 Paul Floyd 2024-06-20 11:45:48 UTC
On amd64 Linux, one warning that I've opened an issue for on Petr's github.

A few other warnings about pointer-to-int-casts.

regtest clean.
Comment 18 Paul Floyd 2024-06-21 06:42:59 UTC
On a machine that is StarFive JH7100 SoC (2x SiFive U74 at 1.20 GHz)

I have a problem with make check.

gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o compressed compressed.o  
compressed.o: in function `test_compressed_10':
/home/paulf/valgrind-riscv64/none/tests/riscv64/compressed.c:347:(.text+0x56d16): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20
collect2: error: ld returned 1 exit status
make[5]: *** [Makefile:741: compressed] Error 1
make[5]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests/riscv64'
make[4]: *** [Makefile:899: check-am] Error 2
make[4]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests/riscv64'
make[3]: *** [Makefile:2270: check-recursive] Error 1
make[3]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests'
make[2]: *** [Makefile:1101: check-recursive] Error 1
make[2]: Leaving directory '/home/paulf/valgrind-riscv64/none'
make[1]: *** [Makefile:926: check-recursive] Error 1
make[1]: Leaving directory '/home/paulf/valgrind-riscv64'
make: *** [Makefile:1225: check] Error 2

Maybe a GCC problem?

gcc --version
gcc (Debian 13.2.0-13) 13.2.0
Comment 19 JojoR 2024-06-21 06:47:34 UTC
(In reply to Paul Floyd from comment #18)
> On a machine that is StarFive JH7100 SoC (2x SiFive U74 at 1.20 GHz)
> 
> I have a problem with make check.
> 
> gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o
> compressed compressed.o  
> compressed.o: in function `test_compressed_10':
> /home/paulf/valgrind-riscv64/none/tests/riscv64/compressed.c:347:(.
> text+0x56d16): dangerous relocation: The addend isn't allowed for
> R_RISCV_GOT_HI20
> collect2: error: ld returned 1 exit status
> make[5]: *** [Makefile:741: compressed] Error 1
> make[5]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests/riscv64'
> make[4]: *** [Makefile:899: check-am] Error 2
> make[4]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests/riscv64'
> make[3]: *** [Makefile:2270: check-recursive] Error 1
> make[3]: Leaving directory '/home/paulf/valgrind-riscv64/none/tests'
> make[2]: *** [Makefile:1101: check-recursive] Error 1
> make[2]: Leaving directory '/home/paulf/valgrind-riscv64/none'
> make[1]: *** [Makefile:926: check-recursive] Error 1
> make[1]: Leaving directory '/home/paulf/valgrind-riscv64'
> make: *** [Makefile:1225: check] Error 2
> 
> Maybe a GCC problem?
> 
> gcc --version
> gcc (Debian 13.2.0-13) 13.2.0

Yes, looks ld met some bugs :(
and I suggest you can get the latest toolchain from here:
https://github.com/riscv-collab/riscv-gnu-toolchain/releases/
Comment 20 Paul Floyd 2024-07-02 10:47:54 UTC
And regtest results

== 737 tests, 6 stderr failures, 2 stdout failures, 0 stderrB failures, 1 stdoutB failure, 0 post failures ==
gdbserver_tests/hgtls                    (stdoutB)
memcheck/tests/pointer-trace             (stderr)
none/tests/double_close_range            (stderr)
none/tests/double_close_range_sup        (stderr)
none/tests/double_close_range_xml        (stderr)
none/tests/riscv64/compressed            (stdout)
none/tests/riscv64/compressed            (stderr)
none/tests/riscv64/integer               (stdout)
none/tests/riscv64/integer               (stderr)

I've seen memcheck/tests/pointer-trace issues before where the working directory is on NFS. Not riscv related.

The double_close_range tests are fairly new and may need some extra filtering.

The two riscv64 fails look like a  problem with the toolchain. I'll see if trying a local build of the toolchain helps.
Comment 21 Petr Pavlu 2024-07-08 21:16:08 UTC
(In reply to Paul Floyd from comment #20)
> And regtest results
> 
> == 737 tests, 6 stderr failures, 2 stdout failures, 0 stderrB failures, 1
> stdoutB failure, 0 post failures ==
> gdbserver_tests/hgtls                    (stdoutB)

The hgtls test fails because GDB is confused by missing DW_AT_location attributes for TLS variables. It looks to be a problem with the RISC-V target in GCC not implementing TARGET_ASM_OUTPUT_DWARF_DTPREL. I have a preliminary patch for GCC which adds it.

> [...]
> none/tests/riscv64/compressed            (stdout)
> none/tests/riscv64/compressed            (stderr)
> none/tests/riscv64/integer               (stdout)
> none/tests/riscv64/integer               (stderr)
> 
> [...]
> The two riscv64 fails look like a  problem with the toolchain. I'll see if
> trying a local build of the toolchain helps.

The mentioned compilation failure of RISC-V tests is some problem related to them being compiled as position-independent, which is apparently the default on Debian. It is possible for me to reproduce it locally. I'll have a closer look.
Comment 22 JojoR 2024-07-18 03:20:15 UTC
> > [...]
> > none/tests/riscv64/compressed            (stdout)
> > none/tests/riscv64/compressed            (stderr)
> > none/tests/riscv64/integer               (stdout)
> > none/tests/riscv64/integer               (stderr)
> > 
> > [...]
> > The two riscv64 fails look like a  problem with the toolchain. I'll see if
> > trying a local build of the toolchain helps.
> 
> The mentioned compilation failure of RISC-V tests is some problem related to
> them being compiled as position-independent, which is apparently the default
> on Debian. It is possible for me to reproduce it locally. I'll have a closer
> look.

What's the details about the error output ?
I can help to have a look if that is obvious :)
BTW, it didn't happen in my environment.
Comment 23 JojoR 2024-10-10 06:51:05 UTC
Hi, Paul Floyd & Petr Pavlu

Any progress ? 
It's depression if there are a few small issues :(
Comment 24 Paul Floyd 2024-10-10 09:22:01 UTC
(In reply to JojoR from comment #23)
> Hi, Paul Floyd & Petr Pavlu
> 
> Any progress ? 
> It's depression if there are a few small issues :(

There are two things that I consider as requirements.

Firstly someone to get git write access to maintain this.

Secondly all the usual code requirements (review for such a big change, all regressions passing on all platforms).
Comment 25 Mark Wielaard 2024-10-11 14:59:40 UTC
https://builder.sourceware.org/ now has several riscv builders. We should setup one.
We are already testing armhf, i386, ppc64, arm64, ppc64le, s390x, x86_64 and power9/10.
https://builder.sourceware.org/buildbot/#/builders?tags=valgrind
Comment 26 Mark Wielaard 2024-12-13 20:08:02 UTC
Created attachment 176580 [details]
riscv64: Add initial support: new port-specific Valgrind files

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 27 Mark Wielaard 2024-12-13 20:09:22 UTC
Created attachment 176581 [details]
riscv64: Add initial support: new port-specific VEX files

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 28 Mark Wielaard 2024-12-13 20:10:44 UTC
Created attachment 176582 [details]
riscv64: Add initial support: new port-specific test

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 29 Mark Wielaard 2024-12-13 20:11:52 UTC
Created attachment 176583 [details]
riscv64: Add initial support: Valgrind modifications

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 30 Mark Wielaard 2024-12-13 20:14:15 UTC
Created attachment 176584 [details]
riscv64: Add initial support: VEX modifications

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 31 Mark Wielaard 2024-12-13 20:15:07 UTC
Created attachment 176585 [details]
riscv64: Add initial support: test modifications

Rebased against current valgrind trunk (commit d9f4746a8815ca4a57639f5213405c81d13ab8cd)
Comment 32 Mark Wielaard 2024-12-13 21:35:59 UTC
One more change that should go into patch 1 riscv64: Add initial support: new port-specific Valgrind files because since commit 6a28e665f8dd7c031aef5aa0eaa4acbbd8ba27a9 ("With --track-fds=yes warn when file descriptor is closed a second time") we don't have a generic POST close handler anymore:

diff --git a/coregrind/m_syswrap/syswrap-riscv64-linux.c b/coregrind/m_syswrap/syswrap-riscv64-linux.c
index b959bc861..c07da94f8 100644
--- a/coregrind/m_syswrap/syswrap-riscv64-linux.c
+++ b/coregrind/m_syswrap/syswrap-riscv64-linux.c
@@ -365,7 +365,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINX_(__NR_fchownat, sys_fchownat),                             /* 54 */
    GENX_(__NR_fchown, sys_fchown),                                 /* 55 */
    LINXY(__NR_openat, sys_openat),                                 /* 56 */
-   GENXY(__NR_close, sys_close),                                   /* 57 */
+   GENX_(__NR_close, sys_close),                                   /* 57 */
    LINX_(__NR_vhangup, sys_vhangup),                               /* 58 */
    LINXY(__NR_pipe2, sys_pipe2),                                   /* 59 */
    LINX_(__NR_quotactl, sys_quotactl),                             /* 60 */
Comment 33 Mark Wielaard 2024-12-13 21:43:47 UTC
And in my rebase of patch 6 I forgot a \ at the end of one line:

diff --git a/helgrind/tests/tc11_XCHG.c b/helgrind/tests/tc11_XCHG.c
index 6ad44efac..e92b671b7 100644
--- a/helgrind/tests/tc11_XCHG.c
+++ b/helgrind/tests/tc11_XCHG.c
@@ -131,7 +131,7 @@
 
 #elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) \
       || defined(PLAT_arm_linux) || defined(PLAT_arm64_linux) \
-      || defined(PLAT_arm64_freebsd)
+      || defined(PLAT_arm64_freebsd) \
       || defined(PLAT_riscv64_linux)
 #  if defined(HAVE_BUILTIN_ATOMIC)
 #    define XCHG_M_R(_addr,_lval)                                           \
Comment 34 Mark Wielaard 2024-12-13 21:45:58 UTC
Got the same issue as Paul in comment #18
Maybe we can guard the none/tests/riscv64/compressed.c test with some configure check?
It seems unfortunate to have such compile issues with shipping toolchains.
Comment 35 Mark Wielaard 2024-12-13 21:58:53 UTC
Also none/tests/riscv64/integer.c doesn't compile on my setup.

GCC 13.3.0
GNU Binutils 2.42.0.20240216

depbase=`echo integer.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -I../../..  -I../../.. -I../../../include -I../../../coregrind -I../../../include -I../../../VEX/pub -I../../../VEX/pub -DVGA_riscv64=1 -DVGO_linux=1 -DVGP_riscv64_linux=1 -DVGPV_riscv64_linux_vanilla=1    -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector     -MT integer.o -MD -MP -MF $depbase.Tpo -c -o integer.o integer.c &&\
mv -f $depbase.Tpo $depbase.Po
integer.c: Assembler messages:
integer.c:132: Error: illegal operands `la zero,0'
integer.c:133: Error: illegal operands `la zero,0'
integer.c:134: Error: illegal operands `la zero,0'
integer.c:135: Error: illegal operands `la zero,0'
integer.c:145: Error: illegal operands `la zero,0'
integer.c:146: Error: illegal operands `la zero,0'
integer.c:147: Error: illegal operands `la zero,0'
integer.c:148: Error: illegal operands `la zero,0'
integer.c:158: Error: illegal operands `la zero,0'
integer.c:159: Error: illegal operands `la zero,0'
integer.c:160: Error: illegal operands `la zero,0'
integer.c:161: Error: illegal operands `la zero,0'
integer.c:171: Error: illegal operands `la zero,0'
integer.c:172: Error: illegal operands `la zero,0'
integer.c:173: Error: illegal operands `la zero,0'
integer.c:174: Error: illegal operands `la zero,0'
integer.c:184: Error: illegal operands `la zero,0'
integer.c:185: Error: illegal operands `la zero,0'
integer.c:186: Error: illegal operands `la zero,0'
integer.c:187: Error: illegal operands `la zero,0'
integer.c:197: Error: illegal operands `la zero,0'
integer.c:198: Error: illegal operands `la zero,0'
integer.c:199: Error: illegal operands `la zero,0'
integer.c:200: Error: illegal operands `la zero,0'
make[5]: *** [Makefile:787: integer.o] Error 1
make[5]: Leaving directory '/home/mark/valgrind/none/tests/riscv64'
make[4]: *** [Makefile:901: check-am] Error 2
make[4]: Leaving directory '/home/mark/valgrind/none/tests/riscv64'
make[3]: *** [Makefile:2342: check-recursive] Error 1
make[3]: Leaving directory '/home/mark/valgrind/none/tests'
make[2]: *** [Makefile:1101: check-recursive] Error 1
make[2]: Leaving directory '/home/mark/valgrind/none'
make[1]: *** [Makefile:926: check-recursive] Error 1
make[1]: Leaving directory '/home/mark/valgrind'
make: *** [Makefile:1225: check] Error 2
Comment 36 Mark Wielaard 2024-12-13 22:51:55 UTC
So disabling compressed and integer, but without a configure check because I don't know precisely what to test for.

diff --git a/configure.ac b/configure.ac
index 7d3c1a99b..7828b0193 100755
--- a/configure.ac
+++ b/configure.ac
@@ -3755,6 +3755,8 @@ CFLAGS="$save_CFLAGS"
 
 AM_CONDITIONAL(BUILD_ARMV82_DOTPROD_TESTS, test x$ac_have_armv82_dotprod_feature = xyes)
 
+AM_CONDITIONAL(BUILD_COMPRESSED_WORKS, false)
+AM_CONDITIONAL(BUILD_INTEGER_WORKS, false)
 
 # XXX JRS 2010 Oct 13: what is this for?  For sure, we don't need this
 # when building the tool executables.  I think we should get rid of it.

diff --git a/none/tests/riscv64/Makefile.am b/none/tests/riscv64/Makefile.am
index b2de2bd39..3eeaeb451 100644
--- a/none/tests/riscv64/Makefile.am
+++ b/none/tests/riscv64/Makefile.am
@@ -17,13 +17,19 @@ EXTRA_DIST = \
 check_PROGRAMS = \
        allexec \
        atomic \
-       compressed \
        csr \
        float32 \
        float64 \
-       integer \
        muldiv
 
+if BUILD_COMPRESSED_WORKS
+  check_PROGRAMS += compressed
+endif
+
+if BUILD_INTEGER_WORKS
+  check_PROGRAMS += integer
+endif
+
 AM_CFLAGS    += @FLAG_M64@
 AM_CXXFLAGS  += @FLAG_M64@
 AM_CCASFLAGS += @FLAG_M64@

diff --git a/none/tests/riscv64/compressed.vgtest b/none/tests/riscv64/compressed.vgtest
index 5c3d44864..84e9988e0 100644
--- a/none/tests/riscv64/compressed.vgtest
+++ b/none/tests/riscv64/compressed.vgtest
@@ -1,2 +1,3 @@
+prereq: test -x compressed
 prog: compressed
 vgopts: -q
diff --git a/none/tests/riscv64/integer.vgtest b/none/tests/riscv64/integer.vgtest
index daa059178..c779c5cdf 100644
--- a/none/tests/riscv64/integer.vgtest
+++ b/none/tests/riscv64/integer.vgtest
@@ -1,2 +1,3 @@
+prereq: test -x integer
 prog: integer
 vgopts: -q
Comment 37 Mark Wielaard 2024-12-13 22:54:43 UTC
== 744 tests, 11 stderr failures, 1 stdout failure, 0 stderrB failures, 1 stdoutB failure, 0 post failures ==
gdbserver_tests/hgtls                    (stdoutB)
memcheck/tests/linux/bug480706           (stderr)
helgrind/tests/tls_threads               (stderr)
helgrind/tests/tls_threads2              (stderr)
drd/tests/condvar                        (stderr)
drd/tests/pth_mutex_signal               (stderr)
none/tests/double_close_range            (stderr)
none/tests/double_close_range_sup        (stderr)
none/tests/double_close_range_xml        (stderr)
none/tests/mmap_o_direct                 (stderr)
none/tests/nestedfns                     (stdout)
none/tests/nestedfns                     (stderr)
none/tests/procfs-linux                  (stderr)
Comment 38 Mark Wielaard 2024-12-13 23:20:28 UTC
The none/tests/procfs-linux (stderr) issue was a change in the handling of readlinkat.
Adding a POST handler fixes it and makes the test pass:

diff --git a/coregrind/m_syswrap/syswrap-riscv64-linux.c b/coregrind/m_syswrap/syswrap-riscv64-linux.c
index b959bc861..602d4ad38 100644
--- a/coregrind/m_syswrap/syswrap-riscv64-linux.c
+++ b/coregrind/m_syswrap/syswrap-riscv64-linux.c
@@ -386,7 +386,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINX_(__NR_vmsplice, sys_vmsplice),                             /* 75 */
    LINX_(__NR_splice, sys_splice),                                 /* 76 */
    LINX_(__NR_tee, sys_tee),                                       /* 77 */
-   LINX_(__NR_readlinkat, sys_readlinkat),                         /* 78 */
+   LINXY(__NR_readlinkat, sys_readlinkat),                         /* 78 */
    LINXY(__NR_newfstatat, sys_newfstatat),                         /* 79 */
    GENXY(__NR_fstat, sys_newfstat),                                /* 80 */
    GENX_(__NR_sync, sys_sync),                                     /* 81 */
Comment 39 Mark Wielaard 2024-12-14 02:09:18 UTC
Created attachment 176588 [details]
close_range fd as Int

The double_close_range failure seems to be because the close_range wrapper is using unsigned int and the ARG regwords directly. Which causes the ARG2 == ~0U check to fail. Explicitly using Int for the fd arguments seems to fix it. I am not clear on why this was only an issue for the riscv port. It seems this patch is OK for other arches (tested on amd64 and i386).
Comment 40 Mark Wielaard 2024-12-14 02:24:15 UTC
The none/tests/mmap_o_direct failure comes from vki-riscv64-linux.h not defining VKI_O_DIRECT.
With that defined the test passes.

diff --git a/include/vki/vki-riscv64-linux.h b/include/vki/vki-riscv64-linux.h
index 72f7ed420..5cc98b6ab 100644
--- a/include/vki/vki-riscv64-linux.h
+++ b/include/vki/vki-riscv64-linux.h
@@ -208,6 +208,7 @@ typedef struct vki_sigaltstack {
 #define VKI_O_APPEND     02000
 #define VKI_O_NONBLOCK   04000
 #define VKI_O_LARGEFILE        0100000
+#define VKI_O_DIRECT   00040000
 
 #define VKI_F_DUPFD            0       /* dup */
 #define VKI_F_GETFD            1       /* get close_on_exec */
Comment 41 Mark Wielaard 2024-12-14 02:44:35 UTC
memcheck/tests/linux/bug480706 fails because mlock2 wasn't wrapped

diff --git a/coregrind/m_syswrap/syswrap-riscv64-linux.c b/coregrind/m_syswrap/syswrap-riscv64-linux.c
index b959bc861..68c53b0bd 100644
--- a/coregrind/m_syswrap/syswrap-riscv64-linux.c
+++ b/coregrind/m_syswrap/syswrap-riscv64-linux.c
@@ -568,6 +568,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY(__NR_bpf, sys_bpf),                                       /* 280 */
    LINX_(__NR_execveat, sys_execveat),                             /* 281 */
    LINX_(__NR_membarrier, sys_membarrier),                         /* 283 */
+   GENX_(__NR_mlock2, sys_mlock2),                                 /* 284 */
    LINX_(__NR_copy_file_range, sys_copy_file_range),               /* 285 */
    LINXY(__NR_preadv2, sys_preadv2),                               /* 286 */
    LINX_(__NR_pwritev2, sys_pwritev2),                             /* 287 */
diff --git a/include/vki/vki-scnums-riscv64-linux.h b/include/vki/vki-scnums-riscv64-linux.h
index 773fd6638..15ba9308d 100644
--- a/include/vki/vki-scnums-riscv64-linux.h
+++ b/include/vki/vki-scnums-riscv64-linux.h
@@ -293,6 +293,7 @@
 #define __NR_execveat 281
 #define __NR_userfaultfd 282
 #define __NR_membarrier 283
+#define __NR_mlock2 284
 #define __NR_copy_file_range 285
 #define __NR_preadv2 286
 #define __NR_pwritev2 287
Comment 42 Mark Wielaard 2024-12-14 02:53:10 UTC
drd/tests/condvar fails with

Other thread: waiting for notify
Other thread: notified
RISCV64 front end: standard
disInstr(riscv64): unhandled instruction 0x8330000F
disInstr(riscv64): 1000'0011 0011'0000 0000'0000 0000'1111
==1493609== valgrind: Unrecognised instruction at address 0x10bbda.
==1493609==    at 0x10BBDA: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_release_last_use() (shared_ptr_base.h:182)
==1493609==    by 0x10ADBF: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_release() (shared_ptr_base.h:311)
==1493609==    by 0x10BCAD: std::__shared_count<(__gnu_cxx::_Lock_policy)1>::~__shared_count() (shared_ptr_base.h:1071)
==1493609==    by 0x10B855: std::__shared_ptr<std::__future_base::_State_baseV2, (__gnu_cxx::_Lock_policy)1>::~__shared_ptr() (shared_ptr_base.h:1524)
==1493609==    by 0x10B875: std::shared_ptr<std::__future_base::_State_baseV2>::~shared_ptr() (shared_ptr.h:175)
==1493609==    by 0x10B895: std::__basic_future<void>::~__basic_future() (future:695)
==1493609==    by 0x10B8DD: std::future<void>::~future() (future:878)
==1493609==    by 0x10A8E1: main (condvar.cpp:55)
==1493609== Your program just tried to execute an instruction that Valgrind
==1493609== did not recognise.  There are two possible reasons for this.
==1493609== 1. Your program has a bug and erroneously jumped to a non-code
==1493609==    location.  If you are running Memcheck and you just saw a
==1493609==    warning about a bad jump, it's probably your program's fault.
==1493609== 2. The instruction is legitimate but Valgrind doesn't handle it,
==1493609==    i.e. it's Valgrind's fault.  If you think this is the case or
==1493609==    you are not sure, please let us know and we'll try to fix it.
==1493609== Either way, Valgrind will now raise a SIGILL signal which will
==1493609== probably kill your program.

This seems to be:
__atomic_thread_fence (__ATOMIC_ACQ_REL);
=> 0x000000000010bbda <+28>:	fence.tso
Comment 43 Mark Wielaard 2024-12-14 03:16:44 UTC
(In reply to Mark Wielaard from comment #42)
> drd/tests/condvar fails with
> 
> Other thread: waiting for notify
> Other thread: notified
> RISCV64 front end: standard
> disInstr(riscv64): unhandled instruction 0x8330000F
> disInstr(riscv64): 1000'0011 0011'0000 0000'0000 0000'1111
> ==1493609== valgrind: Unrecognised instruction at address 0x10bbda.
> [...]
> This seems to be:
> __atomic_thread_fence (__ATOMIC_ACQ_REL);
> => 0x000000000010bbda <+28>:	fence.tso

Assuming fence and fence.tso are basically the same thing
(which they might not be) then the following seems to fix it:

diff --git a/VEX/priv/guest_riscv64_toIR.c b/VEX/priv/guest_riscv64_toIR.c
index 93ea5a173..a4f4a1907 100644
--- a/VEX/priv/guest_riscv64_toIR.c
+++ b/VEX/priv/guest_riscv64_toIR.c
@@ -1610,7 +1610,8 @@ static Bool dis_RV64I(/*MB_OUT*/ DisResult* dres,
    }
 
    /* ------------------------ fence ------------------------ */
-   if (INSN(19, 0) == 0b00000000000000001111 && INSN(31, 28) == 0b0000) {
+   if (INSN(19, 0) == 0b00000000000000001111
+       && (INSN(31, 28) == 0b0000 || INSN(31, 28) == 0b1000)) {
       UInt succ = INSN(23, 20);
       UInt pred = INSN(27, 24);
       stmt(irsb, IRStmt_MBE(Imbe_Fence));
Comment 44 Mark Wielaard 2024-12-14 03:31:05 UTC
Both helgrind/tests/tls_threads and helgrind/tests/tls_threads2 fail because if this warning:

+WARNING: could not find symbol for var stack_cache_actsize in libpthread.so.0
+=> pthread stack cache cannot be disabled!

I thought this was fixed by:

commit 2de91d914cc5ed4ed7ea8e70d5e06c46e991f39f
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Fri Dec 23 16:49:20 2022 +0100

    Bug 444488 - Use glibc.pthread.stack_cache_size tunable
    
    Try to use GLIBC_TUNABLES to disable the pthread stack
    cache.

This machine has glibc 2.39 so should have tunable support.
$ /usr/lib/ld-linux-riscv64-lp64d.so.1 --list-tunables | grep stack_cache_size
glibc.pthread.stack_cache_size: 0x2800000 (min: 0x0, max: 0xffffffffffffffff)

So it isn't immediately clear why it tries to find the stack_cache_actsize var in libpthread.so.0
Comment 45 Richard Jones 2024-12-14 07:34:43 UTC
(In reply to Mark Wielaard from comment #35)
> integer.c:132: Error: illegal operands `la zero,0'

Are you maintaining these patches in a git repo somewhere?  It might be easier to follow that way.  I can't find the actual instance of "la zero, 0" in the patches.

Without being able to see the context, the instruction above seems unnecessary as the target register (zero) would discard the result, unless it's about testing a side effect of the load.
Comment 46 Richard Jones 2024-12-14 07:45:00 UTC
(In reply to Mark Wielaard from comment #43)
> Assuming fence and fence.tso are basically the same thing
> (which they might not be) then the following seems to fix it:

Normal memory model is Arm-like (ie. quite relaxed).  RISC-V processors with the TSO (total store ordering) extension ("Ztso") behave more like the x86 memory model.  FENCE.TSO is a fence instruction that is like FENCE but uses total store ordering.

Ztso: https://github.com/riscv/riscv-isa-manual/blob/main/src/ztso-st-ext.adoc
FENCE.TSO: https://riscv-software-src.github.io/riscv-unified-db/manual/html/isa/20240411/insts/fence.html

> diff --git a/VEX/priv/guest_riscv64_toIR.c b/VEX/priv/guest_riscv64_toIR.c
> index 93ea5a173..a4f4a1907 100644
> --- a/VEX/priv/guest_riscv64_toIR.c
> +++ b/VEX/priv/guest_riscv64_toIR.c
> @@ -1610,7 +1610,8 @@ static Bool dis_RV64I(/*MB_OUT*/ DisResult* dres,
>     }
>  
>     /* ------------------------ fence ------------------------ */
> -   if (INSN(19, 0) == 0b00000000000000001111 && INSN(31, 28) == 0b0000) {
> +   if (INSN(19, 0) == 0b00000000000000001111
> +       && (INSN(31, 28) == 0b0000 || INSN(31, 28) == 0b1000)) {
>        UInt succ = INSN(23, 20);
>        UInt pred = INSN(27, 24);
>        stmt(irsb, IRStmt_MBE(Imbe_Fence));

Does valgrind have anything like Arm vs x86 memory models?  If it does then I suspect the above will be wrong.
Comment 47 Paul Floyd 2024-12-14 11:02:20 UTC
(In reply to Richard Jones from comment #46)

> Does valgrind have anything like Arm vs x86 memory models?  If it does then
> I suspect the above will be wrong.

I don't think that the memory models really matter. Valgrind runs on a single CPU so there are no issues of ordering between threads.
Comment 48 Richard Jones 2024-12-14 11:07:29 UTC
That'll be fine in that case!
Comment 49 Paul Floyd 2024-12-14 15:39:11 UTC
(In reply to Mark Wielaard from comment #44)

> So it isn't immediately clear why it tries to find the stack_cache_actsize
> var in libpthread.so.0

--sim-hints=no-nptl-pthread-stackcache controls this. If that is set we will try two things

look for stack_cache_actsize and if we find it set the value to one billion which turns off the thread stack cache - if this is done then we don't do the next one

look for gnu_get_libc_version, call the function and print a message if the version is < 2.34.

Normally one of the two should happen. 2.34 removed the stack_cache_actsize symbol.

I think the message that you are seeing only gets output if neither are found (probably the message should be updated to reflect that).

Can you see the gnu_get_libc_version symbol in libc.so?
Comment 50 Mark Wielaard 2024-12-15 01:26:02 UTC
(In reply to Richard Jones from comment #45)
> Are you maintaining these patches in a git repo somewhere?  It might be
> easier to follow that way. 

I used the new/experimental sourceware forge to push a repo with the rebased patches:
https://forge.sourceware.org/mjw/valgrind/src/branch/riscv64-linux

git clone https://forge.sourceware.org/mjw/valgrind
cd valgrind
git switch riscv64-linux

(Note that the patches on that branch will be updated/rebased/merge this isn't the final series)

There is also a "pull request" on the forge in case people like to review it that way:
https://forge.sourceware.org/valgrind/valgrind-fork/pulls/1
Comment 51 Paul Floyd 2024-12-15 16:00:18 UTC
Everything is OK on FreeBSD.
Comment 52 Mark Wielaard 2024-12-15 17:59:32 UTC
On a fedora system I saw an issue with testcases that invoked bash, and also when running bash itself under valgrind.
It does an And1(0:I1,t6))
So an AND against False [0], which is odd in itself, since that should really have been optimized out as always being False.
But the real issue is not handling Ity_I1 (constants) in the backend.

==== SB 4680 (evchecks 98254) [tid 1] 0x1b708a fmtulong+150 /usr/bin/bash+0xaf08a

------------------------ Front end ------------------------

	(riscv64) 0x1B708A:  c.li a1, 10

              ------ IMark(0x1B708A, 2, 0) ------
              PUT(104) = 0xA:I64
              PUT(272) = 0x1B708C:I64

	(riscv64) 0x1B708C:  c.andi a4, 0x2

              ------ IMark(0x1B708C, 2, 0) ------
              PUT(128) = And64(GET:I64(128),0x2:I64)
              PUT(272) = 0x1B708E:I64

	(riscv64) 0x1B708E:  beq a4, zero, 0x1B726C

              ------ IMark(0x1B708E, 4, 0) ------
              if (CmpEQ64(GET:I64(128),GET:I64(16))) { PUT(272) = 0x1B726C:I64; exit-Boring } 
              PUT(272) = 0x1B7092:I64
              PUT(272) = GET:I64(272); exit-Boring

IRSB {
   t0:I64   t1:I64   t2:I1   t3:I64   t4:I64   t5:I64   

   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   ------ IMark(0x1B708A, 2, 0) ------
   PUT(104) = 0xA:I64
   PUT(272) = 0x1B708C:I64
   ------ IMark(0x1B708C, 2, 0) ------
   t1 = GET:I64(128)
   t0 = And64(t1,0x2:I64)
   PUT(128) = t0
   PUT(272) = 0x1B708E:I64
   ------ IMark(0x1B708E, 4, 0) ------
   t4 = GET:I64(16)
   t2 = CmpEQ64(t0,t4)
   if (t2) { PUT(272) = 0x1B726C:I64; exit-Boring } 
   PUT(272) = 0x1B7092:I64; exit-Boring
}

BlockEnd: Cond{condSX=t2, deltaSX=482, deltaFT=8}

-+-+ (ext# 1) Considering cbranch to SX=0x1B726C FT=0x1B7092 -+-+

-+-+ SPEC side exit -+-+

	(riscv64) 0x1B726C:  c.mv a0, a3

              ------ IMark(0x1B726C, 2, 0) ------
              PUT(96) = GET:I64(120)
              PUT(272) = 0x1B726E:I64

	(riscv64) 0x1B726E:  c.j 0x1B70C8

              ------ IMark(0x1B726E, 2, 0) ------
              PUT(272) = 0x1B70C8:I64
              PUT(272) = GET:I64(272); exit-Boring

IRSB {
   t0:I64   t1:I64   

   ------ IMark(0x1B726C, 2, 0) ------
   t0 = GET:I64(120)
   PUT(96) = t0
   PUT(272) = 0x1B726E:I64
   ------ IMark(0x1B726E, 2, 0) ------
   PUT(272) = 0x1B70C8:I64; exit-Boring
}

BlockEnd: Uncond{delta=62}

-+-+ SPEC fall through -+-+

	(riscv64) 0x1B7092:  c.li a5, 10

              ------ IMark(0x1B7092, 2, 0) ------
              PUT(136) = 0xA:I64
              PUT(272) = 0x1B7094:I64

	(riscv64) 0x1B7094:  beq a1, a5, 0x1B726C

              ------ IMark(0x1B7094, 4, 0) ------
              if (CmpEQ64(GET:I64(104),GET:I64(136))) { PUT(272) = 0x1B726C:I64; exit-Boring } 
              PUT(272) = 0x1B7098:I64
              PUT(272) = GET:I64(272); exit-Boring

IRSB {
   t0:I1   t1:I64   t2:I64   t3:I64   

   ------ IMark(0x1B7092, 2, 0) ------
   PUT(136) = 0xA:I64
   PUT(272) = 0x1B7094:I64
   ------ IMark(0x1B7094, 4, 0) ------
   t1 = GET:I64(104)
   t0 = CmpEQ64(t1,0xA:I64)
   if (t0) { PUT(272) = 0x1B726C:I64; exit-Boring } 
   PUT(272) = 0x1B7098:I64; exit-Boring
}

BlockEnd: Cond{condSX=t0, deltaSX=482, deltaFT=14}

-+-+ After normalisation (idiom=3) -+-+

-+-+ IRSB -+-+
IRSB {
   t0:I64   t1:I64   t2:I1   t3:I64   t4:I64   t5:I64   t6:I1   
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   ------ IMark(0x1B708A, 2, 0) ------
   PUT(104) = 0xA:I64
   PUT(272) = 0x1B708C:I64
   ------ IMark(0x1B708C, 2, 0) ------
   t1 = GET:I64(128)
   t0 = And64(t1,0x2:I64)
   PUT(128) = t0
   PUT(272) = 0x1B708E:I64
   ------ IMark(0x1B708E, 4, 0) ------
   t4 = GET:I64(16)
   t2 = CmpEQ64(t0,t4)
   t6 = Not1(t2)
   if (t6) { PUT(272) = 0x1B7092:I64; exit-Boring } 
   PUT(272) = 0x1B726C:I64; exit-Boring
}
Cond{condSX=t6, deltaSX=8, deltaFT=482}

-+-+ SX -+-+
IRSB {
   t0:I1   t1:I64   t2:I64   t3:I64   t4:I1   

   ------ IMark(0x1B7092, 2, 0) ------
   PUT(136) = 0xA:I64
   PUT(272) = 0x1B7094:I64
   ------ IMark(0x1B7094, 4, 0) ------
   t1 = GET:I64(104)
   t0 = CmpEQ64(t1,0xA:I64)
   t4 = Not1(t0)
   if (t4) { PUT(272) = 0x1B7098:I64; exit-Boring } 
   PUT(272) = 0x1B726C:I64; exit-Boring
}
Cond{condSX=t4, deltaSX=14, deltaFT=482}

-+-+ DOING &&-TRANSFORM -+-+

-+-+ FINAL RESULT -+-+

IRSB {
   t0:I64   t1:I64   t2:I1   t3:I64   t4:I64   t5:I64   t6:I1   t7:I1
   t8:I64   t9:I64   t10:I64   t11:I1   t12:I64   t13:I64   t14:I64   t15:I64
   t16:I1   

   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   IR-NoOp
   ------ IMark(0x1B708A, 2, 0) ------
   PUT(104) = 0xA:I64
   PUT(272) = 0x1B708C:I64
   ------ IMark(0x1B708C, 2, 0) ------
   t1 = GET:I64(128)
   t0 = And64(t1,0x2:I64)
   PUT(128) = t0
   PUT(272) = 0x1B708E:I64
   ------ IMark(0x1B708E, 4, 0) ------
   t4 = GET:I64(16)
   t2 = CmpEQ64(t0,t4)
   t6 = Not1(t2)
   ------ IMark(0x1B7092, 2, 0) ------
   t12 = GET:I64(136)
   t13 = ITE(t6,0xA:I64,t12)
   PUT(136) = t13
   t14 = GET:I64(272)
   t15 = ITE(t6,0x1B7094:I64,t14)
   PUT(272) = t15
   ------ IMark(0x1B7094, 4, 0) ------
   t8 = GET:I64(104)
   t7 = CmpEQ64(t8,0xA:I64)
   t11 = Not1(t7)
   t16 = And1(t11,t6)
   if (t16) { PUT(272) = 0x1B7098:I64; exit-Boring } 
   PUT(272) = 0x1B726C:I64; exit-Boring
}

GuestBytes 1B708A 14  A9 45 09 8B 63 0F 07 1C A9 47 63 8C F5 1C  0013C80E


------------------------ Instruction selection ------------------------
(evCheck) lw t0, -2040(s0); c.addiw t0, -1; sw t0, -2040(s0); bge t0, zero, 1f; ld t0, -2048(s0); c.jr 0(t0); 1:

-- ------ IMark(0x1B708A, 2, 0) ------

-- PUT(104) = 0xA:I64
li      %vR17, 0xA
sd      %vR17, -1944(s0)

-- ------ IMark(0x1B708C, 2, 0) ------

-- t0 = And64(GET:I64(128),0x2:I64)
ld      %vR19, -1920(s0)
li      %vR20, 0x2
and     %vR18, %vR19, %vR20
mv      %vR0, %vR18

-- PUT(128) = t0
sd      %vR0, -1920(s0)

-- ------ IMark(0x1B708E, 4, 0) ------

-- t6 = Not1(CmpEQ64(t0,GET:I64(16)))
ld      %vR23, -2032(s0)
sub     %vR22, %vR0, %vR23
sltiu   %vR24, %vR22, 1
sltiu   %vR21, %vR24, 1
mv      %vR6, %vR21

-- ------ IMark(0x1B7092, 2, 0) ------

-- PUT(136) = ITE(t6,0xA:I64,GET:I64(136))
li      %vR26, 0xA
ld      %vR27, -1912(s0)
(CSEL) beq %vR6, zero, 1f; c.mv %vR25, %vR26; c.j 2f; 1: c.mv %vR25, %vR27; 2:
sd      %vR25, -1912(s0)

-- PUT(272) = ITE(t6,0x1B7094:I64,0x1B708E:I64)
li      %vR29, 0x1B7094
li      %vR30, 0x1B708E
(CSEL) beq %vR6, zero, 1f; c.mv %vR28, %vR29; c.j 2f; 1: c.mv %vR28, %vR30; 2:
sd      %vR28, -1776(s0)

-- ------ IMark(0x1B7094, 4, 0) ------

-- if (And1(0:I1,t6)) { PUT(272) = 0x1B7098:I64; exit-Boring } 
vex: the `impossible' happened:
   iselIntExpr_R(riscv64)
vex storage: T total 136618504 bytes allocated
vex storage: P total 0 bytes allocated

valgrind: the 'impossible' happened:
   LibVEX called failure_exit().

host stacktrace:
==2344425==    at 0x5802029C: show_sched_status_wrk (m_libcassert.c:426)
==2344425==    by 0x5802035B: report_and_quit (m_libcassert.c:497)
==2344425==    by 0x5802049B: vgPlain_core_panic_at (m_libcassert.c:573)
==2344425==    by 0x580204B7: vgPlain_core_panic (m_libcassert.c:583)
==2344425==    by 0x58030861: failure_exit (m_translate.c:761)
==2344425==    by 0x580C9B89: vpanic (main_util.c:253)
==2344425==    by 0x580F11A3: iselIntExpr_R (host_riscv64_isel.c:1192)
==2344425==    by 0x580F1B83: iselIntExpr_R (host_riscv64_isel.c:716)
==2344425==    by 0x580F36E7: iselSB_RISCV64 (host_riscv64_isel.c:1842)
==2344425==    by 0x580C824B: LibVEX_Translate (main_main.c:1151)
==2344425==    by 0x58032685: vgPlain_translate (m_translate.c:1835)
==2344425==    by 0x5800D70F: handle_chain_me (scheduler.c:1172)
==2344425==    by 0x5800F9A1: vgPlain_scheduler (scheduler.c:1568)
==2344425==    by 0x58063A7D: run_a_thread_NORETURN (syswrap-linux.c:102)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 2344425)
==2344425==    at 0x1B708A: fmtulong (in /usr/bin/bash)
==2344425==    by 0x156961: set_ppid (in /usr/bin/bash)
==2344425==    by 0x156B73: initialize_shell_variables (in /usr/bin/bash)
==2344425==    by 0x13AF5F: ??? (in /usr/bin/bash)
==2344425==    by 0x138767: main (in /usr/bin/bash)
client stack range: [0x1FFEFFD000 0x1FFF000FFF] client SP: 0x1FFEFFF6F0
valgrind stack range: [0x10029CF000 0x1002ACEFFF] top usage: 12464 of 1048576
Comment 53 Mark Wielaard 2024-12-15 18:00:42 UTC
Fix for comment #52

diff --git a/VEX/priv/host_riscv64_isel.c b/VEX/priv/host_riscv64_isel.c
index 76fc3fd5c..6921a47db 100644
--- a/VEX/priv/host_riscv64_isel.c
+++ b/VEX/priv/host_riscv64_isel.c
@@ -1161,6 +1161,10 @@ static HReg iselIntExpr_R_wrk(ISelEnv* env, IRExpr* e)
          vassert(ty == Ity_I8);
          u = vex_sx_to_64(e->Iex.Const.con->Ico.U8, 8);
          break;
+      case Ico_U1:
+         vassert(ty == Ity_I1);
+         u = e->Iex.Const.con->Ico.U1 ? 1 : 0;
+         break;
       default:
          goto irreducible;
       }
Comment 54 Mark Wielaard 2024-12-15 21:29:18 UTC
Created attachment 176664 [details]
VEX/priv/ir_opt.c: Also fold Iop_And1 expressions when possible

Another fix for the issue seen in comment #52.
This one is more generic. I think we should just add both this one and the one from comment #53.
Either (or both together) work.
Both have been pushed to https://forge.sourceware.org/mjw/valgrind/src/branch/riscv64-linux
Comment 55 Mark Wielaard 2024-12-15 21:52:39 UTC
On a pioneer box with fedora 38, glibc-2.37-5.fc38.riscv64, GCC 14.2.0, Binutils 2.43.1, GDB 15.1 and all above patches applied:

== 743 tests, 3 stderr failures, 4 stdout failures, 0 stderrB failures, 1 stdoutB failure, 0 post failures ==
gdbserver_tests/hgtls                    (stdoutB)
memcheck/tests/linux/stack_changes       (stderr)
memcheck/tests/sh-mem-random             (stdout)
memcheck/tests/sh-mem-random             (stderr)
none/tests/nestedfns                     (stdout)
none/tests/nestedfns                     (stderr)
none/tests/riscv64/float32               (stdout)
none/tests/riscv64/float64               (stdout)

hgtls isn't clear, it seems to quit early:

+A debugging session is active.
+       Inferior 1 [Remote target] will be detached.
+Quit anyway? (y or n) [answered Y; input not from terminal]
+Detaching from program: /home/milkv/valgrind/none/tests/tls, Remote target
+Ending remote debugging.
+[Inferior 1 (Remote target) detached]

stackchange sees a lot of:

+Invalid write of size 8
+   ...
+   by 0x........: hello (stack_changes.c:20)
+ Address 0x........ is on thread 1's stack
+ in frame #0, created by __vfprintf_internal (???:)

This might just be the really old glibc?

sh-mem-random gives:

+sh-mem-random: can't mmap hi-mem

The earlier mappings do seem to work.

nestedfns fails with:

+Process terminating with default action of signal 11 (SIGSEGV)
+ Bad permissions for mapped region at address 0x........
+   at 0x........: ???
+   by 0x........: call_func (nestedfns.c:14)
+   by 0x........: test1 (nestedfns.c:23)
+   by 0x........: main (nestedfns.c:37)
+

Not sure this simply means (noexecstack) nested functions simply don't work on riscv?

--- float32.stdout.exp  2024-12-15 21:41:34.723691375 +0100
+++ float32.stdout.out  2024-12-15 22:18:50.073700974 +0100
@@ -882,7 +882,7 @@
   output: fa0=0xffffffff00000000, fcsr=0x00000000
 fmin.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff7fa00000, fcsr=0x00000000
-  output: fa0=0xffffffff00000000, fcsr=0x00000010
+  output: fa0=0xffffffff7fc00000, fcsr=0x00000010
 fmax.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff3f800000, fcsr=0x00000000
   output: fa0=0xffffffff3f800000, fcsr=0x00000000
@@ -900,7 +900,7 @@
   output: fa0=0xffffffff00000000, fcsr=0x00000000
 fmax.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff7fa00000, fcsr=0x00000000
-  output: fa0=0xffffffff00000000, fcsr=0x00000010
+  output: fa0=0xffffffff7fc00000, fcsr=0x00000010
 fcvt.w.s a0, fa0 ::
   inputs: fa0=0xffffffff00000000, fcsr=0x00000000
   output: a0=0x0000000000000000, fcsr=0x00000000

--- float32.stdout.exp  2024-12-15 21:41:34.723691375 +0100
+++ float32.stdout.out  2024-12-15 22:18:50.073700974 +0100
@@ -882,7 +882,7 @@
   output: fa0=0xffffffff00000000, fcsr=0x00000000
 fmin.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff7fa00000, fcsr=0x00000000
-  output: fa0=0xffffffff00000000, fcsr=0x00000010
+  output: fa0=0xffffffff7fc00000, fcsr=0x00000010
 fmax.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff3f800000, fcsr=0x00000000
   output: fa0=0xffffffff3f800000, fcsr=0x00000000
@@ -900,7 +900,7 @@
   output: fa0=0xffffffff00000000, fcsr=0x00000000
 fmax.s fa0, fa1, fa2 ::
   inputs: fa1=0xffffffff00000000, fa2=0xffffffff7fa00000, fcsr=0x00000000
-  output: fa0=0xffffffff00000000, fcsr=0x00000010
+  output: fa0=0xffffffff7fc00000, fcsr=0x00000010
 fcvt.w.s a0, fa0 ::
   inputs: fa0=0xffffffff00000000, fcsr=0x00000000
   output: a0=0x0000000000000000, fcsr=0x00000000

Oddly this output does match the running float32 and float64 natively.
So maybe this cpu has a buggy fmin and fmax instruction?

processor       : 0
hart            : 2
isa             : rv64imafdcv
mmu             : sv39
mvendorid       : 0x5b7
marchid         : 0x0
mimpid          : 0x0
Comment 56 Mark Wielaard 2024-12-15 23:38:24 UTC
The compressed and integer tests don't compile with gcc 13.2.0 and binutils 2.41 and produce the same error message:

gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o compressed compressed.o  
compressed.o: in function `test_compressed_10':
/home/mark/valgrind/none/tests/riscv64/compressed.c:347:(.text+0x56d22): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20

gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o integer integer.o  
integer.o: in function `test_integer_shared':
/home/mark/valgrind/none/tests/riscv64/integer.c:81:(.text+0x22cd8): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20

With gcc 13.3.0 and binutils 2.42.0 both compressed and integer don't compile but with different error messages:

gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o compressed compressed.o  
compressed.o: in function `test_compressed_10':
/home/mark/valgrind/none/tests/riscv64/compressed.c:347:(.text+0x56d22): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20

gcc -DHAVE_CONFIG_H -I. -I../../..  -I../../.. -I../../../include -I../../../coregrind -I../../../include -I../../../VEX/pub -I../../../VEX/pub -DVGA_riscv64=1 -DVGO_linux=1 -DVGP_riscv64_linux=1 -DVGPV_riscv64_linux_vanilla=1    -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector     -MT integer.o -MD -MP -MF $depbase.Tpo -c -o integer.o integer.c &&\
mv -f $depbase.Tpo $depbase.Po
integer.c: Assembler messages:
integer.c:132: Error: illegal operands `la zero,0'
integer.c:133: Error: illegal operands `la zero,0'
integer.c:134: Error: illegal operands `la zero,0'
integer.c:135: Error: illegal operands `la zero,0'
integer.c:145: Error: illegal operands `la zero,0'
integer.c:146: Error: illegal operands `la zero,0'
integer.c:147: Error: illegal operands `la zero,0'
integer.c:148: Error: illegal operands `la zero,0'
integer.c:158: Error: illegal operands `la zero,0'
integer.c:159: Error: illegal operands `la zero,0'
integer.c:160: Error: illegal operands `la zero,0'
integer.c:161: Error: illegal operands `la zero,0'
integer.c:171: Error: illegal operands `la zero,0'
integer.c:172: Error: illegal operands `la zero,0'
integer.c:173: Error: illegal operands `la zero,0'
integer.c:174: Error: illegal operands `la zero,0'
integer.c:184: Error: illegal operands `la zero,0'
integer.c:185: Error: illegal operands `la zero,0'
integer.c:186: Error: illegal operands `la zero,0'
integer.c:187: Error: illegal operands `la zero,0'
integer.c:197: Error: illegal operands `la zero,0'
integer.c:198: Error: illegal operands `la zero,0'
integer.c:199: Error: illegal operands `la zero,0'
integer.c:200: Error: illegal operands `la zero,0'

With gcc 14.2.0 and binutils 2.43.1 compressed builds (and the test passes), but integer doesn't:

depbase=`echo compressed.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -I../../..  -I../../.. -I../../../include -I../../../coregrind -I../../../include -I../../../VEX/pub -I../../../VEX/pub -DVGA_riscv64=1 -DVGO_linux=1 -DVGP_riscv64_linux=1 -DVGPV_riscv64_linux_vanilla=1    -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector     -MT compressed.o -MD -MP -MF $depbase.Tpo -c -o compressed.o compressed.c &&\
mv -f $depbase.Tpo $depbase.Po
gcc -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector       -o compressed compressed.o  

depbase=`echo integer.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -I../../..  -I../../.. -I../../../include -I../../../coregrind -I../../../include -I../../../VEX/pub -I../../../VEX/pub -DVGA_riscv64=1 -DVGO_linux=1 -DVGP_riscv64_linux=1 -DVGPV_riscv64_linux_vanilla=1    -Winline -Wall -Wshadow -Wno-long-long -g -fno-stack-protector     -MT integer.o -MD -MP -MF $depbase.Tpo -c -o integer.o integer.c &&\
mv -f $depbase.Tpo $depbase.Po
integer.c: Assembler messages:
integer.c:132: Error: illegal operands `la zero,0'
integer.c:133: Error: illegal operands `la zero,0'
integer.c:134: Error: illegal operands `la zero,0'
integer.c:135: Error: illegal operands `la zero,0'
integer.c:145: Error: illegal operands `la zero,0'
integer.c:146: Error: illegal operands `la zero,0'
integer.c:147: Error: illegal operands `la zero,0'
integer.c:148: Error: illegal operands `la zero,0'
integer.c:158: Error: illegal operands `la zero,0'
integer.c:159: Error: illegal operands `la zero,0'
integer.c:160: Error: illegal operands `la zero,0'
integer.c:161: Error: illegal operands `la zero,0'
integer.c:171: Error: illegal operands `la zero,0'
integer.c:172: Error: illegal operands `la zero,0'
integer.c:173: Error: illegal operands `la zero,0'
integer.c:174: Error: illegal operands `la zero,0'
integer.c:184: Error: illegal operands `la zero,0'
integer.c:185: Error: illegal operands `la zero,0'
integer.c:186: Error: illegal operands `la zero,0'
integer.c:187: Error: illegal operands `la zero,0'
integer.c:197: Error: illegal operands `la zero,0'
integer.c:198: Error: illegal operands `la zero,0'
integer.c:199: Error: illegal operands `la zero,0'
integer.c:200: Error: illegal operands `la zero,0'
Comment 57 Mark Wielaard 2024-12-16 00:36:43 UTC
make regtest (all above patches applied and integer and compressed tests disabled) on a visionfive 2
with gcc 13.2.0, binutils 2.41 and glibc 2.38

== 744 tests, 3 stderr failures, 2 stdout failures, 0 stderrB failures, 1 stdoutB failure, 0 post failures ==
gdbserver_tests/hgtls                    (stdoutB)
memcheck/tests/sh-mem-random             (stdout)
memcheck/tests/sh-mem-random             (stderr)
drd/tests/pth_mutex_signal               (stderr)
none/tests/nestedfns                     (stdout)
none/tests/nestedfns                     (stderr)

pth_mutex_signal seems flaky, it sometimes succeeds and sometimes the thread handles the signal runs before the thread that goes to sleep.

--- pth_mutex_signal.stderr.exp	2024-12-15 22:34:02.188892832 +0000
+++ pth_mutex_signal.stderr.out	2024-12-16 00:02:50.293423348 +0000
@@ -4,8 +4,8 @@
 thread created
 sleeping
 signalling
-sleeping
 nullHandler running
+sleeping
 unlocking
 contender locked mutex
 contender unlocking mutex

All other tests fail as above on the Sophon Sg2042 (except that stack_changes, float32 and float64 pass on this setup)
Comment 58 Mark Wielaard 2024-12-16 00:38:31 UTC
And on the p550 with gcc 13.3.0, binutils 2.42.0 and glibc 2.39:

== 744 tests, 4 stderr failures, 1 stdout failure, 0 stderrB failures, 1 stdoutB failure, 0 post failures ==
gdbserver_tests/hgtls                    (stdoutB)
helgrind/tests/tls_threads               (stderr)
helgrind/tests/tls_threads2              (stderr)
drd/tests/pth_mutex_signal               (stderr)
none/tests/nestedfns                     (stdout)
none/tests/nestedfns                     (stderr)
Comment 59 Mark Wielaard 2024-12-20 23:00:17 UTC
(In reply to Mark Wielaard from comment #39)
> Created attachment 176588 [details]
> close_range fd as Int
> 
> The double_close_range failure seems to be because the close_range wrapper
> is using unsigned int and the ARG regwords directly. Which causes the ARG2
> == ~0U check to fail. Explicitly using Int for the fd arguments seems to fix
> it. I am not clear on why this was only an issue for the riscv port. It
> seems this patch is OK for other arches (tested on amd64 and i386).

I pushed this patch directly to valgrind trunk.
Comment 60 Mark Wielaard 2024-12-20 23:34:58 UTC
(In reply to Mark Wielaard from comment #55) 
> nestedfns fails with:
> 
> +Process terminating with default action of signal 11 (SIGSEGV)
> + Bad permissions for mapped region at address 0x........
> +   at 0x........: ???
> +   by 0x........: call_func (nestedfns.c:14)
> +   by 0x........: test1 (nestedfns.c:23)
> +   by 0x........: main (nestedfns.c:37)
> +
> 
> Not sure this simply means (noexecstack) nested functions simply don't work
> on riscv?

This isn't riscv specific. It also fails on other arches.
Seems to be caused by:

commit c5552fe28b8d89ed5a92cc736fa00d7e336a3f2c
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Fri Dec 6 21:24:50 2024 +0100

    regtest: fix a warning building none/tests/nestedfns on some platforms

diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 53a6e1f6bc95..fa0128d3a8e4 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -335,6 +335,7 @@ endif
 
 if HAVE_NESTED_FUNCTIONS
    check_PROGRAMS += nestedfns
+   nestedfns_LDFLAGS = -Wl,-z,noexecstack
 endif
 
 # This doesn't appear to be compilable on Darwin.

So this sets noexecstack for the nestedfns exec.
But as the comment at the top of nestedfns says:

/* This is a test program from Lee Kindness which used to fail on V
   because gcc implements the nested function mumbo jumbo using self
   modifying code on the stack, at least on x86 and amd64.  It now
   works transparently because by default V now generates
   self-checking translations for translations taken from stack-like
   segments.
*/

And indeed even on amd64-linux this program now crashes even when not run under valgrind:

Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffd9d0 in ?? ()
(gdb) where
#0  0x00007fffffffd9d0 in ?? ()
#1  0x0000000000401138 in call_func (sel=0x7fffffffd9d0) at nestedfns.c:14
#2  0x0000000000401196 in test1 () at nestedfns.c:23
#3  0x000000000040120b in main (argc=1, argv=0x7fffffffdb48) at nestedfns.c:37

And that is indeed the sel function stub on the stack...

Paul, what was the warning? And can we just accept that warning?
Reverting this seems to make the test work again as expected.
Comment 61 Mark Wielaard 2024-12-21 01:05:09 UTC
(In reply to Mark Wielaard from comment #54)
> Created attachment 176664 [details]
> VEX/priv/ir_opt.c: Also fold Iop_And1 expressions when possible
> 
> Another fix for the issue seen in comment #52.
> This one is more generic.

I have pushed this to one directly to valgrind trunk.
Comment 62 Paul Floyd 2024-12-21 16:21:50 UTC
(In reply to Mark Wielaard from comment #60)
> (In reply to Mark Wielaard from comment #55) 
> > nestedfns fails with:
> > 
> > +Process terminating with default action of signal 11 (SIGSEGV)
> > + Bad permissions for mapped region at address 0x........
> > +   at 0x........: ???
> > +   by 0x........: call_func (nestedfns.c:14)
> > +   by 0x........: test1 (nestedfns.c:23)
> > +   by 0x........: main (nestedfns.c:37)
> > +
> > 
> > Not sure this simply means (noexecstack) nested functions simply don't work
> > on riscv?
> 
> This isn't riscv specific. It also fails on other arches.
> Seems to be caused by:
> 
> commit c5552fe28b8d89ed5a92cc736fa00d7e336a3f2c
> Author: Paul Floyd <pjfloyd@wanadoo.fr>
> Date:   Fri Dec 6 21:24:50 2024 +0100
> 
>     regtest: fix a warning building none/tests/nestedfns on some platforms
> 
> diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
> index 53a6e1f6bc95..fa0128d3a8e4 100644
> --- a/none/tests/Makefile.am
> +++ b/none/tests/Makefile.am
> @@ -335,6 +335,7 @@ endif
>  
>  if HAVE_NESTED_FUNCTIONS
>     check_PROGRAMS += nestedfns
> +   nestedfns_LDFLAGS = -Wl,-z,noexecstack
>  endif
>  
>  # This doesn't appear to be compilable on Darwin.
> 
> So this sets noexecstack for the nestedfns exec.
> But as the comment at the top of nestedfns says:
> 
> /* This is a test program from Lee Kindness which used to fail on V
>    because gcc implements the nested function mumbo jumbo using self
>    modifying code on the stack, at least on x86 and amd64.  It now
>    works transparently because by default V now generates
>    self-checking translations for translations taken from stack-like
>    segments.
> */
> 
> And indeed even on amd64-linux this program now crashes even when not run
> under valgrind:
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007fffffffd9d0 in ?? ()
> (gdb) where
> #0  0x00007fffffffd9d0 in ?? ()
> #1  0x0000000000401138 in call_func (sel=0x7fffffffd9d0) at nestedfns.c:14
> #2  0x0000000000401196 in test1 () at nestedfns.c:23
> #3  0x000000000040120b in main (argc=1, argv=0x7fffffffdb48) at
> nestedfns.c:37
> 
> And that is indeed the sel function stub on the stack...
> 
> Paul, what was the warning? And can we just accept that warning?
> Reverting this seems to make the test work again as expected.

On arm raspberrypios

/usr/bin/ld: warning: nestedfns-nestedfns.o: requires executable stack (because the .note.GNU-stack section is executable)

but the exe runs OK

No problem on FreeBSD because this is a non-standard GCC extension that clang doesn't accept.

I've pushed a fix that turns off the warning rather than turning off the exec stack.
Comment 63 Mark Wielaard 2024-12-21 22:40:57 UTC
(In reply to Paul Floyd from comment #62)
> I've pushed a fix that turns off the warning rather than turning off the
> exec stack.

Thanks. That resolves two more failures. Only a handful left.
Comment 64 Mark Wielaard 2024-12-21 23:26:22 UTC
Comment on attachment 176588 [details]
close_range fd as Int

This patch is now pushed to trunk as:

commit d984d9aabe5b89d6787c2604b72c09360e7b6fc0
Author: Mark Wielaard <mark@klomp.org>
Date:   Sat Dec 14 22:34:12 2024 +0000

    Use Ints for fds in PRE and POST sys_close_range
    
    The double_close_range test failed on riscv64-linux because the
    close_range wrapper is using unsigned int and the ARG regwords
    directly. Which causes the ARG2 == ~0U check to fail. Explicitly
    using Int for the fd arguments fixes this. I am not clear on why
    this was only an issue for the riscv port. It seems this patch is
    OK for other arches (tested on amd64 and i386).
Comment 65 Mark Wielaard 2024-12-21 23:27:37 UTC
Comment on attachment 176664 [details]
VEX/priv/ir_opt.c: Also fold Iop_And1 expressions when possible

This patch is now pushed to trunk as:

commit 1f8a81cc2493670a82334bd5b4bc1ffa6d02174b
Author: Mark Wielaard <mark@klomp.org>
Date:   Sun Dec 15 21:26:21 2024 +0100

    VEX/priv/ir_opt.c: Also fold Iop_And1 expressions when possible
    
    Treat Iop_And1 just like And16/And32/And64. Fold fully constant And1
    expressions and handle And1(x,True), And1(True,x), And1(x,False),
    And1(False,x) and And1(x,x).
    
    Make sure isOnesU handles Ico_U1 (isZerosU and sameIRExprs already
    did).
    
    https://bugs.kde.org/show_bug.cgi?id=468575#c52
Comment 66 Mark Wielaard 2024-12-21 23:30:14 UTC
Created attachment 176810 [details]
riscv64: Add initial support: new port-specific Valgrind files

Rebased and added the following fixups:
- Remove POST handler from sys_close
- Define VKI_O_DIRECT in vki-riscv64-linux.h
- Wrap riscv64-linux mlock2
- Add POST handler for sys_readlinkat
Comment 67 Mark Wielaard 2024-12-21 23:32:01 UTC
Created attachment 176811 [details]
riscv64: Add initial support: new port-specific VEX files

Rebased and added the following fixup:
- Handle Ity_I1, Iex.Const (boolean)
Comment 68 Mark Wielaard 2024-12-21 23:33:51 UTC
Created attachment 176812 [details]
riscv64: Add initial support: new port-specific test

Rebased
Comment 69 Mark Wielaard 2024-12-21 23:39:08 UTC
Created attachment 176813 [details]
riscv64: Add initial support: Valgrind modifications

Rebased
Comment 70 Mark Wielaard 2024-12-21 23:40:21 UTC
Created attachment 176814 [details]
riscv64: Add initial support: VEX modifications

Rebased
Comment 71 Mark Wielaard 2024-12-21 23:43:46 UTC
Created attachment 176815 [details]
riscv64: Add initial support: test modifications

Rebase and add fixup:
- helgrind/tests/tc11_XCHG.c: Fix XCHG_M_R guard
Comment 72 Mark Wielaard 2024-12-21 23:48:55 UTC
Created attachment 176816 [details]
Disable none/tests/riscv64 compressed and integer builds and test

Till we can figure out what the correct configure checks are for
building them.

Both produce Assembler messages: Error: illegal operands 'la zero,0'
Comment 73 Mark Wielaard 2024-12-21 23:50:02 UTC
Created attachment 176817 [details]
VEX/priv/guest_riscv64_toIR.c: Recognize both fence and fence.tso

fence.tso is used for __atomic_thread_fence (__ATOMIC_ACQ_REL)
Comment 74 Mark Wielaard 2024-12-21 23:54:19 UTC
Rebased patches also pushed here:
https://forge.sourceware.org/mjw/valgrind/src/branch/riscv64-linux

We really have to figure out why/how to build the integer and compressed testcases.
The fence.tso patch is needed, but might be done a little nicer.
Comment 75 Mark Wielaard 2024-12-22 22:43:49 UTC
Trying to figure out:
integer.c: Assembler messages:
integer.c:132: Error: illegal operands `la zero,0'

integer.c:132 is:
   TESTINST_0_2_Bxx_COND(4, "beq a0, zero, 1f", 0, 0, a0, zero);

TESTINST_0_2_Bxx_COND defined in testinst.h:
#define TESTINST_0_2_Bxx_COND(length, instruction, rs1_val, rs2_val, rs1, rs2) \
   JMP_COND(length, instruction, #rs1_val, #rs2_val, rs1, rs2)

#define JMP_COND(length, instruction, rs1_val, rs2_val, rs1, rs2)              \
   {                                                                           \
      unsigned long w[3 /*out*/ + 2 /*spill*/] = {0, 0, 0, 0, 0};              \
      /* w[0] = flag that the branch was taken                                 \
         w[1] = flag that rs1 is valid                                         \
         w[2] = flag that rs2 is valid                                         \
         w[3] = spill slot for rs1                                             \
         w[4] = spill slot for rs2                                             \
       */                                                                      \
      register unsigned long* t1 asm("t1") = w;                                \
      __asm__ __volatile__(                                                    \
         "li t2, 1;"                                                           \
         "sd t2, 0(%[w]);"             /* Set result to "taken". */            \
         ".if \"" #rs1 "\" != \"unused\";"                                     \
         "sd " #rs1 ", 24(%[w]);"      /* Spill rs1. */                        \
         "la " #rs1 ", " rs1_val ";"   /* Load the first input. */             \
         ".endif;"                                                             \
         ".if \"" #rs2 "\" != \"unused\";"                                     \
         "sd " #rs2 ", 32(%[w]);"      /* Spill rs2. */                        \
         "la " #rs2 ", " rs2_val ";"   /* Load the second input. */            \
         ".endif;"                                                             \
         ASMINST_##length(instruction) ";"                                     \
         "li t2, 0;"                                                           \
         "sd t2, 0(%[w]);"             /* Set result to "not taken". */        \
         "1:;"                                                                 \
         ".if \"" #rs1 "\" != \"unused\";"                                     \
         "li t2, 1;"                                                           \
         "sd t2, 8(%[w]);"             /* Flag that rs1 is valid. */           \
         ".endif;"                                                             \
         ".if \"" #rs2 "\" != \"unused\";"                                     \
         "li t2, 1;"                                                           \
         "sd t2, 16(%[w]);"            /* Flag that rs2 is valid. */           \
         ".endif;"                                                             \
         ".if \"" #rs1 "\" != \"unused\";"                                     \
         "ld " #rs1 ", 24(%[w]);"      /* Reload rs1. */                       \
         ".endif;"                                                             \
         ".if \"" #rs2 "\" != \"unused\";"                                     \
         "ld " #rs2 ", 32(%[w]);"      /* Reload rs2. */                       \
         ".endif;"                                                             \
         :                                                                     \
         : [w] "r"(t1)                                                         \
         : "t2", "memory");                                                    \
      printf("%s ::\n", instruction);                                          \
      if (w[1] != 0) { /* If rs1 is valid. */                                  \
         printf("  inputs: %s=%s", #rs1, rs1_val);                             \
         if (w[2] != 0) /* If rs2 is valid. */                                 \
            printf(", %s=%s", #rs2, rs2_val);                                  \
         printf("\n");                                                         \
      }                                                                        \
      printf("  branch: %s\n", w[0] ? "taken" : "not taken");                  \
   }

So it looks like this line:

         "la " #rs2 ", " rs2_val ";"   /* Load the second input. */            \

rs2 = zero and rs2_val = 0

Producing

"la zero, 0;"

So that is a write to the zero register of 0.
Which should be legal? The zero register should ignore writes?
Comment 76 Mark Wielaard 2024-12-23 00:02:10 UTC
Created attachment 176828 [details]
integer.c: replace zero by a1

Simplest seems to be to replace the usage of "zero" in the branch instruction tests by "a1".
It seems that does test something similar that isn't tested before.
With this patch the integer testcase compiles, links (*) and the passes regtest.
Does anybody knowing riscv assembly/instructions know whether the tests against the zero register should also work?
And if so, if there is a way to write them in gas assembly?

(*) links with binutils ld >= 2.43, with 2.42 or 2.41 it produces:
/home/mark/valgrind/none/tests/riscv64/integer.c:81:(.text+0x22cd8): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20

Similar to compress with older binutils. (It also does compiles, links and passes with binutils 2.43.1)
Comment 77 Mark Wielaard 2024-12-23 17:03:17 UTC
Filed a binutils gas bug to ask about "la zero, 0;" being legal or not
https://sourceware.org/bugzilla/show_bug.cgi?id=32496
Comment 78 Mark Wielaard 2024-12-24 17:56:17 UTC
(In reply to JojoR from comment #10)
> (In reply to Petr Pavlu from comment #9)
> > (In reply to Paul Floyd from comment #8)
> > > Are the other failures "reaonable"?
> > 
> > > memcheck/tests/sh-mem-random             (stdout)
> > > memcheck/tests/sh-mem-random             (stderr)
> > 
> > Another unexpected mmap() failure.
> 
> From our investigation, high address mmap is not supported by some riscv
> board/os if it support feature "Sv39" only,
> so it is reasonable also :)

Found that there are there are other arches that restrict highest user space address, so I propose the following patch which makes sh-mem-random pass on the risc-v systems I have access to and still seems a reasonable value for other arches:

diff --git a/memcheck/tests/sh-mem-random.c b/memcheck/tests/sh-mem-random.c
index ae82248ae690..0e01684acb61 100644
--- a/memcheck/tests/sh-mem-random.c
+++ b/memcheck/tests/sh-mem-random.c
@@ -247,7 +247,10 @@ int main(void)
       int nbytes_p;
       // (U1*)(UWord)constULL funny casting to keep gcc quiet on
       // 32-bit platforms
-      U1* huge_addr = (U1*)(UWord)0x6600000000ULL;  // 408GB
+      // https://www.kernel.org/doc/html/next/riscv/vm-layout.html
+      // Says RISC-V Linux Kernel SV39 user-space virtual memory
+      // ends at 256GB. So try at 240GB.
+      U1* huge_addr = (U1*)(UWord)0x3c00000000ULL;  // 240GB
       // Note, kernel 2.6.? on Athlon64 refuses fixed mmap requests
       // at above 512GB.
Comment 79 Mark Wielaard 2024-12-24 18:10:07 UTC
Created attachment 176870 [details]
VEX/priv/guest_riscv64_toIR.c: Recognize both fence and fence.tso

Cleaned up fence.tso patch. Can probably be pushed on top of existing patches (to fix drd/tests/condvar)
Comment 80 Mark Wielaard 2024-12-25 18:16:38 UTC
I keep hitting

compressed.o: in function `test_compressed_10':
/home/mark/valgrind/none/tests/riscv64/compressed.c:347:(.text+0x56d26): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20
collect2: error: ld returned 1 exit status

and 

integer.o: in function `test_integer_shared':
/home/mark/valgrind/none/tests/riscv64/integer.c:81:(.text+0x22cdc): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20
collect2: error: ld returned 1 exit status

I thought this was something fixed with gcc14 and/or binutils-2.43 but on some setups I am still getting the above.
Comment 81 Mark Wielaard 2024-12-25 18:23:55 UTC
(In reply to Mark Wielaard from comment #78)
> Found that there are there are other arches that restrict highest user space
> address, so I propose the following patch which makes sh-mem-random pass on
> the risc-v systems I have access to and still seems a reasonable value for
> other arches:
> 
> diff --git a/memcheck/tests/sh-mem-random.c b/memcheck/tests/sh-mem-random.c
> index ae82248ae690..0e01684acb61 100644
> --- a/memcheck/tests/sh-mem-random.c
> +++ b/memcheck/tests/sh-mem-random.c
> @@ -247,7 +247,10 @@ int main(void)
>        int nbytes_p;
>        // (U1*)(UWord)constULL funny casting to keep gcc quiet on
>        // 32-bit platforms
> -      U1* huge_addr = (U1*)(UWord)0x6600000000ULL;  // 408GB
> +      // https://www.kernel.org/doc/html/next/riscv/vm-layout.html
> +      // Says RISC-V Linux Kernel SV39 user-space virtual memory
> +      // ends at 256GB. So try at 240GB.
> +      U1* huge_addr = (U1*)(UWord)0x3c00000000ULL;  // 240GB
>        // Note, kernel 2.6.? on Athlon64 refuses fixed mmap requests
>        // at above 512GB.

Pushed this as:

commit 738af55f1b12a06f76943ca4afb9ba9ec3603ea5 (HEAD -> master, origin/master, origin/HEAD)
Author: Mark Wielaard <mark@klomp.org>
Date:   Tue Dec 24 19:11:17 2024 +0100

    memcheck/tests/sh-mem-random.c: Set huge_addr to 240GB
    
    https://www.kernel.org/doc/html/next/riscv/vm-layout.html
    Says RISC-V Linux Kernel SV39 user-space virtual memory ends at 256GB.
    So try at 240GB. This seems a reasonable value for other arches too.
    
    https://bugs.kde.org/show_bug.cgi?id=468575#c78
Comment 82 Mark Wielaard 2024-12-26 12:23:17 UTC
Created attachment 176883 [details]
riscv64: syswrap various shared linux syscalls

syswrap-riscv64-linux.c: Hook up open_tree, move_mount, fsopen,
fsconfig, fsmount, fspick, pidfd_open, openat2, pidfd_getfd,
epoll_pwait2, landlock_create_ruleset, landlock_add_rule,
landlock_restrict_self and fchmodat2.
Comment 83 Mark Wielaard 2024-12-28 00:40:30 UTC
Created attachment 176918 [details]
riscv64: Add hardwire for ld-linux-riscv64-lp64d.so.1 strcmp

When using dlopen ld.so can end up in glibc strcmp_unaligned_loop
which causes undefined reads. Hardwire strcmp for ld.so with a simple
assembly implementation.