Print this page
10823 should ignore DW_TAG_subprogram with DW_AT_declaration tags
10824 GCC7-derived CTF can double qualifiers on arrays
10825 ctfdump -c drops last type
10826 ctfdump -c goes off the rails with a missing parent
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libctf/common/ctf_dwarf.c
          +++ new/usr/src/lib/libctf/common/ctf_dwarf.c
↓ open down ↓ 20 lines elided ↑ open up ↑
  21   21  /*
  22   22   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  /*
  26   26   * Copyright 2012 Jason King.  All rights reserved.
  27   27   * Use is subject to license terms.
  28   28   */
  29   29  
  30   30  /*
  31      - * Copyright 2019 Joyent, Inc.
       31 + * Copyright 2019, Joyent, Inc.
  32   32   */
  33   33  
  34   34  /*
  35   35   * CTF DWARF conversion theory.
  36   36   *
  37   37   * DWARF data contains a series of compilation units. Each compilation unit
  38   38   * generally refers to an object file or what once was, in the case of linked
  39   39   * binaries and shared objects. Each compilation unit has a series of what DWARF
  40   40   * calls a DIE (Debugging Information Entry). The set of entries that we care
  41   41   * about have type information stored in a series of attributes. Each DIE also
↓ open down ↓ 1436 lines elided ↑ open up ↑
1478 1478           * subranges. If it's the latter, then for each subrange we introduce a
1479 1479           * type. We can always use the base type.
1480 1480           */
1481 1481          if ((ret = ctf_dwarf_create_array_range(cup, rdie, idp, tid,
1482 1482              isroot)) != 0)
1483 1483                  return (ret);
1484 1484          ctf_dprintf("Got back id %d\n", *idp);
1485 1485          return (ctf_dwmap_add(cup, *idp, die, B_FALSE));
1486 1486  }
1487 1487  
     1488 +/*
     1489 + * Given "const int const_array3[11]", GCC7 at least will create a DIE tree of
     1490 + * DW_TAG_const_type:DW_TAG_array_type:DW_Tag_const_type:<member_type>.
     1491 + *
     1492 + * Given C's syntax, this renders out as "const const int const_array3[11]".  To
     1493 + * get closer to round-tripping (and make the unit tests work), we'll peek for
     1494 + * this case, and avoid adding the extraneous qualifier if we see that the
     1495 + * underlying array referent already has the same qualifier.
     1496 + *
     1497 + * This is unfortunately less trivial than it could be: this issue applies to
     1498 + * qualifier sets like "const volatile", as well as multi-dimensional arrays, so
     1499 + * we need to descend down those.
     1500 + *
     1501 + * Returns CTF_ERR on error, or a boolean value otherwise.
     1502 + */
1488 1503  static int
     1504 +needed_array_qualifier(ctf_cu_t *cup, int kind, ctf_id_t ref_id)
     1505 +{
     1506 +        const ctf_type_t *t;
     1507 +        ctf_arinfo_t arinfo;
     1508 +        int akind;
     1509 +
     1510 +        if (kind != CTF_K_CONST && kind != CTF_K_VOLATILE &&
     1511 +            kind != CTF_K_RESTRICT)
     1512 +                return (1);
     1513 +
     1514 +        if ((t = ctf_dyn_lookup_by_id(cup->cu_ctfp, ref_id)) == NULL)
     1515 +                return (CTF_ERR);
     1516 +
     1517 +        if (LCTF_INFO_KIND(cup->cu_ctfp, t->ctt_info) != CTF_K_ARRAY)
     1518 +                return (1);
     1519 +
     1520 +        if (ctf_dyn_array_info(cup->cu_ctfp, ref_id, &arinfo) != 0)
     1521 +                return (CTF_ERR);
     1522 +
     1523 +        ctf_id_t id = arinfo.ctr_contents;
     1524 +
     1525 +        for (;;) {
     1526 +                if ((t = ctf_dyn_lookup_by_id(cup->cu_ctfp, id)) == NULL)
     1527 +                        return (CTF_ERR);
     1528 +
     1529 +                akind = LCTF_INFO_KIND(cup->cu_ctfp, t->ctt_info);
     1530 +
     1531 +                if (akind == kind)
     1532 +                        break;
     1533 +
     1534 +                if (akind == CTF_K_ARRAY) {
     1535 +                        if (ctf_dyn_array_info(cup->cu_ctfp,
     1536 +                            id, &arinfo) != 0)
     1537 +                                return (CTF_ERR);
     1538 +                        id = arinfo.ctr_contents;
     1539 +                        continue;
     1540 +                }
     1541 +
     1542 +                if (akind != CTF_K_CONST && akind != CTF_K_VOLATILE &&
     1543 +                    akind != CTF_K_RESTRICT)
     1544 +                        break;
     1545 +
     1546 +                id = t->ctt_type;
     1547 +        }
     1548 +
     1549 +        if (kind == akind) {
     1550 +                ctf_dprintf("ignoring extraneous %s qualifier for array %d\n",
     1551 +                    ctf_kind_name(cup->cu_ctfp, kind), ref_id);
     1552 +        }
     1553 +
     1554 +        return (kind != akind);
     1555 +}
     1556 +
     1557 +static int
