Print this page
12364 mdb trips assertion related to autowrap

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mdb/common/mdb/mdb_io.c
          +++ new/usr/src/cmd/mdb/common/mdb/mdb_io.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
  27      - * Copyright (c) 2019, Joyent, Inc. All rights reserved.
       27 + * Copyright 2020 Joyent, Inc.
  28   28   * Copyright (c) 2016 by Delphix. All rights reserved.
  29   29   */
  30   30  
  31   31  /*
  32   32   * MDB uses its own enhanced standard i/o mechanism for all input and output.
  33   33   * This file provides the underpinnings of this mechanism, including the
  34   34   * printf-style formatting code, the output pager, and APIs for raw input
  35   35   * and output.  This mechanism is used throughout the debugger for everything
  36   36   * from simple sprintf and printf-style formatting, to input to the lexer
  37   37   * and parser, to raw file i/o for reading ELF files.  In general, we divide
↓ open down ↓ 1732 lines elided ↑ open up ↑
1770 1770  {
1771 1771          va_list alist;
1772 1772  
1773 1773          va_start(alist, format);
1774 1774          nbytes = mdb_iob_vsnprintf(buf, nbytes, format, alist);
1775 1775          va_end(alist);
1776 1776  
1777 1777          return (nbytes);
1778 1778  }
1779 1779  
     1780 +/*
     1781 + * Return how many bytes we can copy into our buffer, limited by either cols or
     1782 + * bufsiz depending on whether AUTOWRAP is on.  Note that typically,
     1783 + * mdb_iob_set_autowrap() will have already checked for an existing
     1784 + * "->iob_nbytes > ->iob_cols" situation, but we double check here anyway.
     1785 + */
     1786 +static size_t
     1787 +iob_bufleft(mdb_iob_t *iob)
     1788 +{
     1789 +        if (IOB_AUTOWRAP(iob)) {
     1790 +                if (iob->iob_cols < iob->iob_nbytes) {
     1791 +                        mdb_iob_nl(iob);
     1792 +                        ASSERT(iob->iob_cols >= iob->iob_nbytes);
     1793 +                }
     1794 +                return (iob->iob_cols - iob->iob_nbytes);
     1795 +        }
     1796 +
     1797 +        ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
     1798 +        return (iob->iob_bufsiz - iob->iob_nbytes);
     1799 +}
     1800 +
