dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / mdb_test / mdb_test.c
blobda6e8be326de9f8b82ed6d77996edabdb5f896b2
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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>
38 #define _MDB
39 #include <mdb/mdb_io_impl.h>
40 #include <mdb/mdb.h>
41 #undef _MDB
43 static int
44 cd_init(mdb_walk_state_t *wsp)
46 wsp->walk_addr = 0xf;
47 return (WALK_NEXT);
50 static int
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)
56 return (WALK_DONE);
58 return (status);
61 /*ARGSUSED*/
62 static int
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);
68 return (DCMD_ERR);
71 if (argc != 0) {
72 mdb_warn("ERROR: praddr invoked with argc = %lu\n", argc);
73 return (DCMD_ERR);
76 mdb_printf("%lr\n", addr);
77 return (DCMD_OK);
80 static int
81 compare(const void *lp, const void *rp)
83 uintptr_t lhs = *((const uintptr_t *)lp);
84 uintptr_t rhs = *((const uintptr_t *)rp);
85 return (lhs - rhs);
88 /*ARGSUSED*/
89 static int
90 cmd_qsort(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
92 mdb_pipe_t p;
93 size_t i;
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);
98 return (DCMD_ERR);
101 if (argc != 0) {
102 mdb_warn("ERROR: qsort invoked with argc = %lu\n", argc);
103 return (DCMD_ERR);
106 mdb_get_pipe(&p);
108 if (p.pipe_data == NULL || p.pipe_len != 16) {
109 mdb_warn("ERROR: qsort got bad results from mdb_get_pipe\n");
110 return (DCMD_ERR);
113 if (p.pipe_data[0] != addr) {
114 mdb_warn("ERROR: qsort pipe_data[0] != addr\n");
115 return (DCMD_ERR);
118 qsort(p.pipe_data, p.pipe_len, sizeof (uintptr_t), compare);
119 mdb_set_pipe(&p);
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);
124 return (DCMD_ERR);
128 return (DCMD_OK);
131 /*ARGSUSED*/
132 static int
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 };
136 int state, i;
138 mdb_printf("- adding countdown walker\n");
139 if (mdb_add_walker(&w) != 0) {
140 mdb_warn("ERROR: failed to add walker");
141 return (DCMD_ERR);
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");
147 return (DCMD_ERR);
150 mdb_printf("- removing countdown walker\n");
151 if (mdb_remove_walker("count") != 0) {
152 mdb_warn("ERROR: failed to remove walker");
153 return (DCMD_ERR);
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");
166 return (DCMD_ERR);
171 return (DCMD_OK);
174 static int
175 cmd_vread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
177 size_t nbytes;
178 ssize_t rbytes;
179 void *buf;
181 if (!(flags & DCMD_ADDRSPEC) || argc != 1)
182 return (DCMD_USAGE);
184 if (argv->a_type == MDB_TYPE_STRING)
185 nbytes = (size_t)mdb_strtoull(argv->a_un.a_str);
186 else
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);
192 if (rbytes >= 0) {
193 mdb_printf("mdb_vread of %lu bytes returned %ld\n",
194 nbytes, rbytes);
195 } else
196 mdb_warn("mdb_vread returned %ld", rbytes);
198 return (DCMD_OK);
201 /*ARGSUSED*/
202 static int
203 cmd_pread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
205 size_t nbytes;
206 ssize_t rbytes;
207 void *buf;
209 if (!(flags & DCMD_ADDRSPEC) || argc != 1)
210 return (DCMD_USAGE);
212 if (argv->a_type == MDB_TYPE_STRING)
213 nbytes = (size_t)mdb_strtoull(argv->a_un.a_str);
214 else
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());
220 if (rbytes >= 0) {
221 mdb_printf("mdb_pread of %lu bytes returned %ld\n",
222 nbytes, rbytes);
223 } else
224 mdb_warn("mdb_pread returned %ld", rbytes);
226 return (DCMD_OK);
229 /*ARGSUSED*/
230 static int
231 cmd_readsym(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
233 size_t nbytes;
234 ssize_t rbytes;
235 void *buf;
237 if ((flags & DCMD_ADDRSPEC) || argc != 2 ||
238 argv->a_type != MDB_TYPE_STRING)
239 return (DCMD_USAGE);
241 if (argv[1].a_type == MDB_TYPE_STRING)
242 nbytes = (size_t)mdb_strtoull(argv[1].a_un.a_str);
243 else
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);
249 if (rbytes >= 0) {
250 mdb_printf("mdb_readsym of %lu bytes returned %ld\n",
251 nbytes, rbytes);
252 } else
253 mdb_warn("mdb_readsym returned %ld", rbytes);
255 return (DCMD_OK);
258 static int
259 cmd_call_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
261 const char *dcmd;
263 if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
264 return (DCMD_USAGE);
266 dcmd = argv->a_un.a_str;
267 argv++;
268 argc--;
270 if (mdb_call_dcmd(dcmd, addr, flags, argc, argv) == -1) {
271 mdb_warn("failed to execute %s", dcmd);
272 return (DCMD_ERR);
275 return (DCMD_OK);
278 /*ARGSUSED*/
279 static int
280 cmd_getsetdot(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
282 if (argc != 0)
283 return (DCMD_USAGE);
285 mdb_set_dot(0x12345678feedbeefULL);
287 if (mdb_get_dot() != 0x12345678feedbeefULL) {
288 mdb_warn("mdb_get_dot() returned wrong value!\n");
289 return (DCMD_ERR);
292 return (DCMD_OK);
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.
299 #ifndef _KMDB
300 static void
301 do_nputs_tests(const char *banner, uint_t flags,
302 size_t rows, size_t cols, size_t ocols)
304 uint_t oflags;
305 int i;
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");
313 mdb_printf("\n");
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++)
320 mdb_printf(" xx");
321 mdb_printf("\n");
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);
328 /*ARGSUSED*/
329 static int
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;
335 if (argc != 0)
336 return (DCMD_USAGE);
338 if (!(flags & DCMD_ADDRSPEC))
339 addr = cols;
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);
353 return (DCMD_OK);
355 #endif
357 /*ARGSUSED*/
358 static int
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)
362 return (DCMD_USAGE);
364 if (argv[1].a_type == MDB_TYPE_STRING)
365 mdb_printf(argv[0].a_un.a_str, argv[1].a_un.a_str);
366 else
367 mdb_printf(argv[0].a_un.a_str, argv[1].a_un.a_val);
369 return (DCMD_OK);
372 /*ARGSUSED*/
373 static int
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 },
389 #ifndef _KMDB
390 { "nputs", "?", "test iob nputs engine", cmd_nputs },
391 #endif
392 { "printf", "fmt arg", "test printf engine", cmd_printf },
393 { "abort", NULL, "test unexpected dcmd abort", cmd_abort },
394 { NULL }
397 static const mdb_walker_t walkers[] = {
398 { "countdown", "count down from 16 to 0", cd_init, cd_step, NULL },
399 { NULL }
402 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
404 const mdb_modinfo_t *
405 _mdb_init(void)
407 return (&modinfo);