7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2019, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2016 by Delphix. All rights reserved.
29 */
30
31 /*
32 * MDB uses its own enhanced standard i/o mechanism for all input and output.
33 * This file provides the underpinnings of this mechanism, including the
34 * printf-style formatting code, the output pager, and APIs for raw input
35 * and output. This mechanism is used throughout the debugger for everything
36 * from simple sprintf and printf-style formatting, to input to the lexer
37 * and parser, to raw file i/o for reading ELF files. In general, we divide
38 * our i/o implementation into two parts:
39 *
40 * (1) An i/o buffer (mdb_iob_t) provides buffered read or write capabilities,
41 * as well as access to formatting and the ability to invoke a pager. The
42 * buffer is constructed explicitly for use in either reading or writing; it
43 * may not be used for both simultaneously.
44 *
45 * (2) Each i/o buffer is associated with an underlying i/o backend (mdb_io_t).
46 * The backend provides, through an ops-vector, equivalents for the standard
47 * read, write, lseek, ioctl, and close operations. In addition, the backend
1760 *spb.spb_buf = '\0';
1761 else if (buf != NULL && nbytes > 0)
1762 *--spb.spb_buf = '\0';
1763
1764 return (spb.spb_total);
1765 }
1766
1767 /*PRINTFLIKE3*/
1768 size_t
1769 mdb_iob_snprintf(char *buf, size_t nbytes, const char *format, ...)
1770 {
1771 va_list alist;
1772
1773 va_start(alist, format);
1774 nbytes = mdb_iob_vsnprintf(buf, nbytes, format, alist);
1775 va_end(alist);
1776
1777 return (nbytes);
1778 }
1779
1780 void
1781 mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
1782 {
1783 size_t m, n, nleft = nbytes;
1784 const char *p, *q = s;
1785
1786 ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1787
1788 if (nbytes == 0)
1789 return; /* Return immediately if there is no work to do */
1790
1791 /*
1792 * If the string contains embedded newlines or tabs, invoke ourself
1793 * recursively for each string component, followed by a call to the
1794 * newline or tab routine. This insures that strings with these
1795 * characters obey our wrapping and indenting rules, and that strings
1796 * with embedded newlines are flushed after each newline, allowing
1797 * the output pager to take over if it is enabled.
1798 */
1799 while ((p = strnpbrk(q, "\t\n", nleft)) != NULL) {
1800 if (p > q)
1801 mdb_iob_nputs(iob, q, (size_t)(p - q));
1802
1803 if (*p == '\t')
1804 mdb_iob_tab(iob);
1805 else
1806 mdb_iob_nl(iob);
1807
1808 nleft -= (size_t)(p - q) + 1; /* Update byte count */
1809 q = p + 1; /* Advance past delimiter */
1810 }
1811
1812 /*
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
1816 * flush the buffer if we reach the end of a line.
1817 */
1818 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
1827 m = MIN(nleft, n); /* copy at most n bytes in this pass */
1828
1829 bcopy(q, iob->iob_bufp, m);
1830 nleft -= m;
1831 q += m;
1832
1833 iob->iob_bufp += m;
1834 iob->iob_nbytes += m;
1835
1836 if (m == n && nleft != 0) {
1837 if (IOB_AUTOWRAP(iob)) {
1838 mdb_iob_nl(iob);
1839 } else {
1840 mdb_iob_flush(iob);
1841 }
1842 }
1843 }
1844 }
1845
1846 void
1867 * insert sufficient whitespace to reach position n.
1868 */
1869 size_t n = (iob->iob_nbytes + iob->iob_tabstop) /
1870 iob->iob_tabstop * iob->iob_tabstop;
1871
1872 if (n < iob->iob_cols)
1873 mdb_iob_fill(iob, ' ', n - iob->iob_nbytes);
1874 else
1875 mdb_iob_nl(iob);
1876 }
1877 }
1878
1879 void
1880 mdb_iob_fill(mdb_iob_t *iob, int c, size_t nfill)
1881 {
1882 size_t i, m, n;
1883
1884 ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1885
1886 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
1895 m = MIN(nfill, n); /* fill at most n bytes in this pass */
1896
1897 for (i = 0; i < m; i++)
1898 *iob->iob_bufp++ = (char)c;
1899
1900 iob->iob_nbytes += m;
1901 nfill -= m;
1902
1903 if (m == n && nfill != 0) {
1904 if (IOB_AUTOWRAP(iob)) {
1905 mdb_iob_nl(iob);
1906 } else {
1907 mdb_iob_flush(iob);
1908 }
1909 }
1910 }
1911 }
1912
1913 void
1914 mdb_iob_ws(mdb_iob_t *iob, size_t n)
2151 mdb_iob_t *
2152 mdb_iob_stack_pop(mdb_iob_stack_t *stk)
2153 {
2154 mdb_iob_t *top = stk->stk_top;
2155
2156 ASSERT(top != NULL);
2157
2158 stk->stk_top = top->iob_next;
2159 top->iob_next = NULL;
2160 stk->stk_size--;
2161
2162 return (top);
2163 }
2164
2165 size_t
2166 mdb_iob_stack_size(mdb_iob_stack_t *stk)
2167 {
2168 return (stk->stk_size);
2169 }
2170
2171 /*
2172 * Stub functions for i/o backend implementors: these stubs either act as
2173 * pass-through no-ops or return ENOTSUP as appropriate.
2174 */
2175 ssize_t
2176 no_io_read(mdb_io_t *io, void *buf, size_t nbytes)
2177 {
2178 if (io->io_next != NULL)
2179 return (IOP_READ(io->io_next, buf, nbytes));
2180
2181 return (set_errno(EMDB_IOWO));
2182 }
2183
2184 ssize_t
2185 no_io_write(mdb_io_t *io, const void *buf, size_t nbytes)
2186 {
2187 if (io->io_next != NULL)
2188 return (IOP_WRITE(io->io_next, buf, nbytes));
2189
2190 return (set_errno(EMDB_IORO));
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2020 Joyent, Inc.
28 * Copyright (c) 2016 by Delphix. All rights reserved.
29 */
30
31 /*
32 * MDB uses its own enhanced standard i/o mechanism for all input and output.
33 * This file provides the underpinnings of this mechanism, including the
34 * printf-style formatting code, the output pager, and APIs for raw input
35 * and output. This mechanism is used throughout the debugger for everything
36 * from simple sprintf and printf-style formatting, to input to the lexer
37 * and parser, to raw file i/o for reading ELF files. In general, we divide
38 * our i/o implementation into two parts:
39 *
40 * (1) An i/o buffer (mdb_iob_t) provides buffered read or write capabilities,
41 * as well as access to formatting and the ability to invoke a pager. The
42 * buffer is constructed explicitly for use in either reading or writing; it
43 * may not be used for both simultaneously.
44 *
45 * (2) Each i/o buffer is associated with an underlying i/o backend (mdb_io_t).
46 * The backend provides, through an ops-vector, equivalents for the standard
47 * read, write, lseek, ioctl, and close operations. In addition, the backend
1760 *spb.spb_buf = '\0';
1761 else if (buf != NULL && nbytes > 0)
1762 *--spb.spb_buf = '\0';
1763
1764 return (spb.spb_total);
1765 }
1766
1767 /*PRINTFLIKE3*/
1768 size_t
1769 mdb_iob_snprintf(char *buf, size_t nbytes, const char *format, ...)
1770 {
1771 va_list alist;
1772
1773 va_start(alist, format);
1774 nbytes = mdb_iob_vsnprintf(buf, nbytes, format, alist);
1775 va_end(alist);
1776
1777 return (nbytes);
1778 }
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
1801 void
1802 mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
1803 {
1804 size_t m, n, nleft = nbytes;
1805 const char *p, *q = s;
1806
1807 ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1808
1809 if (nbytes == 0)
1810 return; /* Return immediately if there is no work to do */
1811
1812 /*
1813 * If the string contains embedded newlines or tabs, invoke ourself
1814 * recursively for each string component, followed by a call to the
1815 * newline or tab routine. This insures that strings with these
1816 * characters obey our wrapping and indenting rules, and that strings
1817 * with embedded newlines are flushed after each newline, allowing
1818 * the output pager to take over if it is enabled.
1819 */
1820 while ((p = strnpbrk(q, "\t\n", nleft)) != NULL) {
1821 if (p > q)
1822 mdb_iob_nputs(iob, q, (size_t)(p - q));
1823
1824 if (*p == '\t')
1825 mdb_iob_tab(iob);
1826 else
1827 mdb_iob_nl(iob);
1828
1829 nleft -= (size_t)(p - q) + 1; /* Update byte count */
1830 q = p + 1; /* Advance past delimiter */
1831 }
1832
1833 /*
1834 * For a given string component, we copy a chunk into the buffer, and
1835 * flush the buffer if we reach the end of a line.
1836 */
1837 while (nleft != 0) {
1838 n = iob_bufleft(iob);
1839 m = MIN(nleft, n); /* copy at most n bytes in this pass */
1840
1841 bcopy(q, iob->iob_bufp, m);
1842 nleft -= m;
1843 q += m;
1844
1845 iob->iob_bufp += m;
1846 iob->iob_nbytes += m;
1847
1848 if (m == n && nleft != 0) {
1849 if (IOB_AUTOWRAP(iob)) {
1850 mdb_iob_nl(iob);
1851 } else {
1852 mdb_iob_flush(iob);
1853 }
1854 }
1855 }
1856 }
1857
1858 void
1879 * insert sufficient whitespace to reach position n.
1880 */
1881 size_t n = (iob->iob_nbytes + iob->iob_tabstop) /
1882 iob->iob_tabstop * iob->iob_tabstop;
1883
1884 if (n < iob->iob_cols)
1885 mdb_iob_fill(iob, ' ', n - iob->iob_nbytes);
1886 else
1887 mdb_iob_nl(iob);
1888 }
1889 }
1890
1891 void
1892 mdb_iob_fill(mdb_iob_t *iob, int c, size_t nfill)
1893 {
1894 size_t i, m, n;
1895
1896 ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
1897
1898 while (nfill != 0) {
1899 n = iob_bufleft(iob);
1900 m = MIN(nfill, n); /* fill at most n bytes in this pass */
1901
1902 for (i = 0; i < m; i++)
1903 *iob->iob_bufp++ = (char)c;
1904
1905 iob->iob_nbytes += m;
1906 nfill -= m;
1907
1908 if (m == n && nfill != 0) {
1909 if (IOB_AUTOWRAP(iob)) {
1910 mdb_iob_nl(iob);
1911 } else {
1912 mdb_iob_flush(iob);
1913 }
1914 }
1915 }
1916 }
1917
1918 void
1919 mdb_iob_ws(mdb_iob_t *iob, size_t n)
2156 mdb_iob_t *
2157 mdb_iob_stack_pop(mdb_iob_stack_t *stk)
2158 {
2159 mdb_iob_t *top = stk->stk_top;
2160
2161 ASSERT(top != NULL);
2162
2163 stk->stk_top = top->iob_next;
2164 top->iob_next = NULL;
2165 stk->stk_size--;
2166
2167 return (top);
2168 }
2169
2170 size_t
2171 mdb_iob_stack_size(mdb_iob_stack_t *stk)
2172 {
2173 return (stk->stk_size);
2174 }
2175
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 /*
2197 * Stub functions for i/o backend implementors: these stubs either act as
2198 * pass-through no-ops or return ENOTSUP as appropriate.
2199 */
2200 ssize_t
2201 no_io_read(mdb_io_t *io, void *buf, size_t nbytes)
2202 {
2203 if (io->io_next != NULL)
2204 return (IOP_READ(io->io_next, buf, nbytes));
2205
2206 return (set_errno(EMDB_IOWO));
2207 }
2208
2209 ssize_t
2210 no_io_write(mdb_io_t *io, const void *buf, size_t nbytes)
2211 {
2212 if (io->io_next != NULL)
2213 return (IOP_WRITE(io->io_next, buf, nbytes));
2214
2215 return (set_errno(EMDB_IORO));
|