1780 1801  void
1781 1802  mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
1782 1803  {
1783 1804          size_t m, n, nleft = nbytes;
1784 1805          const char *p, *q = s;
1785 1806  
1786 1807          ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1787 1808  
1788 1809          if (nbytes == 0)
1789 1810                  return; /* Return immediately if there is no work to do */
↓ open down ↓ 13 lines elided ↑ open up ↑
1803 1824                  if (*p == '\t')
1804 1825                          mdb_iob_tab(iob);
1805 1826                  else
1806 1827                          mdb_iob_nl(iob);
1807 1828  
1808 1829                  nleft -= (size_t)(p - q) + 1;   /* Update byte count */
1809 1830                  q = p + 1;                      /* Advance past delimiter */
1810 1831          }
1811 1832  
1812 1833          /*
1813      -         * For a given string component, we determine how many bytes (n) we can
1814      -         * copy into our buffer (limited by either cols or bufsiz depending
1815      -         * on whether AUTOWRAP is on), copy a chunk into the buffer, and
     1834 +         * For a given string component, we copy a chunk into the buffer, and
1816 1835           * flush the buffer if we reach the end of a line.
1817 1836           */
1818 1837          while (nleft != 0) {
1819      -                if (IOB_AUTOWRAP(iob)) {
1820      -                        ASSERT(iob->iob_cols >= iob->iob_nbytes);
1821      -                        n = iob->iob_cols - iob->iob_nbytes;
1822      -                } else {
1823      -                        ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
1824      -                        n = iob->iob_bufsiz - iob->iob_nbytes;
1825      -                }
1826      -
     1838 +                n = iob_bufleft(iob);
1827 1839                  m = MIN(nleft, n); /* copy at most n bytes in this pass */
1828 1840  
1829 1841                  bcopy(q, iob->iob_bufp, m);
1830 1842                  nleft -= m;
1831 1843                  q += m;
1832 1844  
1833 1845                  iob->iob_bufp += m;
1834 1846                  iob->iob_nbytes += m;
1835 1847  
1836 1848                  if (m == n && nleft != 0) {
↓ open down ↓ 40 lines elided ↑ open up ↑
1877 1889  }
1878 1890  
1879 1891  void
1880 1892  mdb_iob_fill(mdb_iob_t *iob, int c, size_t nfill)
1881 1893  {
1882 1894          size_t i, m, n;
1883 1895  
1884 1896          ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1885 1897  
1886 1898          while (nfill != 0) {
1887      -                if (IOB_AUTOWRAP(iob)) {
1888      -                        ASSERT(iob->iob_cols >= iob->iob_nbytes);
1889      -                        n = iob->iob_cols - iob->iob_nbytes;
1890      -                } else {
1891      -                        ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
1892      -                        n = iob->iob_bufsiz - iob->iob_nbytes;
1893      -                }
1894      -
     1899 +                n = iob_bufleft(iob);
1895 1900                  m = MIN(nfill, n); /* fill at most n bytes in this pass */
1896 1901  
1897 1902                  for (i = 0; i < m; i++)
1898 1903                          *iob->iob_bufp++ = (char)c;
1899 1904  
1900 1905                  iob->iob_nbytes += m;
1901 1906                  nfill -= m;
1902 1907  
1903 1908                  if (m == n && nfill != 0) {
1904 1909                          if (IOB_AUTOWRAP(iob)) {
↓ open down ↓ 257 lines elided ↑ open up ↑
2162 2167          return (top);
2163 2168  }
2164 2169  
2165 2170  size_t
2166 2171  mdb_iob_stack_size(mdb_iob_stack_t *stk)
2167 2172  {
2168 2173          return (stk->stk_size);
2169 2174  }
2170 2175  
2171 2176  /*
     2177 + * This only enables autowrap for iobs that are already autowrap themselves such
     2178 + * as mdb.m_out typically.
     2179 + *
     2180 + * Note that we might be the middle of the iob buffer at this point, and
     2181 + * specifically, iob->iob_nbytes could be more than iob->iob_cols.  As that's
     2182 + * not a valid situation, we may need to do an autowrap *now*.
     2183 + *
     2184 + * In theory, we would need to do this across all MDB_IOB_AUTOWRAP iob's;
     2185 + * instead, we have a failsafe in iob_bufleft().
     2186 + */
     2187 +void
     2188 +mdb_iob_set_autowrap(mdb_iob_t *iob)
     2189 +{
     2190 +        mdb.m_flags |= MDB_FL_AUTOWRAP;
     2191 +        if (IOB_WRAPNOW(iob, 0))
     2192 +                mdb_iob_nl(iob);
     2193 +        ASSERT(iob->iob_cols >= iob->iob_nbytes);
     2194 +}
     2195 +
     2196 +/*
2172 2197   * Stub functions for i/o backend implementors: these stubs either act as
2173 2198   * pass-through no-ops or return ENOTSUP as appropriate.
2174 2199   */
2175 2200  ssize_t
2176 2201  no_io_read(mdb_io_t *io, void *buf, size_t nbytes)
2177 2202  {
2178 2203          if (io->io_next != NULL)
2179 2204                  return (IOP_READ(io->io_next, buf, nbytes));
2180 2205  
2181 2206          return (set_errno(EMDB_IOWO));
↓ open down ↓ 78 lines elided ↑ open up ↑
2260 2285  void
2261 2286  no_io_resume(mdb_io_t *io)
2262 2287  {
2263 2288          if (io->io_next != NULL)
2264 2289                  IOP_RESUME(io->io_next);
2265 2290  }
2266 2291  
2267 2292  /*
2268 2293   * Iterate over the varargs. The first item indicates the mode:
2269 2294   * MDB_TBL_PRNT
2270      - *      pull out the next vararg as a const char * and pass it and the
2271      - *      remaining varargs to iob_doprnt; if we want to print the column,
2272      - *      direct the output to mdb.m_out otherwise direct it to mdb.m_null
     2295 + *      pull out the next vararg as a const char * and pass it and the
     2296 + *      remaining varargs to iob_doprnt; if we want to print the column,
     2297 + *      direct the output to mdb.m_out otherwise direct it to mdb.m_null
2273 2298   *
2274 2299   * MDB_TBL_FUNC
2275      - *      pull out the next vararg as type mdb_table_print_f and the
2276      - *      following one as a void * argument to the function; call the
2277      - *      function with the given argument if we want to print the column
     2300 + *      pull out the next vararg as type mdb_table_print_f and the
     2301 + *      following one as a void * argument to the function; call the
     2302 + *      function with the given argument if we want to print the column
2278 2303   *
2279 2304   * The second item indicates the flag; if the flag is set in the flags
2280 2305   * argument, then the column is printed. A flag value of 0 indicates
2281 2306   * that the column should always be printed.
2282 2307   */
2283 2308  void
2284 2309  mdb_table_print(uint_t flags, const char *delimeter, ...)
2285 2310  {
2286 2311          va_list alist;
2287 2312          uint_t flg;
↓ open down ↓ 51 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX