Bug 476548 - valgrind 3.22.0 fails on assertion when loading debuginfo file produced by mold
Summary: valgrind 3.22.0 fails on assertion when loading debuginfo file produced by mold
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: 3.22 GIT
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Paul Floyd
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-11-04 14:03 UTC by Jan Palus
Modified: 2023-12-05 23:00 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Palus 2023-11-04 14:03:07 UTC
SUMMARY
After valgrind upgrade to 3.22.0 it started failing with:

valgrind: m_debuginfo/readelf.c:3394 (vgModuleLocal_read_elf_debug): Assertion 'di->rodata_size == a_shdr.sh_size' failed.

when loading debuginfo file produced with mold 2.3.1. Binaries linked with bfd/lld work fine.

valgrind 3.21.0 works fine.

Also raised in mold under https://github.com/rui314/mold/issues/1139 as it's not clear who is to blame.

STEPS TO REPRODUCE
1. Build sample c++ binary with debug symbols and link with mold:
g++ -x c++ -g2 -fuse-ld=mold -o test - <<EOF
#include <iostream>

int main() {
    std::cout << "hello world" << std::endl;
}
EOF
2. Create debuginfo file:
eu-strip -f test.di test
3. Run valgrind against binary:
valgrind -v ./test

OBSERVED RESULT

valgrind fails:

...
--413198--   Considering /home/users/builder/test.di ..
--413198--   .. CRC is valid

valgrind: m_debuginfo/readelf.c:3394 (vgModuleLocal_read_elf_debug): Assertion 'di->rodata_size == a_shdr.sh_size' failed.
...


EXPECTED RESULT

valgrind works fine
Comment 1 Paul Floyd 2023-11-04 17:12:29 UTC
This changed fairly recently. If possible use Valgrind 3.21 while we look for a fix.
Comment 2 Paul Floyd 2023-11-07 12:14:45 UTC
Does this occur when you don't strip the binary?

The FreeBSD mold package is marked as broken due to an issue with strip (though that issue is with the mold exe).
Comment 3 Jan Palus 2023-11-07 14:26:35 UTC
I've done some debugging and possibly found the culprit.

The assertion di->rodata_size == a_shdr.sh_size failed because left hand side was 8 while the other was 3. However in readelf output for both stripped binary and debuginfo file I see rodata size as 3. So assumed right hand side must be correct. So I've checked why valgrind thinks it's 8 for debuginfo file and found this:

2482       if (0 == VG_(strncmp)(name, ".rodata", 7)) {
2483          if ((inrx||inrw1) && !di->rodata_present) { /* first .rodata* */
2484             di->rodata_svma = svma;
2485             di->rodata_avma = svma;
2486             di->rodata_size = size;
2487             di->rodata_debug_svma = svma;
2488          } else if ((inrx||inrw1) && di->rodata_present) { /* not first .rodata* */
2489             Addr tmp = VG_ROUNDUP(di->rodata_size + di->rodata_svma, alyn);
2490             if (svma == tmp) { /* adjacent to previous .rodata* */
2491                di->rodata_size = size + tmp - di->rodata_svma;
2492             } else {
2493                BAD(".rodata"); /* is OK, but we cannot handle multiple .rodata* */
2494             }
2495          }

https://sourceware.org/git/?p=valgrind.git;a=blob;f=coregrind/m_debuginfo/readelf.c;h=fb64ed9769d28e7f64762c8a34ebab8e353bc21f;hb=HEAD#l2482

It extends rodata_size with size of adjacent sections with name starting with ".rodata".

Both debuginfo and stripped binary have adjacent .rodata and .rodata.cst4 sections with size 3 and 4 respectively which I believe after aligning make 8:

  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [12] .rodata           PROGBITS        000000000020059c 00059c 000003 00   A  0   0  1
  [13] .rodata.cst4      PROGBITS        00000000002005a0 0005a0 000004 04  AM  0   0  4

I would assume same logic for accumulating size is not reflected here:

https://sourceware.org/git/?p=valgrind.git;a=blob;f=coregrind/m_debuginfo/readelf.c;h=fb64ed9769d28e7f64762c8a34ebab8e353bc21f;hb=HEAD#l3362
Comment 4 Paul Floyd 2023-11-08 09:12:16 UTC
Looks plausible. We might need to break out that FIND macro into an (inline) function if it also needs to be looking for contiguous rodata segments.
Comment 5 Paul Floyd 2023-11-09 08:08:35 UTC
Confirmed on Fedora 38 with Valgrind 3.21 (works) and git head (fails).
Comment 6 Paul Floyd 2023-11-18 08:15:17 UTC
commit 9ea4ae66707a4dcc6f4328e11911652e4418c585 (HEAD -> master, origin/users/paulf/try-bug476548, origin/master, origin/HEAD, bug476548)
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Sat Nov 18 08:49:34 2023 +0100

    Bug 476548 - valgrind 3.22.0 fails on assertion when loading debuginfo file produced by mold
Comment 7 Jan Palus 2023-11-18 13:05:57 UTC
Confirmed the fix works fine. Thanks!
Comment 8 Mark Wielaard 2023-12-05 11:50:44 UTC
Found the same issue on Fedora 38 while loading /usr/lib64/ossl-modules/fips.so which has:

[16] .rodata              PROGBITS     0000000000105000 00105000 0000fa90  0 A  
    0   0 64
[17] .rodata1             PROGBITS     0000000000114aa0 00114aa0 00000020  0 A  
    0   0 32

commit 9ea4ae66707a4dcc6f4328e11911652e4418c585 fixes it

We might want to backport this to the VALGRIND_3_22_BRANCH
Comment 9 Mark Wielaard 2023-12-05 23:00:27 UTC
Also pushed to VALGRIND_3_22_BRANCH as:

commit 1d00e5ce0fb069911c4b525ec38289fb5d9021b0
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Sat Nov 18 08:49:34 2023 +0100

    Bug 476548 - valgrind 3.22.0 fails on assertion when loading debuginfo file produced by mold
    
    (cherry picked from commit 9ea4ae66707a4dcc6f4328e11911652e4418c585)