]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 492663 - Valgrind ignores debug info for some binaries
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 7 Sep 2024 07:06:03 +0000 (09:06 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 7 Sep 2024 07:06:03 +0000 (09:06 +0200)
ML_(check_elf_and_get_rw_loads) now always checks for
merged PT_LOADs when called from valgrind_main when
iterating over nsegments.

Updated comments and changed variable names and the
debug message when the number of expected RW PT_LOADs
hasn't been reached.

coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_readelf.h
coregrind/m_debuginfo/readelf.c

index cc79429bd6016bd8ada99e113e42a357d7d9766b..a6a0f79b3b249107d0e987372ba80d7ac604bb47 100644 (file)
@@ -1072,7 +1072,8 @@ static ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
           exe_handlers->load_fn ( == VG_(load_ELF) )
           [or load_MACHO].
 
-       This does the mmap'ing and creates the associated NSegments.
+       This does the mmap'ing with VG_(am_do_mmap_NO_NOTIFY)
+       and creates the associated NSegments.
 
        The NSegments may get merged, (see maybe_merge_nsegments)
        so there could be more PT_LOADs than there are NSegments.
@@ -1125,7 +1126,7 @@ static ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
 ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
 {
    NSegment const * seg;
-   Int rw_load_count;
+   Int expected_rw_load_count;
    const HChar* filename;
    Bool       is_rx_map, is_rw_map, is_ro_map;
 
@@ -1372,9 +1373,9 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
    /* We're only interested in mappings of object files. */
 #  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
-   rw_load_count = 0;
+   expected_rw_load_count = 0;
 
-   elf_ok = ML_(check_elf_and_get_rw_loads) ( actual_fd, filename, &rw_load_count );
+   elf_ok = ML_(check_elf_and_get_rw_loads) ( actual_fd, filename, &expected_rw_load_count, use_fd == -1 );
 
    if (use_fd == -1) {
       VG_(close)( actual_fd );
@@ -1444,7 +1445,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
    /* So, finally, are we in an accept state? */
    vg_assert(!di->have_dinfo);
    if (di->fsm.have_rx_map &&
-       di->fsm.rw_map_count == rw_load_count) {
+       di->fsm.rw_map_count == expected_rw_load_count) {
       /* Ok, so, finally, we found what we need, and we haven't
          already read debuginfo for this object.  So let's do so now.
          Yee-ha! */
@@ -1457,7 +1458,8 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
       /* If we don't have an rx and rw mapping, go no further. */
       if (debug)
          VG_(dmsg)("di_notify_mmap-6: "
-                   "no dinfo loaded %s (no rx or no rw mapping)\n", filename);
+                   "no dinfo loaded %s (no rx or rw mappings (%d) not reached expected count (%d))\n",
+                   filename, di->fsm.rw_map_count, expected_rw_load_count);
       return 0;
    }
 }
index 7e0fa17c9d7c103f64584fb62517f9124b5f818c..75e02c9800eaac53b0d4e87c683cec262768953e 100644 (file)
@@ -62,7 +62,8 @@ extern Bool ML_(read_elf_object) ( DebugInfo* di );
    function.  */
 extern Bool ML_(read_elf_debug) ( DebugInfo* di );
 
-extern Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_load_count );
+extern Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename,
+                                            Int * rw_load_count, Bool from_nsegments );
 
 
 #endif /* ndef __PRIV_READELF_H */
index 735f830441aed157dba2b0b1edab84e6b08a4a0f..b037b9201a97c54c5220f48cf9a762ec70b432c5 100644 (file)
@@ -3852,7 +3852,8 @@ Bool ML_(read_elf_debug) ( struct _DebugInfo* di )
    /* NOTREACHED */
 }
 
-Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_load_count )
+Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename,
+                                       Int * rw_load_count, Bool from_nsegments )
 {
    Bool     res, ok;
    UWord    i;
@@ -3924,9 +3925,10 @@ Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_l
                 * Hold your horses
                 * Just because The ELF file contains 2 RW PT_LOAD segments
                 * doesn't mean that Valgrind will also make 2 calls to
-                * VG_(di_notify_mmap): in some cases, the 2 NSegments will get
-                * merged and VG_(di_notify_mmap) only gets called once.
-                * How to detect that the segments will be merged ?
+                * VG_(di_notify_mmap): in some cases, the 2 NSegments will
+                * have been merged and VG_(di_notify_mmap) only gets called
+                * once.
+                * How to detect that the segments were be merged ?
                 * Logically, they will be merged if the first segment ends
                 * at the beginning of the second segment:
                 *   Seg1 virtual address + Seg1 segment_size
@@ -3949,12 +3951,12 @@ Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_l
                 * the 2 different segments loaded separately are both counted
                 * here, we use the non rounded up p_filesz.
                 * This is all a nightmare/hack. Something cleaner should be
-                * done than trying to guess here if segments will or will not
-                * be merged later depending on how the loader will load
-                * with or without rounding up.
-                * */
+                * done than other than reverse engineering whether this call
+                * results from merged nsegments or not. Particularly as
+                * the mmap'ing and nsegment merging is all under our control.
+                */
                if (previous_rw_a_phdr.p_memsz > 0 &&
-                   ehdr_m.e_type == ET_EXEC &&
+                   from_nsegments &&
                    previous_rw_a_phdr.p_vaddr + previous_rw_a_phdr.p_filesz
                      == a_phdr.p_vaddr)
                {