Author: pfg
Date: Fri Jul 26 00:28:19 2013
New Revision: 253661
URL: http://svnweb.freebsd.org/changeset/base/253661

Log:
  Fix a segfault in ctfmerge due to a bug in gcc.
  
  GCC can generate bogus dwarf attributes with DW_AT_byte_size
  set to 0xFFFFFFFF.
  The issue was originaly detected in NetBSD but it has been
  adapted for portability and to avoid compiler warnings.
  
  Reference:
  https://www.illumos.org/issues/3776
  
  Obtained from:        NetBSD
  MFC after:    1 month

Modified:
  head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
  head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
  head/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
  head/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c   Thu Jul 25 20:53:15 
2013        (r253660)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c   Fri Jul 26 00:28:19 
2013        (r253661)
@@ -52,6 +52,8 @@ static char *curfile;
 #define        CTF_BUF_CHUNK_SIZE      (64 * 1024)
 #define        RES_BUF_CHUNK_SIZE      (64 * 1024)
 
+static int ntypes=0;           /* The number of types. */
+
 struct ctf_buf {
        strtab_t ctb_strtab;    /* string table */
        caddr_t ctb_base;       /* pointer to base of buffer */
@@ -1143,6 +1145,10 @@ resurrect_types(ctf_header_t *h, tdata_t
                                        (*mpp)->ml_type = tdarr[ctm->ctm_type];
                                        (*mpp)->ml_offset = ctm->ctm_offset;
                                        (*mpp)->ml_size = 0;
+                                       if (ctm->ctm_type > ntypes) {
+                                               parseterminate("Invalid member 
type ctm_type=%d",
+                                                   ctm->ctm_type);
+                                       }
                                }
                        } else {
                                for (i = 0, mpp = &tdp->t_members; i < vlen;
@@ -1159,6 +1165,10 @@ resurrect_types(ctf_header_t *h, tdata_t
                                        (*mpp)->ml_offset =
                                            (int)CTF_LMEM_OFFSET(ctlm);
                                        (*mpp)->ml_size = 0;
+                                       if (ctlm->ctlm_type > ntypes) {
+                                               parseterminate("Invalid lmember 
type ctlm_type=%d",
+                                                   ctlm->ctlm_type);
+                                       }
                                }
                        }
 
@@ -1272,9 +1282,10 @@ ctf_parse(ctf_header_t *h, caddr_t buf, 
 {
        tdata_t *td = tdata_new();
        tdesc_t **tdarr;
-       int ntypes = count_types(h, buf);
        int idx, i;
 
+       ntypes = count_types(h, buf);
+
        /* shudder */
        tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1));
        tdarr[0] = NULL;

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h      Thu Jul 25 
20:53:15 2013        (r253660)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h      Fri Jul 26 
00:28:19 2013        (r253661)
@@ -159,7 +159,7 @@ typedef struct ardef {
 /* Auxiliary structure for structure/union tdesc_t */
 typedef struct mlist {
        int     ml_offset;      /* Offset from start of structure (in bits) */
-       int     ml_size;        /* Member size (in bits) */
+       uint_t  ml_size;        /* Member size (in bits) */
        char    *ml_name;       /* Member name */
        struct  tdesc *ml_type; /* Member type */
        struct  mlist *ml_next; /* Next member */

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c Thu Jul 25 20:53:15 
2013        (r253660)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c Fri Jul 26 00:28:19 
2013        (r253661)
@@ -674,6 +674,13 @@ die_array_create(dwarf_t *dw, Dwarf_Die 
                tdesc_t *dimtdp;
                int flags;
 
+               /* Check for bogus gcc DW_AT_byte_size attribute */
+               if (uval == (unsigned)-1) {
+                       printf("dwarf.c:%s() working around bogus -1 
DW_AT_byte_size\n",
+                           __func__);
+                       uval = 0;
+               }
+               
                tdp->t_size = uval;
 
                /*
@@ -760,6 +767,12 @@ die_enum_create(dwarf_t *dw, Dwarf_Die d
        tdp->t_type = ENUM;
 
        (void) die_unsigned(dw, die, DW_AT_byte_size, &uval, DW_ATTR_REQ);
+       /* Check for bogus gcc DW_AT_byte_size attribute */
+       if (uval == (unsigned)-1) {
+               printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
+                   __func__); 
+               uval = 0;
+       }
        tdp->t_size = uval;
 
        if ((mem = die_child(dw, die)) != NULL) {
@@ -873,7 +886,7 @@ static void
 die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
     int type, const char *typename)
 {
-       Dwarf_Unsigned sz, bitsz, bitoff;
+       Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0;
        Dwarf_Die mem;
        mlist_t *ml, **mlastp;
        iidesc_t *ii;
@@ -929,6 +942,8 @@ die_sou_create(dwarf_t *dw, Dwarf_Die st
                        ml->ml_name = NULL;
 
                ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type);
+               debug(3, "die_sou_create(): ml_type = %p t_id = %d\n",
+                   ml->ml_type, ml->ml_type->t_id);
 
                if (die_mem_offset(dw, mem, DW_AT_data_member_location,
                    &mloff, 0)) {
@@ -956,8 +971,24 @@ die_sou_create(dwarf_t *dw, Dwarf_Die st
 
                *mlastp = ml;
                mlastp = &ml->ml_next;
+
+               /* Find the size of the largest member to work around a gcc
+                * bug.  See GCC Bugzilla 35998.
+                */
+               if (maxsz < ml->ml_size)
+                       maxsz = ml->ml_size;
+
        } while ((mem = die_sibling(dw, mem)) != NULL);
 
+       /* See if we got a bogus DW_AT_byte_size.  GCC will sometimes
+        * emit this.
+        */
+       if (sz == (unsigned)-1) {
+                printf("dwarf.c:%s() working around bogus -1 
DW_AT_byte_size\n",
+                    __func__);
+                tdp->t_size = maxsz / 8;  /* maxsz is in bits, t_size is bytes 
*/
+       }
+
        /*
         * GCC will attempt to eliminate unused types, thus decreasing the
         * size of the emitted dwarf.  That is, if you declare a foo_t in your
@@ -1054,7 +1085,7 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **
                }
 
                if (ml->ml_size != 0 && mt->t_type == INTRINSIC &&
-                   mt->t_intr->intr_nbits != ml->ml_size) {
+                   mt->t_intr->intr_nbits != (int)ml->ml_size) {
                        /*
                         * This member is a bitfield, and needs to reference
                         * an intrinsic type with the same width.  If the
@@ -1370,6 +1401,13 @@ die_base_create(dwarf_t *dw, Dwarf_Die b
         */
        (void) die_unsigned(dw, base, DW_AT_byte_size, &sz, DW_ATTR_REQ);
 
+       /* Check for bogus gcc DW_AT_byte_size attribute */
+       if (sz == (unsigned)-1) {
+               printf("dwarf.c:%s() working around bogus -1 DW_AT_byte_size\n",
+                   __func__);
+               sz = 0;
+       }
+
        if (tdp->t_name == NULL)
                terminate("die %llu: base type without name\n", off);
 

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c      Thu Jul 25 
20:53:15 2013        (r253660)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c      Fri Jul 26 
00:28:19 2013        (r253661)
@@ -952,7 +952,7 @@ soudef(char *cp, stabtype_t type, tdesc_
 
                itdp = find_intrinsic(tdp);
                if (itdp->t_type == INTRINSIC) {
-                       if (mlp->ml_size != itdp->t_intr->intr_nbits) {
+                       if ((int)mlp->ml_size != itdp->t_intr->intr_nbits) {
                                parse_debug(4, cp, "making %d bit intrinsic "
                                    "from %s", mlp->ml_size, tdesc_name(itdp));
                                mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
@@ -1173,7 +1173,7 @@ resolve_typed_bitfields_cb(void *arg, vo
        while (tdp) {
                switch (tdp->t_type) {
                case INTRINSIC:
-                       if (ml->ml_size != tdp->t_intr->intr_nbits) {
+                       if ((int)ml->ml_size != tdp->t_intr->intr_nbits) {
                                debug(3, "making %d bit intrinsic from %s",
                                    ml->ml_size, tdesc_name(tdp));
                                ml->ml_type = bitintrinsic(tdp, ml->ml_size);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to