[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: mdemo ltdl failure
From: |
Charles Wilson |
Subject: |
Re: mdemo ltdl failure |
Date: |
Fri, 16 Mar 2007 10:35:01 -0500 |
User-agent: |
Thunderbird 1.5.0.10 (Windows/20070221) |
[cross-posted to cygwin]
Ralf Wildenhues wrote:
A (very small) progress report.
On Tue, Feb 27, 2007 at 11:02:01PM +0100, Ralf Wildenhues wrote:
* Charles Wilson wrote on Tue, Feb 27, 2007 at 05:42:50AM CET:
> Ralf Wildenhues wrote:
> >The only thing that's then still worrying me is that on Cygwin, the
> >mdemo and mdemo_static programs sometimes throw segmentation faults
> >on my system. Not all the time though.
> > Well, it's failing all the time for me, but I'm not sure it's a >
segfault. What does "Hangup" mean, when reported by the shell after >
executing the app:
Good question, I don't know. I suppose there is memory corruption
earlier, and due to it anything weird can happen later, so the exit
status is not really reliable.
When I compiled with -O0, the error message changed to 'Aborted (core
dumped)'. It was indeed a segfault, and occurred at line 1582 in
ltdl.c: 'FREE(buf)' within lt_argz_insertdir.
It's exposed by try_iterate which calls lt_dlforeachfile. I think it's
somewhere in dirent code. I have a feeling that it's not caused by
anything in Libtool, but am not sure. (Only noting this because it may
ring a bell, not because I have any evidence.)
I've (almost) tracked down the error: it is caused by yet another bug in
newlib's argz_insert() (or possibly realloc()! ), as called by
lt_argz_insert:
1473 static int
1474 lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1475 const char *entry)
1476 {
1477 error_t error;
1478
1479 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1480 pargz_len, NULL, entry) failed with EINVAL. */
1481 if (before)
1482 error = argz_insert (pargz, pargz_len, before, entry);
1483 else
1484 error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1485
1486 if (error)
The very first time argz_insert() is called -- rather than argz_append()
-- the memory pointed to by pargz and entry gets corrupted (entry is
known as 'buf' back in the caller lt_argz_insertdir.)
The value of 'entry' and 'before' during each successive call to
lt_arg_insert() was:
"tests/mdemo/config", NULL
"tests/mdemo/foo1", NULL
"tests/mdemo/foo2", NULL
"tests/mdemo/libfoo2", NULL
"tests/mdemo/libmlib", NULL
"tests/mdemo/libsub", NULL
"tests/mdemo/libtool", NULL
"tests/mdemo/main", NULL
"tests/mdemo/Makefile", == *pargz
Note that dirent is returning filenames in case-insensitive alphabetical
order -- but lt_argz_insertinorder() is using case-sensitive comparison,
so Makefile gets inserted at the front of the list, while all the others
were successively appended to the pargz list.
What's odd is that this bug in argz_insert() is very ticklish: it
triggers on "tests/mdemo/Makefile", but not when argz_insert is called
with "./tests/mdemo/Makefile". See the attached gdb screenshots from
just before the buggy call and just after. I've highlighted in red the
location to which *pargz points, and in blue the location to which entry
(ne' buf) points.
The "after" shot indicates that the original contents of entry got
copied to some 11 bytes prior to the beginning of the *pargz buffer,
overlapping the beginning of the newly realloc'ed *pargz. Furthermore,
after the call, the *pargz buffer -- if the value of of *pargz and
*pargz_len are to be believed -- extends across where entry (e.g. buf)
points -- so the malloc subsytem obviously no longer thinks *buf is an
allocated block (otherwise, it wouldn't have included that chunk in the
memory assigned to *pargz by the realloc). So, naturally, FREE(buf) fails.
I need to verify this using a debug-built cygwin kernel, but it looks
like within newlib's argz_insert(), the call to realloc() is not
operating correctly in this instance.
Note that using libltdl's own argz routines "fixes" this problem,
perhaps because libltdl's argz_insert does not use realloc, but rather
explicitly mallocs the new memory, does the copy, explicitly frees the
old memory, and then does the *pargz pointer reassignment.
export ac_cv_func_argz_append=no;
export ac_cv_func_argz_create_sep=no;
export ac_cv_func_argz_insert=no;
export ac_cv_func_argz_next=no;
export ac_cv_func_argz_stringify=no;
export ac_cv_header_argz_h=no
../libtool-HEAD/configure FC=no CFLAGS="-ggdb -O0"
make
make -k check-TESTS TESTS='tests/mdemo-conf.test tests/mdemo-make.test
tests/mdemo-exec.test' VERBOSE=t CFLAGS="-ggdb -O0"
works just fine (and I've verified that in this case, _lt__argz_insert()
is being used, not cygwin's argz_insert()).
--
Chuck
P.S. all this was done using libtool-HEAD from yesterday, most recent
changelog entry:
2007-03-09 Gary V. Vaughan <...>
* libtoolize.m4sh: Replace literal tab chars in help comment
with spaces to align columns in --help output.
which unfortunately exhibited new testsuite failures in Subproject
Libltdl...
33: compiling softlinked libltdl FAILED (subproject.at:59)
34: compiling copied libltdl FAILED (subproject.at:75)
35: installable libltdl FAILED (subproject.at:95)
Haven't even tried to track these down.

