diff options
author | John Levon <john.levon@joyent.com> | 2020-03-06 02:57:48 -0800 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2020-03-07 09:03:10 -0800 |
commit | f11c6b604a17df4ddc8c4987e50f5b8d8a945516 (patch) | |
tree | cbef0dbf2a3dd834efa7d6fca8611b07c3e33555 | |
parent | ebb7c6fd4f966f94af3e235242b8a39b7a53664a (diff) | |
download | illumos-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.c | 4 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_io.c | 77 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_io.h | 6 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_print.c | 36 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_set.c | 4 |
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) { |