xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_value.c (revision 2c687d6826d5cbe1435931df7165d210c3336019)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
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  * Copyright 2018 Joyent, Inc.
26  */
27 
28 /*
29  * Immediate Value Target
30  *
31  * The immediate value target is used when the '=' verb is used to
32  * format an immediate value, or with ::print -i.  The target is
33  * initialized with a specific value, and then simply copies bytes from
34  * this integer in its read routine.  Two notes:
35  *
36  * (1) the address parameter of value_read is treated as an offset into
37  * the immediate value.
38  *
39  * (2) on big-endian systems, we need to be careful about the place we
40  * copy data from. If the caller specified a typesize in the argv array
41  * we use that for offsetting, otherwise we use the read size.
42  * If the user didn't specify the typesize, then 'addr' is ignored,
43  * and all reads are at an offset of 0 into the immediate value. This
44  * covers both the usage of ::print -i, and the semantics of adb
45  * commands like "0x1234=X", which should produce 0x1234 as a result;
46  * the adb model is for it to act like a cast down to the smaller
47  * integer type; this is handled as mentioned.
48  */
49 
50 #include <mdb/mdb_target_impl.h>
51 #include <mdb/mdb_types.h>
52 #include <mdb/mdb_conf.h>
53 #include <mdb/mdb_err.h>
54 
55 #include <sys/isa_defs.h>
56 #include <strings.h>
57 
58 void mdb_value_tgt_destroy(mdb_tgt_t *);
59 
60 typedef struct mdb_value_data {
61 	uintmax_t mvd_data;
62 	size_t mvd_typesize;
63 } mdb_value_data_t;
64 
65 static ssize_t
66 value_read(mdb_tgt_t *t, void *dst, size_t nbytes, uintptr_t addr)
67 {
68 	mdb_value_data_t *data = t->t_data;
69 	size_t size = data->mvd_typesize;
70 	const char *src = (const char *)&data->mvd_data;
71 	size_t off;
72 
73 	/*
74 	 * If no output size was specified, use the current read size.
75 	 * In this case, "addr" is not an offset into the mvd_data,
76 	 * so we ignore it.
77 	 */
78 	if (size == 0) {
79 		size = nbytes;
80 		addr = 0;
81 	} else {
82 		nbytes = MIN(size, nbytes);
83 	}
84 
85 	off = addr;
86 #ifdef _BIG_ENDIAN
87 	if (sizeof (uintmax_t) >= size)
88 		off += sizeof (uintmax_t) - size;
89 #endif
90 
91 	if (off > sizeof (uintmax_t))
92 		return (0);
93 	if (off + nbytes > sizeof (uintmax_t))
94 		nbytes = sizeof (uintmax_t) - off;
95 
96 	if (nbytes != 0)
97 		bcopy(src + off, dst, nbytes);
98 
99 	return (nbytes);
100 }
101 
102 /*ARGSUSED*/
103 static ssize_t
104 value_write(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
105 {
106 	return (nbytes); /* We allow writes to silently fail */
107 }
108 
109 static const mdb_tgt_ops_t value_ops = {
110 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_setflags */
111 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_setcontext */
112 	(void (*)())(uintptr_t) mdb_tgt_nop,	/* t_activate */
113 	(void (*)())(uintptr_t) mdb_tgt_nop,	/* t_deactivate */
114 	(void (*)())(uintptr_t) mdb_tgt_nop,	/* t_periodic */
115 	mdb_value_tgt_destroy,			/* t_destroy */
116 	(const char *(*)()) mdb_tgt_null,	/* t_name */
117 	(const char *(*)()) mdb_conf_isa,	/* t_isa */
118 	(const char *(*)()) mdb_conf_platform,	/* t_platform */
119 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_uname */
120 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_dmodel */
121 	(ssize_t (*)()) mdb_tgt_notsup,		/* t_aread */
122 	(ssize_t (*)()) mdb_tgt_notsup,		/* t_awrite */
123 	value_read,				/* t_vread */
124 	value_write,				/* t_vwrite */
125 	(ssize_t (*)()) mdb_tgt_notsup,		/* t_pread */
126 	(ssize_t (*)()) mdb_tgt_notsup,		/* t_pwrite */
127 	value_read,				/* t_fread */
128 	value_write,				/* t_fwrite */
129 	value_read,				/* t_ioread */
130 	value_write,				/* t_iowrite */
131 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_vtop */
132 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_lookup_by_name */
133 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_lookup_by_addr */
134 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_symbol_iter */
135 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_mapping_iter */
136 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_object_iter */
137 	(const mdb_map_t *(*)()) mdb_tgt_null,	/* t_addr_to_map */
138 	(const mdb_map_t *(*)()) mdb_tgt_null,	/* t_name_to_map */
139 	(struct ctf_file *(*)()) mdb_tgt_null,	/* t_addr_to_ctf */
140 	(struct ctf_file *(*)()) mdb_tgt_null,	/* t_name_to_ctf */
141 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_status */
142 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_run */
143 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_step */
144 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_step_out */
145 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_next */
146 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_cont */
147 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_signal */
148 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_vbrkpt */
149 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_sbrkpt */
150 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_pwapt */
151 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_vwapt */
152 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_iowapt */
153 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_sysenter */
154 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_sysexit */
155 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_signal */
156 	(int (*)())(uintptr_t) mdb_tgt_null,	/* t_add_fault */
157 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_getareg */
158 	(int (*)())(uintptr_t) mdb_tgt_notsup,	/* t_putareg */
159 	(int (*)())(uintptr_t) mdb_tgt_nop,	/* t_stack_iter */
160 	(int (*)())(uintptr_t) mdb_tgt_notsup	/* t_auxv */
161 };
162 
163 int
164 mdb_value_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
165 {
166 	mdb_value_data_t *data;
167 
168 	if (argc < 1 || argv[0] == NULL)
169 		return (set_errno(EINVAL));
170 	if (argc == 2 && argv[1] == NULL)
171 		return (set_errno(EINVAL));
172 	if (argc > 2)
173 		return (set_errno(EINVAL));
174 
175 	t->t_ops = &value_ops;
176 	data = mdb_zalloc(sizeof (mdb_value_data_t), UM_SLEEP);
177 	t->t_data = data;
178 	data->mvd_data = *((uintmax_t *)(void *)argv[0]);
179 	if (argc == 2)
180 		data->mvd_typesize = *((size_t *)(void *)argv[1]);
181 
182 	return (0);
183 }
184 
185 void
186 mdb_value_tgt_destroy(mdb_tgt_t *t)
187 {
188 	mdb_free(t->t_data, sizeof (mdb_value_data_t));
189 }
190