1489 1558  ctf_dwarf_create_reference(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp,
1490 1559      int kind, int isroot)
1491 1560  {
1492 1561          int ret;
1493 1562          ctf_id_t id;
1494 1563          Dwarf_Die tdie;
1495 1564          char *name;
1496 1565          size_t namelen;
1497 1566  
1498 1567          if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 &&
↓ open down ↓ 18 lines elided ↑ open up ↑
1517 1586                          return (ctf_errno(cup->cu_ctfp));
1518 1587                  }
1519 1588          } else {
1520 1589                  if ((ret = ctf_dwarf_convert_type(cup, tdie, &id,
1521 1590                      CTF_ADD_NONROOT)) != 0) {
1522 1591                          ctf_free(name, namelen);
1523 1592                          return (ret);
1524 1593                  }
1525 1594          }
1526 1595  
     1596 +        if ((ret = needed_array_qualifier(cup, kind, id)) <= 0) {
     1597 +                if (ret != 0) {
     1598 +                        ret = (ctf_errno(cup->cu_ctfp));
     1599 +                } else {
     1600 +                        *idp = id;
     1601 +                }
     1602 +
     1603 +                ctf_free(name, namelen);
     1604 +                return (ret);
     1605 +        }
     1606 +
1527 1607          if ((*idp = ctf_add_reftype(cup->cu_ctfp, isroot, name, id, kind)) ==
1528 1608              CTF_ERR) {
1529 1609                  ctf_free(name, namelen);
1530 1610                  return (ctf_errno(cup->cu_ctfp));
1531 1611          }
1532 1612  
1533 1613          ctf_free(name, namelen);
1534 1614          return (ctf_dwmap_add(cup, *idp, die, B_FALSE));
1535 1615  }
1536 1616  
↓ open down ↓ 277 lines elided ↑ open up ↑
1814 1894                  return (ret);
1815 1895  
1816 1896          arg = child;
1817 1897          while (arg != NULL) {
1818 1898                  Dwarf_Half tag;
1819 1899  
1820 1900                  if ((ret = ctf_dwarf_tag(cup, arg, &tag)) != 0)
1821 1901                          return (ret);
1822 1902  
1823 1903                  /*
1824      -                 * We have to check for a varargs type decleration. This will
     1904 +                 * We have to check for a varargs type declaration. This will
1825 1905                   * happen in one of two ways. If we have a function pointer
1826 1906                   * type, then it'll be done with a tag of type
1827 1907                   * DW_TAG_unspecified_parameters. However, it only means we have
1828 1908                   * a variable number of arguments, if we have more than one
1829 1909                   * argument found so far. Otherwise, when we have a function
1830 1910                   * type, it instead uses a formal parameter whose name is '...'
1831 1911                   * to indicate a variable arguments member.
1832 1912                   *
1833 1913                   * Also, if we have a function pointer, then we have to expect
1834 1914                   * that we might not get a name at all.
↓ open down ↓ 64 lines elided ↑ open up ↑
1899 1979                          return (ret);
1900 1980                  arg = sib;
1901 1981          }
1902 1982  
1903 1983          return (0);
1904 1984  }
1905 1985  
1906 1986  static int
1907 1987  ctf_dwarf_convert_function(ctf_cu_t *cup, Dwarf_Die die)
1908 1988  {
1909      -        int ret;
1910      -        char *name;
1911 1989          ctf_dwfunc_t *cdf;
1912 1990          Dwarf_Die tdie;
     1991 +        Dwarf_Bool b;
     1992 +        char *name;
     1993 +        int ret;
1913 1994  
1914 1995          /*
1915 1996           * Functions that don't have a name are generally functions that have
1916 1997           * been inlined and thus most information about them has been lost. If
1917 1998           * we can't get a name, then instead of returning ENOENT, we silently
1918 1999           * swallow the error.
1919 2000           */
1920 2001          if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0) {
1921 2002                  if (ret == ENOENT)
1922 2003                          return (0);
1923 2004                  return (ret);
1924 2005          }
1925 2006  
1926      -        ctf_dprintf("beginning work on function %s\n", name);
     2007 +        ctf_dprintf("beginning work on function %s (die %llx)\n",
     2008 +            name, ctf_die_offset(die));
     2009 +
     2010 +        if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_declaration, &b)) != 0) {
     2011 +                if (ret != ENOENT)
     2012 +                        return (ret);
     2013 +        } else if (b != 0) {
     2014 +                /*
     2015 +                 * GCC7 at least creates empty DW_AT_declarations for functions
     2016 +                 * defined in headers.  As they lack details on the function
     2017 +                 * prototype, we need to ignore them.  If we later actually
     2018 +                 * see the relevant function's definition, we will see another
     2019 +                 * DW_TAG_subprogram that is more complete.
     2020 +                 */
     2021 +                ctf_dprintf("ignoring declaration of function %s (die %llx)\n",
     2022 +                    name, ctf_die_offset(die));
     2023 +                return (0);
     2024 +        }
     2025 +
1927 2026          if ((cdf = ctf_alloc(sizeof (ctf_dwfunc_t))) == NULL) {
1928 2027                  ctf_free(name, strlen(name) + 1);
1929 2028                  return (ENOMEM);
1930 2029          }
1931 2030          bzero(cdf, sizeof (ctf_dwfunc_t));
1932 2031          cdf->cdf_name = name;
1933 2032  
1934 2033          if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) == 0) {
1935 2034                  if ((ret = ctf_dwarf_convert_type(cup, tdie,
1936 2035                      &(cdf->cdf_fip.ctc_return), CTF_ADD_ROOT)) != 0) {
↓ open down ↓ 1148 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX