Bug 491394 - (vgModuleLocal_addDiCfSI): Assertion 'di->fsm.have_rx_map && di->fsm.rw_map_count' failed.
Summary: (vgModuleLocal_addDiCfSI): Assertion 'di->fsm.have_rx_map && di->fsm.rw_map_c...
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: 3.23.0
Platform: Other Linux
: NOR minor
Target Milestone: ---
Assignee: Paul Floyd
URL:
Keywords:
: 396476 (view as bug list)
Depends on:
Blocks:
 
Reported: 2024-08-07 14:46 UTC by Leah Neukirchen
Modified: 2024-08-26 06:44 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
Binary triggering the assertion failure (9.09 KB, application/x-executable)
2024-08-07 14:46 UTC, Leah Neukirchen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Leah Neukirchen 2024-08-07 14:46:12 UTC
Created attachment 172371 [details]
Binary triggering the assertion failure

SUMMARY

I managed to trigger this assertion by creating a C program that directly implements _start.  This may be out of scope for Valgrind, but other small programs directly written in assembler (with nasm) work under it, so please consider.

STEPS TO REPRODUCE
```
% cat foo.c
void _start() {
	_exit(0);
}
% gcc -v -o foo foo.c -nostdlib -lc -static -Os
...
gcc version 13.2.0 (GCC) 
...
% valgrind ./foo
==5452== Memcheck, a memory error detector
==5452== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==5452== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==5452== Command: ./foo
==5452== 

valgrind: m_debuginfo/storage.c:796 (vgModuleLocal_addDiCfSI): Assertion 'di->fsm.have_rx_map && di->fsm.rw_map_count' failed.
zsh: segmentation fault  valgrind ./foo
```

(Binary is attached.)

OBSERVED RESULT

Valgrind crashes with assertion failure.

EXPECTED RESULT

Valgrind runs the program which exits immediately.

SOFTWARE/OS VERSIONS

valgrind-3.23.0
Linux 6.9.5 x86_64 glibc

ADDITIONAL INFORMATION

Perhaps relevant:
```
% readelf -a foo 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x401000
  Start of program headers:          64 (bytes into file)
  Start of section headers:          8672 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         10
  Section header string table index: 9

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.gnu.pr[...] NOTE             0000000000400200  00000200
       0000000000000030  0000000000000000   A       0     0     8
  [ 2] .note.gnu.bu[...] NOTE             0000000000400230  00000230
       0000000000000024  0000000000000000   A       0     0     4
  [ 3] .text             PROGBITS         0000000000401000  00001000
       0000000000000034  0000000000000000  AX       0     0     16
  [ 4] .eh_frame         PROGBITS         0000000000402000  00002000
       0000000000000044  0000000000000000   A       0     0     8
  [ 5] .tbss             NOBITS           0000000000403000  00002044
       0000000000000004  0000000000000000 WAT       0     0     4
  [ 6] .comment          PROGBITS         0000000000000000  00002044
       0000000000000012  0000000000000001  MS       0     0     1
  [ 7] .symtab           SYMTAB           0000000000000000  00002058
       00000000000000f0  0000000000000018           8     2     8
  [ 8] .strtab           STRTAB           0000000000000000  00002148
       0000000000000038  0000000000000000           0     0     1
  [ 9] .shstrtab         STRTAB           0000000000000000  00002180
       0000000000000060  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000254 0x0000000000000254  R      0x1000
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x0000000000000034 0x0000000000000034  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000
                 0x0000000000000044 0x0000000000000044  R      0x1000
  NOTE           0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x0000000000000030 0x0000000000000030  R      0x8
  NOTE           0x0000000000000230 0x0000000000400230 0x0000000000400230
                 0x0000000000000024 0x0000000000000024  R      0x4
  TLS            0x0000000000002044 0x0000000000403000 0x0000000000403000
                 0x0000000000000000 0x0000000000000004  R      0x4
  GNU_PROPERTY   0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x0000000000000030 0x0000000000000030  R      0x8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.property .note.gnu.build-id 
   01     .text 
   02     .eh_frame 
   03     .note.gnu.property 
   04     .note.gnu.build-id 
   05     .tbss 
   06     .note.gnu.property 
   07     

There is no dynamic section in this file.

There are no relocations in this file.
No processor specific unwind information to decode

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo.c
     2: 0000000000000000     4 TLS     GLOBAL DEFAULT    5 errno
     3: 0000000000401010    36 FUNC    WEAK   DEFAULT    3 _Exit
     4: 0000000000401000     8 FUNC    GLOBAL DEFAULT    3 _start
     5: 0000000000000000     4 TLS     GLOBAL HIDDEN     5 __libc_errno
     6: 0000000000403000     0 NOTYPE  GLOBAL DEFAULT    4 __bss_start
     7: 0000000000403000     0 NOTYPE  GLOBAL DEFAULT    4 _edata
     8: 0000000000403000     0 NOTYPE  GLOBAL DEFAULT    4 _end
     9: 0000000000401010    36 FUNC    GLOBAL HIDDEN     3 _exit

No version information found in this file.

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000020	NT_GNU_PROPERTY_TYPE_0
      Properties: x86 feature used: x86
	x86 ISA used: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: f317ecf6b96dc58f1e331a97a66e54b49afdf923
```
Comment 1 Paul Floyd 2024-08-08 05:08:05 UTC
I’ll take a look when l get back from holidays.
Comment 2 Paul Floyd 2024-08-19 19:38:15 UTC
I have no problem on FreeBSD. I think that the issue is the Linux ld.bfd isn't generating a RW PT_LOAD and Valgrind is expecting at least 1.
Comment 3 Paul Floyd 2024-08-19 20:11:12 UTC
If you can build Valgrind from source, can you try this diff please?

diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
index 148de6f17..ef6a40051 100644
--- a/coregrind/m_debuginfo/storage.c
+++ b/coregrind/m_debuginfo/storage.c
@@ -793,7 +793,7 @@ void ML_(addDiCfSI) ( struct _DebugInfo* di,
                    "warning: DiCfSI %#lx .. %#lx is huge; length = %u (%s)\n",
                    base, base + len - 1, len, di->soname);
 
-   vg_assert(di->fsm.have_rx_map && di->fsm.rw_map_count);
+   vg_assert(di->fsm.have_rx_map);
    /* Find mapping where at least one end of the CFSI falls into. */
    map  = ML_(find_rx_mapping)(di, base, base);
    map2 = ML_(find_rx_mapping)(di, base + len - 1,
@@ -1298,7 +1298,7 @@ void ML_(addVar)( struct _DebugInfo* di,
       seems a reasonable assumption to me. */
    /* This is assured us by top level steering logic in debuginfo.c,
       and it is re-checked at the start of ML_(read_elf_object). */
-   vg_assert(di->fsm.have_rx_map && di->fsm.rw_map_count);
+   vg_assert(di->fsm.have_rx_map);
    if (level > 0 && ML_(find_rx_mapping)(di, aMin, aMax) == NULL) {
       if (VG_(clo_verbosity) > 1) {
          VG_(message)(Vg_DebugMsg,
Comment 4 Leah Neukirchen 2024-08-20 12:57:09 UTC
Indeed, the binary has no RW PT_LOAD (because it doesn't need one, data size is 0). When I use mold as a linker, it adds one and valgrind works again.

Your patch fixes the issue for me, thanks!
Comment 5 Paul Floyd 2024-08-21 06:34:37 UTC
I'm about ready to push the changes. On Debian i386 the testcase crashes for some reason. I'll try to dig into that a bit.
Comment 6 Leah Neukirchen 2024-08-21 14:58:29 UTC
The code crashes on i686 due to using uninitialized %gs (for thread-local storage I assume).
Comment 7 Paul Floyd 2024-08-22 05:59:53 UTC
The code for handling ELF segments needs to be refactored. 

commit b87649504136fc3e72684b176651912ba1514c6d (HEAD -> master, origin/users/paulf/try-bug491394, origin/master, origin/HEAD, bug491394)
Author: Paul Floyd <pjfloyd@wanadoo.fr>
Date:   Tue Aug 20 21:44:00 2024 +0200

    Bug 491394i - (vgModuleLocal_addDiCfSI): Assertion 'di->fsm.have_rx_map && di->fsm.rw_map_count' failed.
Comment 8 Paul Floyd 2024-08-26 06:44:23 UTC
*** Bug 396476 has been marked as a duplicate of this bug. ***