Bug 422601 - valgrind throws 'has_nonempty_rw' assertion failure on dlopen() if other mappings exist
Summary: valgrind throws 'has_nonempty_rw' assertion failure on dlopen() if other mapp...
Status: REPORTED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: 3.15 SVN
Platform: Gentoo Packages Linux
: NOR crash
Target Milestone: ---
Assignee: Julian Seward
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-08 00:29 UTC by Laurent Pinchart
Modified: 2020-06-08 00:37 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Test case that exhibits the issue (1.30 KB, text/x-csrc)
2020-06-08 00:29 UTC, Laurent Pinchart
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Laurent Pinchart 2020-06-08 00:29:39 UTC
Created attachment 129131 [details]
Test case that exhibits the issue

SUMMARY

When processing the mmap() calls from dlopen(), valgrind loads debug symbols from the ELF library being opened. If conflicting other mappings were previously created, a 'has_nonempty_rw' assertion failure is thrown.

STEPS TO REPRODUCE
1. Compile the attached test case with 'gcc -o valgrind-test -lm valgrind-test.c'
2. Run 'valgrind ./valgrind-test'

OBSERVED RESULT

==23177== Memcheck, a memory error detector
==23177== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23177== Using Valgrind-3.15.0-608cb11914-20190413 and LibVEX; rerun with -h for copyright info
==23177== Command: ./valgrind-test
==23177== 
--23177-- Valgrind options:
--23177--    -v
--23177-- Contents of /proc/version:
--23177--   Linux version 5.4.28-gentoo (root@pendragon) (gcc version 8.3.0 (Gentoo 8.3.0-r1 p1.1)) #1 SMP PREEMPT Fri Apr 17 17:51:31 EEST 2020
--23177-- 
--23177-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand
--23177-- Page sizes: currently 4096, max supported 4096
--23177-- Valgrind library directory: /usr/lib64/valgrind
--23177-- Reading syms from /home/laurent/src/test/valgrind-test
--23177-- Reading syms from /lib64/ld-2.30.so
--23177--   Considering /usr/lib/debug/lib64/ld-2.30.so.debug ..
--23177--   .. CRC is valid
--23177-- Reading syms from /usr/lib64/valgrind/memcheck-amd64-linux
--23177--   Considering /usr/lib/debug/usr/lib64/valgrind/memcheck-amd64-linux.debug ..
--23177--   .. CRC is valid
--23177--    object doesn't have a dynamic symbol table
--23177-- Scheduler: using generic scheduler lock implementation.
--23177-- Reading suppressions file: /usr/lib64/valgrind/default.supp
==23177== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-23177-by-laurent-on-???
==23177== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-23177-by-laurent-on-???
==23177== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-23177-by-laurent-on-???
==23177== 
==23177== TO CONTROL THIS PROCESS USING vgdb (which you probably
==23177== don't want to do, unless you know exactly what you're doing,
==23177== or are doing some strange experiment):
==23177==   /usr/lib64/valgrind/../../bin/vgdb --pid=23177 ...command...
==23177== 
==23177== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==23177==   /path/to/gdb ./valgrind-test
==23177== and then give GDB the following command
==23177==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=23177
==23177== --pid is optional if only one valgrind process is running
==23177== 
--23177-- REDIR: 0x401e290 (ld-linux-x86-64.so.2:strlen) redirected to 0x580c9122 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--23177-- REDIR: 0x401e070 (ld-linux-x86-64.so.2:index) redirected to 0x580c913c (vgPlain_amd64_linux_REDIR_FOR_index)
--23177-- Reading syms from /usr/lib64/valgrind/vgpreload_core-amd64-linux.so
--23177--   Considering /usr/lib/debug/usr/lib64/valgrind/vgpreload_core-amd64-linux.so.debug ..
--23177--   .. CRC is valid
--23177-- Reading syms from /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so
--23177--   Considering /usr/lib/debug/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so.debug ..
--23177--   .. CRC is valid
==23177== WARNING: new redirection conflicts with existing -- ignoring it
--23177--     old: 0x0401e290 (strlen              ) R-> (0000.0) 0x580c9122 vgPlain_amd64_linux_REDIR_FOR_strlen
--23177--     new: 0x0401e290 (strlen              ) R-> (2007.0) 0x04839db0 strlen
--23177-- REDIR: 0x401aab0 (ld-linux-x86-64.so.2:strcmp) redirected to 0x483ae00 (strcmp)
--23177-- REDIR: 0x401e7d0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x483e6d0 (mempcpy)
--23177-- Reading syms from /lib64/libdl-2.30.so
--23177--   Considering /usr/lib/debug/lib64/libdl-2.30.so.debug ..
--23177--   .. CRC is valid
--23177-- Reading syms from /lib64/libc-2.30.so
--23177--   Considering /usr/lib/debug/lib64/libc-2.30.so.debug ..
--23177--   .. CRC is valid
--23177-- REDIR: 0x4940660 (libc.so.6:memmove) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f9e0 (libc.so.6:strncpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940970 (libc.so.6:strcasecmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f320 (libc.so.6:strcat) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493fa40 (libc.so.6:rindex) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4941e20 (libc.so.6:rawmemchr) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495a650 (libc.so.6:wmemchr) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495a1f0 (libc.so.6:wcscmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x49407c0 (libc.so.6:mempcpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x49405f0 (libc.so.6:bcmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f980 (libc.so.6:strncmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f3d0 (libc.so.6:strcmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940720 (libc.so.6:memset) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495a1b0 (libc.so.6:wcschr) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f8e0 (libc.so.6:strnlen) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f4a0 (libc.so.6:strcspn) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x49409c0 (libc.so.6:strncasecmp) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f440 (libc.so.6:strcpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940b00 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495b860 (libc.so.6:wcsnlen) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495a230 (libc.so.6:wcscpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493fa80 (libc.so.6:strpbrk) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f380 (libc.so.6:index) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493f8a0 (libc.so.6:strlen) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4946790 (libc.so.6:memrchr) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940a10 (libc.so.6:strcasecmp_l) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x49405b0 (libc.so.6:memchr) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x495a2e0 (libc.so.6:wcslen) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x493fd20 (libc.so.6:strspn) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940910 (libc.so.6:stpncpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x49408b0 (libc.so.6:stpcpy) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4941e60 (libc.so.6:strchrnul) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4940a60 (libc.so.6:strncasecmp_l) redirected to 0x482c1b0 (_vgnU_ifunc_wrapper)
--23177-- REDIR: 0x4a0c9c0 (libc.so.6:__strrchr_avx2) redirected to 0x48397c0 (rindex)
--23177-- REDIR: 0x493b920 (libc.so.6:malloc) redirected to 0x4836730 (malloc)
--23177-- REDIR: 0x493bf60 (libc.so.6:free) redirected to 0x4837960 (free)
--23177-- REDIR: 0x493c6c0 (libc.so.6:calloc) redirected to 0x4838ad0 (calloc)

valgrind: m_debuginfo/readelf.c:1730 (vgModuleLocal_read_elf_debug_info): Assertion 'has_nonempty_rw' failed.

host stacktrace:
==23177==    at 0x580489FC: show_sched_status_wrk (m_libcassert.c:388)
==23177==    by 0x58048B17: report_and_quit (m_libcassert.c:459)
==23177==    by 0x58048CB4: vgPlain_assert_fail (m_libcassert.c:525)
==23177==    by 0x58084B25: vgModuleLocal_read_elf_debug_info (readelf.c:1730)
==23177==    by 0x5807AABB: di_notify_ACHIEVE_ACCEPT_STATE (debuginfo.c:971)
==23177==    by 0x5807AABB: vgPlain_di_notify_mmap (debuginfo.c:1321)
==23177==    by 0x580ACF7A: vgModuleLocal_generic_PRE_sys_mmap (syswrap-generic.c:2402)
==23177==    by 0x580B8A2F: vgSysWrap_amd64_linux_sys_mmap_before (syswrap-amd64-linux.c:415)
==23177==    by 0x580A8670: vgPlain_client_syscall (syswrap-main.c:1863)
==23177==    by 0x580A4B7A: handle_syscall (scheduler.c:1209)
==23177==    by 0x580A6506: vgPlain_scheduler (scheduler.c:1531)
==23177==    by 0x580F6020: thread_wrapper (syswrap-linux.c:103)
==23177==    by 0x580F6020: run_a_thread_NORETURN (syswrap-linux.c:156)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable syscall 9 (lwpid 23177)
==23177==    at 0x401A683: __mmap64 (mmap64.c:59)
==23177==    by 0x401A683: mmap (mmap64.c:47)
==23177==    by 0x4006163: _dl_map_segments (dl-map-segments.h:94)
==23177==    by 0x4006163: _dl_map_object_from_fd (dl-load.c:1181)
==23177==    by 0x4008869: _dl_map_object (dl-load.c:2225)
==23177==    by 0x4012BCA: dl_open_worker (dl-open.c:217)
==23177==    by 0x49E532E: _dl_catch_exception (dl-error-skeleton.c:196)
==23177==    by 0x4012799: _dl_open (dl-open.c:592)
==23177==    by 0x48B1255: dlopen_doit (dlopen.c:66)
==23177==    by 0x49E532E: _dl_catch_exception (dl-error-skeleton.c:196)
==23177==    by 0x49E53CE: _dl_catch_error (dl-error-skeleton.c:215)
==23177==    by 0x48B1994: _dlerror_run (dlerror.c:170)
==23177==    by 0x48B12E5: dlopen@@GLIBC_2.2.5 (dlopen.c:87)
==23177==    by 0x1093D3: main (in /home/laurent/src/test/valgrind-test)
client stack range: [0x1FFEFFD000 0x1FFF000FFF] client SP: 0x1FFEFFEC98
valgrind stack range: [0x10030AA000 0x10031A9FFF] top usage: 18616 of 1048576


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.

EXPECTED RESULT

valgrind should not throw an assertion failure.


ADDITIONAL INFORMATION

When running with --trace-symtab=yes, the following messages appear before the assertion failure:

------ start ELF OBJECT -------------------------------------------------------
------ name = /lib64/libm-2.30.so

Un-de-overlapped _DebugInfoMappings:
  [0]    avma 0x4a73000             size 1261568     foff 0           -- rw --
  [1]    avma 0x4a73000             size 1261568     foff 0           -- -- ro
  [2]    avma 0x4e73000             size 1265664     foff 0           -- -- ro
  [3]    avma 0x4e80000             size 581632      foff 53248       rx -- --

De-overlapped DebugInfoMappings:
  [0]    avma 0x4a73000             size 0           foff 0           -- rw --
  [1]    avma 0x4a73000             size 1261568     foff 0           -- -- ro
  [2]    avma 0x4e73000             size 53248       foff 0           -- -- ro
  [3]    avma 0x4e80000             size 581632      foff 53248       rx -- --

Checking that there are no remaining overlaps.
Check successful.

valgrind: m_debuginfo/readelf.c:1730 (vgModuleLocal_read_elf_debug_info): Assertion 'has_nonempty_rw' failed.

The first two mappings correspond to the manually created mappings in the test application. Despite them beind unmapped manually before dlopen(), they still influence the debug info handling.