Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Sep 2014 20:46:59 +0200
From:      Dimitry Andric <dim@FreeBSD.org>
To:        Will Andrews <will@freebsd.org>
Cc:        Justin Gibbs <gibbs@freebsd.org>, jkoshy@freebsd.org, freebsd-toolchain@freebsd.org, kaiw@freebsd.org
Subject:   Re: elftoolchain update?
Message-ID:  <D44FDBD9-F6AF-48B1-A467-9C51C685E750@FreeBSD.org>
In-Reply-To: <CADBaqmgasfbP6r09yAsmrw-eVHqm3AWSuBdA5tHf5U5rj8j2HA@mail.gmail.com>
References:  <CADBaqmgasfbP6r09yAsmrw-eVHqm3AWSuBdA5tHf5U5rj8j2HA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_30E0948E-EB5E-4D45-B37A-695A9D42D0B0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

On 18 Sep 2014, at 01:01, Will Andrews <will@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?
>=20
> 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.
>=20
> This is easily demonstrated by applying this patch to FreeBSD/head and
> building sbin/devd with WITH_CTF=3D1:
> =
http://people.freebsd.org/~will/add-ctfconvert-to-cpp-object-files.diff
>=20
> 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=3D0x28941f10, attr=3D73, =
valp=3D0xbfbfdea0, err=3D0xbfbfe0a4) 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=3D0x28941f10, attr=3D73, =
valp=3D0xbfbfdea0, err=3D0xbfbfe0a4) at =
/usr/src/lib/libdwarf/../../contrib/elftoolchain/libdwarf/dwarf_attrval.c:=
186
#1  0x08052a45 in die_attr_ref (dw=3D0xbfbfe0a0, die=3D0x28941f10, =
name=3D73) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:417
#2  0x08052844 in die_lookup_pass1 (dw=3D0xbfbfe0a0, die=3D0x28941f10, =
name=3D73) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:476
#3  0x08052380 in die_variable_create (dw=3D0xbfbfe0a0, die=3D0x28941f10, =
off=3D83907, tdp=3D0x0) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:1680
#4  0x08050940 in die_create_one (dw=3D0xbfbfe0a0, die=3D0x28941f10) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:1793
#5  0x0804fa94 in die_create (dw=3D0xbfbfe0a0, die=3D0x28941f10) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:1800
#6  0x0804f368 in dw_read (td=3D0x2881c040, elf=3D0x28830040, =
filename=3D0xbfbfe83e "devd.o") at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:2003
#7  0x0804eb6e in file_read (td=3D0x2881c040, filename=3D0xbfbfe83e =
"devd.o", ignore_non_c=3D0) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/ctfconvert.c:115
#8  0x0804e7ca in main (argc=3D5, argv=3D0xbfbfe694) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/ctfconvert.c:236
(gdb) print at
$1 =3D (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 =3D _dwarf_attr_find(die, attr)) =3D=3D NULL && =
attr !=3D DW_AT_type) {
   158                  DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
   159                  return (DW_DLV_NO_ENTRY);
   160          }
   161
   162          die1 =3D NULL;
   163          if (at =3D=3D NULL &&
   164              (at =3D _dwarf_attr_find(die, =
DW_AT_abstract_origin)) !=3D 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=3D0xbfbfe0a0, die=3D0x28941f10, =
off=3D83907, tdp=3D0x0) at =
/usr/src/cddl/usr.bin/ctfconvert/../../../cddl/contrib/opensolaris/tools/c=
tf/cvt/dwarf.c:1680
1680            ii->ii_dtype =3D die_lookup_pass1(dw, die, DW_AT_type);
(gdb) print name
$2 =3D 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 =3D die_name(dw, die)) =
=3D=3D NULL)
  1675                  return; /* skip prototypes and nameless objects =
*/
  1676
  1677          ii =3D xcalloc(sizeof (iidesc_t));
  1678          ii->ii_type =3D die_isglobal(dw, die) ? II_GVAR : =
II_SVAR;
  1679          ii->ii_name =3D name;
  1680          ii->ii_dtype =3D 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 =3D NULL;
   429
   430          (void) die_string(dw, die, DW_AT_name, &str, 0);
   431          if (str =3D=3D NULL)
   432                  str =3D 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


--Apple-Mail=_30E0948E-EB5E-4D45-B37A-695A9D42D0B0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename=signature.asc
Content-Type: application/pgp-signature;
	name=signature.asc
Content-Description: Message signed with OpenPGP using GPGMail

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)

iEYEARECAAYFAlQbKKgACgkQsF6jCi4glqNK5gCfTxBhMscesG9ogoJfu99Ownts
icAAn1NUB56P1rzA7OsvTL2nzUyWikDi
=hp85
-----END PGP SIGNATURE-----

--Apple-Mail=_30E0948E-EB5E-4D45-B37A-695A9D42D0B0--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?D44FDBD9-F6AF-48B1-A467-9C51C685E750>