4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * MDB Regression Test Module
32 * This module contains dcmds and walkers that exercise various aspects of
33 * MDB and the MDB Module API. It can be manually loaded and executed to
34 * verify that MDB is still working properly.
37 #include <mdb/mdb_modapi.h>
39 #include <mdb/mdb_io_impl.h>
44 cd_init(mdb_walk_state_t
*wsp
)
51 cd_step(mdb_walk_state_t
*wsp
)
53 int status
= wsp
->walk_callback(wsp
->walk_addr
, NULL
, wsp
->walk_cbdata
);
55 if (wsp
->walk_addr
-- == 0)
63 cmd_praddr(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
65 if ((flags
!= (DCMD_ADDRSPEC
|DCMD_LOOP
|DCMD_PIPE
)) &&
66 (flags
!= (DCMD_ADDRSPEC
|DCMD_LOOP
|DCMD_PIPE
|DCMD_LOOPFIRST
))) {
67 mdb_warn("ERROR: praddr invoked with flags = 0x%x\n", flags
);
72 mdb_warn("ERROR: praddr invoked with argc = %lu\n", argc
);
76 mdb_printf("%lr\n", addr
);
81 compare(const void *lp
, const void *rp
)
83 uintptr_t lhs
= *((const uintptr_t *)lp
);
84 uintptr_t rhs
= *((const uintptr_t *)rp
);
90 cmd_qsort(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
95 if (flags
!= (DCMD_ADDRSPEC
| DCMD_LOOP
|
96 DCMD_LOOPFIRST
| DCMD_PIPE
| DCMD_PIPE_OUT
)) {
97 mdb_warn("ERROR: qsort invoked with flags = 0x%x\n", flags
);
102 mdb_warn("ERROR: qsort invoked with argc = %lu\n", argc
);
108 if (p
.pipe_data
== NULL
|| p
.pipe_len
!= 16) {
109 mdb_warn("ERROR: qsort got bad results from mdb_get_pipe\n");
113 if (p
.pipe_data
[0] != addr
) {
114 mdb_warn("ERROR: qsort pipe_data[0] != addr\n");
118 qsort(p
.pipe_data
, p
.pipe_len
, sizeof (uintptr_t), compare
);
121 for (i
= 0; i
< 16; i
++) {
122 if (p
.pipe_data
[i
] != i
) {
123 mdb_warn("ERROR: qsort got bad data in slot %lu\n", i
);
133 cmd_runtest(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
135 mdb_walker_t w
= { "count", "count", cd_init
, cd_step
, NULL
};
138 mdb_printf("- adding countdown walker\n");
139 if (mdb_add_walker(&w
) != 0) {
140 mdb_warn("ERROR: failed to add walker");
144 mdb_printf("- executing countdown pipeline\n");
145 if (mdb_eval("::walk mdb_test`count |::mdb_test`qsort |::praddr")) {
146 mdb_warn("ERROR: failed to eval command");
150 mdb_printf("- removing countdown walker\n");
151 if (mdb_remove_walker("count") != 0) {
152 mdb_warn("ERROR: failed to remove walker");
156 state
= mdb_get_state();
157 mdb_printf("- kernel=%d state=%d\n", mdb_prop_kernel
, state
);
159 if (mdb_prop_kernel
&& (state
== MDB_STATE_DEAD
||
160 state
== MDB_STATE_RUNNING
)) {
161 mdb_printf("- exercising pipelines\n");
162 for (i
= 0; i
< 100; i
++) {
163 if (mdb_eval("::walk proc p | ::map *. | ::grep .==0 "
164 "| ::map <p | ::ps") != 0) {
165 mdb_warn("ERROR: failed to eval pipeline");
175 cmd_vread(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
181 if (!(flags
& DCMD_ADDRSPEC
) || argc
!= 1)
184 if (argv
->a_type
== MDB_TYPE_STRING
)
185 nbytes
= (size_t)mdb_strtoull(argv
->a_un
.a_str
);
187 nbytes
= (size_t)argv
->a_un
.a_val
;
189 buf
= mdb_alloc(nbytes
, UM_SLEEP
| UM_GC
);
190 rbytes
= mdb_vread(buf
, nbytes
, addr
);
193 mdb_printf("mdb_vread of %lu bytes returned %ld\n",
196 mdb_warn("mdb_vread returned %ld", rbytes
);
203 cmd_pread(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
209 if (!(flags
& DCMD_ADDRSPEC
) || argc
!= 1)
212 if (argv
->a_type
== MDB_TYPE_STRING
)
213 nbytes
= (size_t)mdb_strtoull(argv
->a_un
.a_str
);
215 nbytes
= (size_t)argv
->a_un
.a_val
;
217 buf
= mdb_alloc(nbytes
, UM_SLEEP
| UM_GC
);
218 rbytes
= mdb_pread(buf
, nbytes
, mdb_get_dot());
221 mdb_printf("mdb_pread of %lu bytes returned %ld\n",
224 mdb_warn("mdb_pread returned %ld", rbytes
);
231 cmd_readsym(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
237 if ((flags
& DCMD_ADDRSPEC
) || argc
!= 2 ||
238 argv
->a_type
!= MDB_TYPE_STRING
)
241 if (argv
[1].a_type
== MDB_TYPE_STRING
)
242 nbytes
= (size_t)mdb_strtoull(argv
[1].a_un
.a_str
);
244 nbytes
= (size_t)argv
[1].a_un
.a_val
;
246 buf
= mdb_alloc(nbytes
, UM_SLEEP
| UM_GC
);
247 rbytes
= mdb_readsym(buf
, nbytes
, argv
->a_un
.a_str
);
250 mdb_printf("mdb_readsym of %lu bytes returned %ld\n",
253 mdb_warn("mdb_readsym returned %ld", rbytes
);
259 cmd_call_dcmd(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
263 if (argc
< 1 || argv
->a_type
!= MDB_TYPE_STRING
)
266 dcmd
= argv
->a_un
.a_str
;
270 if (mdb_call_dcmd(dcmd
, addr
, flags
, argc
, argv
) == -1) {
271 mdb_warn("failed to execute %s", dcmd
);
280 cmd_getsetdot(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
285 mdb_set_dot(0x12345678feedbeefULL
);
287 if (mdb_get_dot() != 0x12345678feedbeefULL
) {
288 mdb_warn("mdb_get_dot() returned wrong value!\n");
296 * kmdb doesn't export some of the symbols used by these tests - namely mdb and
297 * mdb_iob_.*. We therefore can't use these tests with kmdb.
301 do_nputs_tests(const char *banner
, uint_t flags
,
302 size_t rows
, size_t cols
, size_t ocols
)
307 oflags
= mdb_iob_getflags(mdb
.m_out
) &
308 (MDB_IOB_AUTOWRAP
| MDB_IOB_INDENT
);
310 mdb_printf("%s:\n", banner
);
311 for (i
= 0; i
< 8; i
++)
312 mdb_printf("0123456789");
315 mdb_iob_clrflags(mdb
.m_out
, MDB_IOB_AUTOWRAP
| MDB_IOB_INDENT
);
316 mdb_iob_setflags(mdb
.m_out
, flags
);
317 mdb_iob_resize(mdb
.m_out
, rows
, cols
);
319 for (i
= 0; i
< 50; i
++)
323 mdb_iob_clrflags(mdb
.m_out
, flags
);
324 mdb_iob_setflags(mdb
.m_out
, oflags
);
325 mdb_iob_resize(mdb
.m_out
, rows
, ocols
);
330 cmd_nputs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
332 size_t rows
= mdb
.m_out
->iob_rows
;
333 size_t cols
= mdb
.m_out
->iob_cols
;
338 if (!(flags
& DCMD_ADDRSPEC
))
341 do_nputs_tests("tests with (~WRAP, ~INDENT)",
342 0, rows
, addr
, cols
);
344 do_nputs_tests("tests with (WRAP, ~INDENT)",
345 MDB_IOB_AUTOWRAP
, rows
, addr
, cols
);
347 do_nputs_tests("tests with (~WRAP, INDENT)",
348 MDB_IOB_INDENT
, rows
, addr
, cols
);
350 do_nputs_tests("tests with (WRAP, INDENT)",
351 MDB_IOB_AUTOWRAP
| MDB_IOB_INDENT
, rows
, addr
, cols
);
359 cmd_printf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
361 if (argc
!= 2 || argv
[0].a_type
!= MDB_TYPE_STRING
)
364 if (argv
[1].a_type
== MDB_TYPE_STRING
)
365 mdb_printf(argv
[0].a_un
.a_str
, argv
[1].a_un
.a_str
);
367 mdb_printf(argv
[0].a_un
.a_str
, argv
[1].a_un
.a_val
);
374 cmd_abort(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
376 mdb_printf("hello"); /* stuff something in stdout's buffer */
377 return (*((volatile int *)NULL
));
380 static const mdb_dcmd_t dcmds
[] = {
381 { "runtest", NULL
, "run MDB regression tests", cmd_runtest
},
382 { "qsort", NULL
, "qsort addresses", cmd_qsort
},
383 { "praddr", NULL
, "print addresses", cmd_praddr
},
384 { "vread", ":nbytes", "call mdb_vread", cmd_vread
},
385 { "pread", ":nbytes", "call mdb_pread", cmd_pread
},
386 { "readsym", "symbol nbytes", "call mdb_readsym", cmd_readsym
},
387 { "call_dcmd", "dcmd [ args ... ]", "call dcmd", cmd_call_dcmd
},
388 { "getsetdot", NULL
, "test get and set dot", cmd_getsetdot
},
390 { "nputs", "?", "test iob nputs engine", cmd_nputs
},
392 { "printf", "fmt arg", "test printf engine", cmd_printf
},
393 { "abort", NULL
, "test unexpected dcmd abort", cmd_abort
},
397 static const mdb_walker_t walkers
[] = {
398 { "countdown", "count down from 16 to 0", cd_init
, cd_step
, NULL
},
402 static const mdb_modinfo_t modinfo
= { MDB_API_VERSION
, dcmds
, walkers
};
404 const mdb_modinfo_t
*