elftoolchain update?
Dimitry Andric
dim at FreeBSD.org
Thu Sep 18 18:47:12 UTC 2014
On 18 Sep 2014, at 01:01, Will Andrews <will at freebsd.org> wrote:
> I see there have been a lot of updates & fixes to elftoolchain since
> the last import into FreeBSD/head nearly 8 months ago. Are there any
> plans to update the import?
>
> I'm asking because it appears that ctfconvert currently crashes
> (specifically, due to a bug in dwarf_attrval_unsigned()), if you try
> to use it on C++ object files.
>
> This is easily demonstrated by applying this patch to FreeBSD/head and
> building sbin/devd with WITH_CTF=1:
> http://people.freebsd.org/~will/add-ctfconvert-to-cpp-object-files.diff
>
> Justin Gibbs (cc'd) posted about this issue in February, and it's
> still a problem:
> http://lists.freebsd.org/pipermail/freebsd-toolchain/2014-February/001121.html
In that previous thread, I was not able to reproduce any problems with
ctfconvert or ctfmerge, but I have tried it again just now, and I think
it is a problem in libdwarf.
The crash goes like this:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 28803080 (LWP 100196)]
0x280bb75d in dwarf_attrval_unsigned (die=0x28941f10, attr=73, valp=0xbfbfdea0, err=0xbfbfe0a4) at /usr/src/lib/libdwarf/../../contrib/elftoolchain/libdwarf/dwarf_attrval.c:186
186 switch (at->at_form) {
(gdb) bt
#0 0x280bb75d in dwarf_attrval_unsigned (die=0x28941f10, attr=73, valp=0xbfbfdea0, err=0xbfbfe0a4) at /usr/src/lib/libdwarf/../../contrib/elftoolchain/libdwarf/dwarf_attrval.c:186
#1 0x08052a45 in die_attr_ref (dw=0xbfbfe0a0, die=0x28941f10, name=73) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:417
#2 0x08052844 in die_lookup_pass1 (dw=0xbfbfe0a0, die=0x28941f10, name=73) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:476
#3 0x08052380 in die_variable_create (dw=0xbfbfe0a0, die=0x28941f10, off=83907, tdp=0x0) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:1680
#4 0x08050940 in die_create_one (dw=0xbfbfe0a0, die=0x28941f10) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:1793
#5 0x0804fa94 in die_create (dw=0xbfbfe0a0, die=0x28941f10) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:1800
#6 0x0804f368 in dw_read (td=0x2881c040, elf=0x28830040, filename=0xbfbfe83e "devd.o") at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:2003
#7 0x0804eb6e in file_read (td=0x2881c040, filename=0xbfbfe83e "devd.o", ignore_non_c=0) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c:115
#8 0x0804e7ca in main (argc=5, argv=0xbfbfe694) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c:236
(gdb) print at
$1 = (Dwarf_Attribute) 0x0
Looking at dwarf_attrval_unsigned(), you can see 'at' being NULL-checked
in line 163, but if the _dwarf_attr_find() call on line 164 then also
returns NULL, the switch on line 186 will segfault as above:
140 int
141 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
142 {
143 Dwarf_Attribute at;
...
157 if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
158 DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
159 return (DW_DLV_NO_ENTRY);
160 }
161
162 die1 = NULL;
163 if (at == NULL &&
164 (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
...
184 }
185
186 switch (at->at_form) {
...
I'm not sure what kind of error code should be returned when the second
_dwarf_attr_find() fails, though. Or if that is some sort of problem
with a symbol? If I go to frame 3 (die_variable_create), the name seems
to be the empty string, but not a NULL pointer:
(gdb) frame 3
#3 0x08052380 in die_variable_create (dw=0xbfbfe0a0, die=0x28941f10, off=83907, tdp=0x0) at /usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c:1680
1680 ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type);
(gdb) print name
$2 = 0x2892dc90 ""
The name is looked up on line 1674, where nameless objects are supposed
to be skipped:
1666 static void
1667 die_variable_create(dwarf_t *dw, Dwarf_Die die, Dwarf_Off off, tdesc_t *tdp __unused)
1668 {
1669 iidesc_t *ii;
1670 char *name;
1671
1672 debug(3, "die %llu: creating object definition\n", off);
1673
1674 if (die_isdecl(dw, die) || (name = die_name(dw, die)) == NULL)
1675 return; /* skip prototypes and nameless objects */
1676
1677 ii = xcalloc(sizeof (iidesc_t));
1678 ii->ii_type = die_isglobal(dw, die) ? II_GVAR : II_SVAR;
1679 ii->ii_name = name;
1680 ii->ii_dtype = die_lookup_pass1(dw, die, DW_AT_type);
However, die_name() does not ever seem to return NULL (the code to
return the empty string was added by Kai in r261246):
425 static char *
426 die_name(dwarf_t *dw, Dwarf_Die die)
427 {
428 char *str = NULL;
429
430 (void) die_string(dw, die, DW_AT_name, &str, 0);
431 if (str == NULL)
432 str = xstrdup("");
433
434 return (str);
435 }
There are quite a lot of places in this file where the result of
die_name() is explicitly checked against NULL, so maybe always returning
an empty string was not such a good idea. It may have been done to
avoid another segfault.
The way forward is probably to:
* fix the situation in dwarf_attrval_unsigned(), returning a sensible
error value if both lookups fail.
* make die_name() return a NULL pointer again, or explicitly check for
the empty string in die_variable_create().
-Dimitry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 203 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.freebsd.org/pipermail/freebsd-toolchain/attachments/20140918/1547e596/attachment.sig>
More information about the freebsd-toolchain
mailing list