This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
dlfcn/failtest crash
- To: libc-alpha at sources dot redhat dot com
- Subject: dlfcn/failtest crash
- From: Bruno Haible <haible at ilog dot fr>
- Date: Mon, 28 Aug 2000 11:47:11 +0200 (CEST)
After configuring glibc-2000-08-26 with a --prefix, but before doing
"make install", "make check" fails: dlfcn/failtest dumps core.
Here is the relevant output:
$ /packages/glibc-20000826-build/elf/ld-linux.so.2 --library-path /packages/glibc-20000826-build:/packages/glibc-20000826-build/math:/packages/glibc-20000826-build/elf:/packages/glibc-20000826-build/dlfcn:/packages/glibc-20000826-build/nss:/packages/glibc-20000826-build/nis:/packages/glibc-20000826-build/rt:/packages/glibc-20000826-build/resolv:/packages/glibc-20000826-build/crypt:/packages/glibc-20000826-build/linuxthreads /packages/glibc-20000826-build/dlfcn/failtest
Round 0: Try loading "a-file-with-this-name-does-not-exist"
Speicherzugriffsfehler (core dumped)
The gdb I have doesn't understand the core dump, but it can produce a
backtrace of the process at the fault location:
(gdb) where
#0 0x40073dc4 in ?? ()
#1 0x40073d5f in ?? ()
#2 0x800076b5 in ?? ()
#3 0x80007be5 in ?? ()
#4 0x400f3600 in ?? ()
#5 0x8000d012 in ?? ()
#6 0x400f396e in ?? ()
#7 0x40001334 in ?? ()
#8 0x8000d012 in ?? ()
#9 0x40001762 in ?? ()
#10 0x40001373 in ?? ()
#11 0x80485ca in ?? ()
#12 0x4001f964 in ?? ()
You want a more reasonable backtrace? Here it is:
eip funcstart lib source func
#0 0x40073dc4 0x40073d90 libc.so malloc/malloc.c:3071 chunk_free
#1 0x40073d5f 0x40073cd0 libc.so malloc/malloc.c:3043 __libc_free
#2 0x800076b5 0x80007410 ld.so elf/dl-load.c:1328 open_path
#3 0x80007be5 0x800076d0 ld.so elf/dl-load.c:1522 _dl_map_object
#4 0x400f3600 0x400f3450 libc.so elf/dl-open.c:148 dl_open_worker
#5 0x8000d012 0x8000cf60 ld.so elf/dl-error.c:138 _dl_catch_error
#6 0x400f396e 0x400f38f0 libc.so elf/dl-open.c:327 _dl_open
#7 0x40001334 0x40001300 libdl.so dlfcn/dlopen.c:39 dlopen_doit
#8 0x8000d012 0x8000cf60 ld.so elf/dl-error.c:138 _dl_catch_error
#9 0x40001762 0x40001630 libdl.so dlfcn/dlerror.c:132 _dlerror_run
#10 0x40001373 0x40001340 libdl.so dlfcn/dlopen.c:52 dlopen
#11 0x80485ca 0x8048580 failtest dlfcn/failtest.c:26 main
#12 0x4001f964 libc.so
The *dirsp argument passed to free() in elf/dl-load.c:1328 is
= rtld_search_dirs = 0x80017400, and one can see from the memory map
that it was allocated by the bootstrap malloc() in elf/dl-minimal.c
and therefore must not be passed to free().
Otherwise free(0x80017400) -> chunk_free(0x464c457f, 0x800173f8) -> boom.
08048000-08049000 r-xp 00000000 /packages/glibc-20000826-build/dlfcn/failtest
08049000-0804a000 rw-p 00000000 /packages/glibc-20000826-build/dlfcn/failtest
40000000-40002000 r-xp 00000000 /packages/glibc-20000826-build/dlfcn/libdl.so
40002000-40003000 rw-p 00001000 /packages/glibc-20000826-build/dlfcn/libdl.so
40003000-40104000 r-xp 00000000 /packages/glibc-20000826-build/libc.so
40104000-4010a000 rw-p 00100000 /packages/glibc-20000826-build/libc.so
4010a000-4010f000 rw-p 00000000 mmap (libc.so bss segment)
80000000-80016000 r-xp 00000000 /packages/glibc-20000826-build/elf/ld.so
80016000-80017000 rw-p 00015000 /packages/glibc-20000826-build/elf/ld.so
80017000-80018000 rwxp 00000000 mmap (minimal malloc)
bfffc000-c0000000 rwxp ffffd000 stack
Here is a patch which does two things:
- Before the open_path(...&rtld_search_dirs...) call, test whether
rtld_search_dirs has been set to empty. This is needed regardless how
the malloc/free problem is solved; otherwise failtest crashes during
the second loop round (out of 10).
- Changes open_path so that it calls free() only if *dirsp has been
allocated by a decompose_rpath call immediately before. In all other
cases, it is not clear which malloc() allocated it (the current one or
the minimal one), therefore a memory leak is preferred to a crash.
To really fix the memory leaks here, a different idea would be to
store in each "struct r_search_path_elem **" a bit telling with which
memory allocator it has been allocated.
Bruno
2000-08-27 Bruno Haible <haible@clisp.cons.org>
* elf/dl-load.c (open_path): Add a argument telling whether *dirsp
is guaranteed to be allocated with the same malloc() and may be
passed to free().
(_dl_map_object): Update open_path calls. If rtld_search_dirs has
been set to empty by an earlier open_path call, don't pass it again.
*** glibc-20000826/elf/dl-load.c.bak Fri Aug 25 23:52:56 2000
--- glibc-20000826/elf/dl-load.c Sun Aug 27 02:49:08 2000
***************
*** 1204,1216 ****
_dl_debug_message (0, "\t\t(", what, ")\n", NULL);
}
! /* Try to open NAME in one of the directories in DIRS.
Return the fd, or -1. If successful, fill in *REALNAME
! with the malloc'd full directory name. */
static int
open_path (const char *name, size_t namelen, int preloaded,
! struct r_search_path_elem ***dirsp,
char **realname)
{
struct r_search_path_elem **dirs = *dirsp;
--- 1204,1219 ----
_dl_debug_message (0, "\t\t(", what, ")\n", NULL);
}
! /* Try to open NAME in one of the directories in *DIRSP.
Return the fd, or -1. If successful, fill in *REALNAME
! with the malloc'd full directory name. If it turns out
! that none of the directories in *DIRSP exists, *DIRSP is
! replaced with (void *) -1, and the old value is free()d
! if MAY_FREE_DIRS is true. */
static int
open_path (const char *name, size_t namelen, int preloaded,
! struct r_search_path_elem ***dirsp, int may_free_dirs,
char **realname)
{
struct r_search_path_elem **dirs = *dirsp;
***************
*** 1325,1331 ****
/* Remove the whole path if none of the directories exists. */
if (! any)
{
! free (*dirsp);
*dirsp = (void *) -1;
}
--- 1328,1337 ----
/* Remove the whole path if none of the directories exists. */
if (! any)
{
! /* Paths which were allocated using the minimal malloc() in ld.so
! must not be freed using the general free() in libc. */
! if (may_free_dirs)
! free (*dirsp);
*dirsp = (void *) -1;
}
***************
*** 1414,1425 ****
if (l->l_rpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &l->l_rpath_dirs, &realname);
}
}
else if (l->l_rpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
! &realname);
}
/* If dynamically linked, try the DT_RPATH of the executable
--- 1420,1431 ----
if (l->l_rpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &l->l_rpath_dirs, 1, &realname);
}
}
else if (l->l_rpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
! 0, &realname);
}
/* If dynamically linked, try the DT_RPATH of the executable
***************
*** 1427,1439 ****
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l != loader
&& l->l_rpath_dirs != (void *) -1)
! fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
&realname);
}
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list != (void *) -1)
! fd = open_path (name, namelen, preloaded, &env_path_list, &realname);
/* Look at the RUNPATH informaiton for this binary. */
if (loader != NULL && loader->l_runpath_dirs != (void *) -1)
--- 1433,1446 ----
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l != loader
&& l->l_rpath_dirs != (void *) -1)
! fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, 0,
&realname);
}
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list != (void *) -1)
! fd = open_path (name, namelen, preloaded, &env_path_list, 0,
! &realname);
/* Look at the RUNPATH informaiton for this binary. */
if (loader != NULL && loader->l_runpath_dirs != (void *) -1)
***************
*** 1453,1464 ****
if (loader->l_runpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &loader->l_runpath_dirs, &realname);
}
}
else if (loader->l_runpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &loader->l_runpath_dirs, &realname);
}
if (fd == -1)
--- 1460,1471 ----
if (loader->l_runpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &loader->l_runpath_dirs, 1, &realname);
}
}
else if (loader->l_runpath_dirs != (void *) -1)
fd = open_path (name, namelen, preloaded,
! &loader->l_runpath_dirs, 0, &realname);
}
if (fd == -1)
***************
*** 1518,1525 ****
/* Finally, try the default path. */
if (fd == -1
&& (l == NULL ||
! __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)))
! fd = open_path (name, namelen, preloaded, &rtld_search_dirs,
&realname);
/* Add another newline when we a tracing the library loading. */
--- 1525,1533 ----
/* Finally, try the default path. */
if (fd == -1
&& (l == NULL ||
! __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
! && rtld_search_dirs != (void *) -1)
! fd = open_path (name, namelen, preloaded, &rtld_search_dirs, 0,
&realname);
/* Add another newline when we a tracing the library loading. */