summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2020-03-06 02:57:48 -0800
committerJohn Levon <john.levon@joyent.com>2020-03-07 09:03:10 -0800
commitf11c6b604a17df4ddc8c4987e50f5b8d8a945516 (patch)
treecbef0dbf2a3dd834efa7d6fca8611b07c3e33555
parentebb7c6fd4f966f94af3e235242b8a39b7a53664a (diff)
downloadillumos-joyent-f11c6b604a17df4ddc8c4987e50f5b8d8a945516.tar.gz
12364 mdb trips assertion related to autowrap
Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_fmt.c4
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_io.c77
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_io.h6
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.c36
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_set.c4
5 files changed, 86 insertions, 41 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c
index e03a3bcb6e..662cf7bea5 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c
@@ -21,7 +21,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
* Copyright (c) 2017 by Delphix. All rights reserved.
*/
@@ -733,7 +733,7 @@ mdb_fmt_print(mdb_tgt_t *t, mdb_tgt_as_t as,
* Unless a format has explicitly opted out, we force autowrap
* for the duration of mdb_fmt_print().
*/
- mdb.m_flags |= MDB_FL_AUTOWRAP;
+ mdb_iob_set_autowrap(mdb.m_out);
}
switch (FMT_TYPE(fp->f_type)) {
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_io.c b/usr/src/cmd/mdb/common/mdb/mdb_io.c
index f1ad8d051c..752c6f5c35 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_io.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_io.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc. All rights reserved.
+ * Copyright 2020 Joyent, Inc.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
@@ -1777,6 +1777,27 @@ mdb_iob_snprintf(char *buf, size_t nbytes, const char *format, ...)
return (nbytes);
}
+/*
+ * Return how many bytes we can copy into our buffer, limited by either cols or
+ * bufsiz depending on whether AUTOWRAP is on. Note that typically,
+ * mdb_iob_set_autowrap() will have already checked for an existing
+ * "->iob_nbytes > ->iob_cols" situation, but we double check here anyway.
+ */
+static size_t
+iob_bufleft(mdb_iob_t *iob)
+{
+ if (IOB_AUTOWRAP(iob)) {
+ if (iob->iob_cols < iob->iob_nbytes) {
+ mdb_iob_nl(iob);
+ ASSERT(iob->iob_cols >= iob->iob_nbytes);
+ }
+ return (iob->iob_cols - iob->iob_nbytes);
+ }
+
+ ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
+ return (iob->iob_bufsiz - iob->iob_nbytes);
+}
+
void
mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
{
@@ -1810,20 +1831,11 @@ mdb_iob_nputs(mdb_iob_t *iob, const char *s, size_t nbytes)
}
/*
- * For a given string component, we determine how many bytes (n) we can
- * copy into our buffer (limited by either cols or bufsiz depending
- * on whether AUTOWRAP is on), copy a chunk into the buffer, and
+ * For a given string component, we copy a chunk into the buffer, and
* flush the buffer if we reach the end of a line.
*/
while (nleft != 0) {
- if (IOB_AUTOWRAP(iob)) {
- ASSERT(iob->iob_cols >= iob->iob_nbytes);
- n = iob->iob_cols - iob->iob_nbytes;
- } else {
- ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
- n = iob->iob_bufsiz - iob->iob_nbytes;
- }
-
+ n = iob_bufleft(iob);
m = MIN(nleft, n); /* copy at most n bytes in this pass */
bcopy(q, iob->iob_bufp, m);
@@ -1884,14 +1896,7 @@ mdb_iob_fill(mdb_iob_t *iob, int c, size_t nfill)
ASSERT(iob->iob_flags & MDB_IOB_WRONLY);
while (nfill != 0) {
- if (IOB_AUTOWRAP(iob)) {
- ASSERT(iob->iob_cols >= iob->iob_nbytes);
- n = iob->iob_cols - iob->iob_nbytes;
- } else {
- ASSERT(iob->iob_bufsiz >= iob->iob_nbytes);
- n = iob->iob_bufsiz - iob->iob_nbytes;
- }
-
+ n = iob_bufleft(iob);
m = MIN(nfill, n); /* fill at most n bytes in this pass */
for (i = 0; i < m; i++)
@@ -2169,6 +2174,26 @@ mdb_iob_stack_size(mdb_iob_stack_t *stk)
}
/*
+ * This only enables autowrap for iobs that are already autowrap themselves such
+ * as mdb.m_out typically.
+ *
+ * Note that we might be the middle of the iob buffer at this point, and
+ * specifically, iob->iob_nbytes could be more than iob->iob_cols. As that's
+ * not a valid situation, we may need to do an autowrap *now*.
+ *
+ * In theory, we would need to do this across all MDB_IOB_AUTOWRAP iob's;
+ * instead, we have a failsafe in iob_bufleft().
+ */
+void
+mdb_iob_set_autowrap(mdb_iob_t *iob)
+{
+ mdb.m_flags |= MDB_FL_AUTOWRAP;
+ if (IOB_WRAPNOW(iob, 0))
+ mdb_iob_nl(iob);
+ ASSERT(iob->iob_cols >= iob->iob_nbytes);
+}
+
+/*
* Stub functions for i/o backend implementors: these stubs either act as
* pass-through no-ops or return ENOTSUP as appropriate.
*/
@@ -2267,14 +2292,14 @@ no_io_resume(mdb_io_t *io)
/*
* Iterate over the varargs. The first item indicates the mode:
* MDB_TBL_PRNT
- * pull out the next vararg as a const char * and pass it and the
- * remaining varargs to iob_doprnt; if we want to print the column,
- * direct the output to mdb.m_out otherwise direct it to mdb.m_null
+ * pull out the next vararg as a const char * and pass it and the
+ * remaining varargs to iob_doprnt; if we want to print the column,
+ * direct the output to mdb.m_out otherwise direct it to mdb.m_null
*
* MDB_TBL_FUNC
- * pull out the next vararg as type mdb_table_print_f and the
- * following one as a void * argument to the function; call the
- * function with the given argument if we want to print the column
+ * pull out the next vararg as type mdb_table_print_f and the
+ * following one as a void * argument to the function; call the
+ * function with the given argument if we want to print the column
*
* The second item indicates the flag; if the flag is set in the flags
* argument, then the column is printed. A flag value of 0 indicates
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_io.h b/usr/src/cmd/mdb/common/mdb/mdb_io.h
index 2ef4677db4..0c41c5c740 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_io.h
+++ b/usr/src/cmd/mdb/common/mdb/mdb_io.h
@@ -21,13 +21,13 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2020 Joyent, Inc.
*/
#ifndef _MDB_IO_H
#define _MDB_IO_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -149,6 +149,8 @@ extern size_t mdb_iob_lineno(mdb_iob_t *);
extern size_t mdb_iob_gettabstop(mdb_iob_t *);
extern size_t mdb_iob_getmargin(mdb_iob_t *);
+extern void mdb_iob_set_autowrap(mdb_iob_t *);
+
extern void mdb_iob_stack_create(mdb_iob_stack_t *);
extern void mdb_iob_stack_destroy(mdb_iob_stack_t *);
extern void mdb_iob_stack_push(mdb_iob_stack_t *, mdb_iob_t *, size_t);
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.c b/usr/src/cmd/mdb/common/mdb/mdb_print.c
index b39c7e87fe..62338f78a2 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_print.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c
@@ -25,7 +25,7 @@
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
* Copyright (c) 2014 Nexenta Systems, Inc. All rights reserved.
*/
@@ -931,6 +931,30 @@ print_bitfield(ulong_t off, printarg_t *pap, ctf_encoding_t *ep)
}
/*
+ * We want to print an escaped char as e.g. '\0'. We don't use mdb_fmt_print()
+ * as it won't get auto-wrap right here (although even now, we don't include any
+ * trailing comma).
+ */
+static int
+print_char_val(mdb_tgt_addr_t addr, printarg_t *pap)
+{
+ char cval;
+ char *s;
+
+ if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &cval, 1, addr) != 1)
+ return (1);
+
+ if (mdb.m_flags & MDB_FL_ADB)
+ s = strchr2adb(&cval, 1);
+ else
+ s = strchr2esc(&cval, 1);
+
+ mdb_printf("'%s'", s);
+ strfree(s);
+ return (0);
+}
+
+/*
* Print out a character or integer value. We use some simple heuristics,
* described below, to determine the appropriate radix to use for output.
*/
@@ -971,14 +995,8 @@ print_int_val(const char *type, ctf_encoding_t *ep, ulong_t off,
if (size > 8 || (ep->cte_bits % NBBY) != 0 || (size & (size - 1)) != 0)
return (print_bitfield(off, pap, ep));
- if (IS_CHAR(*ep)) {
- mdb_printf("'");
- if (mdb_fmt_print(pap->pa_tgt, pap->pa_as,
- addr, 1, 'C') == addr)
- return (1);
- mdb_printf("'");
- return (0);
- }
+ if (IS_CHAR(*ep))
+ return (print_char_val(addr, pap));
if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &u.i8, size, addr) != size) {
mdb_warn("failed to read %lu bytes at %llx",
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_set.c b/usr/src/cmd/mdb/common/mdb/mdb_set.c
index cd8926fbcc..8d4a1d30f7 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_set.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_set.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
*/
/*
@@ -275,7 +275,7 @@ print_properties(void)
* we enable it for the duration of the command.
*/
oflags = mdb.m_flags;
- mdb.m_flags |= MDB_FL_AUTOWRAP;
+ mdb_iob_set_autowrap(mdb.m_out);
mdb_printf("follow_exec_mode=");
switch (mdb.m_execmode) {