xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_value.c (revision 0c1b95be)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57b9b3bf3Sedp  * Common Development and Distribution License (the "License").
67b9b3bf3Sedp  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227b9b3bf3Sedp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24399ca3a7SJohn Levon  *
25399ca3a7SJohn Levon  * Copyright 2018 Joyent, Inc.
26a48fdbefSBryan Cantrill  * Copyright 2024 Oxide Computer Company
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Immediate Value Target
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * The immediate value target is used when the '=' verb is used to
337c478bd9Sstevel@tonic-gate  * format an immediate value, or with ::print -i.  The target is
347c478bd9Sstevel@tonic-gate  * initialized with a specific value, and then simply copies bytes from
357c478bd9Sstevel@tonic-gate  * this integer in its read routine.  Two notes:
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * (1) the address parameter of value_read is treated as an offset into
387c478bd9Sstevel@tonic-gate  * the immediate value.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * (2) on big-endian systems, we need to be careful about the place we
417c478bd9Sstevel@tonic-gate  * copy data from. If the caller specified a typesize in the argv array
427c478bd9Sstevel@tonic-gate  * we use that for offsetting, otherwise we use the read size.
437c478bd9Sstevel@tonic-gate  * If the user didn't specify the typesize, then 'addr' is ignored,
447c478bd9Sstevel@tonic-gate  * and all reads are at an offset of 0 into the immediate value. This
457c478bd9Sstevel@tonic-gate  * covers both the usage of ::print -i, and the semantics of adb
467c478bd9Sstevel@tonic-gate  * commands like "0x1234=X", which should produce 0x1234 as a result;
477c478bd9Sstevel@tonic-gate  * the adb model is for it to act like a cast down to the smaller
487c478bd9Sstevel@tonic-gate  * integer type; this is handled as mentioned.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h>
527c478bd9Sstevel@tonic-gate #include <mdb/mdb_types.h>
537c478bd9Sstevel@tonic-gate #include <mdb/mdb_conf.h>
547c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
577c478bd9Sstevel@tonic-gate #include <strings.h>
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate void mdb_value_tgt_destroy(mdb_tgt_t *);
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate typedef struct mdb_value_data {
627c478bd9Sstevel@tonic-gate 	uintmax_t mvd_data;
637c478bd9Sstevel@tonic-gate 	size_t mvd_typesize;
647c478bd9Sstevel@tonic-gate } mdb_value_data_t;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static ssize_t
value_read(mdb_tgt_t * t,void * dst,size_t nbytes,uintptr_t addr)677c478bd9Sstevel@tonic-gate value_read(mdb_tgt_t *t, void *dst, size_t nbytes, uintptr_t addr)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	mdb_value_data_t *data = t->t_data;
707c478bd9Sstevel@tonic-gate 	size_t size = data->mvd_typesize;
717c478bd9Sstevel@tonic-gate 	const char *src = (const char *)&data->mvd_data;
727c478bd9Sstevel@tonic-gate 	size_t off;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	/*
757c478bd9Sstevel@tonic-gate 	 * If no output size was specified, use the current read size.
767c478bd9Sstevel@tonic-gate 	 * In this case, "addr" is not an offset into the mvd_data,
777c478bd9Sstevel@tonic-gate 	 * so we ignore it.
787c478bd9Sstevel@tonic-gate 	 */
797c478bd9Sstevel@tonic-gate 	if (size == 0) {
807c478bd9Sstevel@tonic-gate 		size = nbytes;
817c478bd9Sstevel@tonic-gate 		addr = 0;
827c478bd9Sstevel@tonic-gate 	} else {
837c478bd9Sstevel@tonic-gate 		nbytes = MIN(size, nbytes);
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	off = addr;
877c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN
887c478bd9Sstevel@tonic-gate 	if (sizeof (uintmax_t) >= size)
897c478bd9Sstevel@tonic-gate 		off += sizeof (uintmax_t) - size;
907c478bd9Sstevel@tonic-gate #endif
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	if (off > sizeof (uintmax_t))
937c478bd9Sstevel@tonic-gate 		return (0);
947c478bd9Sstevel@tonic-gate 	if (off + nbytes > sizeof (uintmax_t))
957c478bd9Sstevel@tonic-gate 		nbytes = sizeof (uintmax_t) - off;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	if (nbytes != 0)
987c478bd9Sstevel@tonic-gate 		bcopy(src + off, dst, nbytes);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	return (nbytes);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1047c478bd9Sstevel@tonic-gate static ssize_t
value_write(mdb_tgt_t * t,const void * buf,size_t nbytes,uintptr_t addr)1057c478bd9Sstevel@tonic-gate value_write(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	return (nbytes); /* We allow writes to silently fail */
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate static const mdb_tgt_ops_t value_ops = {
111*0c1b95beSRichard Lowe 	.t_setflags = (int (*)())(uintptr_t)mdb_tgt_notsup,
112*0c1b95beSRichard Lowe 	.t_setcontext = (int (*)())(uintptr_t)mdb_tgt_notsup,
113*0c1b95beSRichard Lowe 	.t_activate = (void (*)())(uintptr_t)mdb_tgt_nop,
114*0c1b95beSRichard Lowe 	.t_deactivate = (void (*)())(uintptr_t)mdb_tgt_nop,
115*0c1b95beSRichard Lowe 	.t_periodic = (void (*)())(uintptr_t)mdb_tgt_nop,
116*0c1b95beSRichard Lowe 	.t_destroy = mdb_value_tgt_destroy,
117*0c1b95beSRichard Lowe 	.t_name = (const char *(*)())mdb_tgt_null,
118*0c1b95beSRichard Lowe 	.t_isa = (const char *(*)())mdb_conf_isa,
119*0c1b95beSRichard Lowe 	.t_platform = (const char *(*)())mdb_conf_platform,
120*0c1b95beSRichard Lowe 	.t_uname = (int (*)())(uintptr_t)mdb_tgt_notsup,
121*0c1b95beSRichard Lowe 	.t_dmodel = (int (*)())(uintptr_t)mdb_tgt_notsup,
122*0c1b95beSRichard Lowe 	.t_aread = (ssize_t (*)())mdb_tgt_notsup,
123*0c1b95beSRichard Lowe 	.t_awrite = (ssize_t (*)())mdb_tgt_notsup,
124*0c1b95beSRichard Lowe 	.t_vread = value_read,
125*0c1b95beSRichard Lowe 	.t_vwrite = value_write,
126*0c1b95beSRichard Lowe 	.t_pread = (ssize_t (*)())mdb_tgt_notsup,
127*0c1b95beSRichard Lowe 	.t_pwrite = (ssize_t (*)())mdb_tgt_notsup,
128*0c1b95beSRichard Lowe 	.t_fread = value_read,
129*0c1b95beSRichard Lowe 	.t_fwrite = value_write,
130*0c1b95beSRichard Lowe 	.t_ioread = value_read,
131*0c1b95beSRichard Lowe 	.t_iowrite = value_write,
132*0c1b95beSRichard Lowe 	.t_vtop = (int (*)())(uintptr_t)mdb_tgt_notsup,
133*0c1b95beSRichard Lowe 	.t_lookup_by_name = (int (*)())(uintptr_t)mdb_tgt_notsup,
134*0c1b95beSRichard Lowe 	.t_lookup_by_addr = (int (*)())(uintptr_t)mdb_tgt_notsup,
135*0c1b95beSRichard Lowe 	.t_symbol_iter = (int (*)())(uintptr_t)mdb_tgt_notsup,
136*0c1b95beSRichard Lowe 	.t_mapping_iter = (int (*)())(uintptr_t)mdb_tgt_notsup,
137*0c1b95beSRichard Lowe 	.t_object_iter = (int (*)())(uintptr_t)mdb_tgt_notsup,
138*0c1b95beSRichard Lowe 	.t_addr_to_map = (const mdb_map_t *(*)())mdb_tgt_null,
139*0c1b95beSRichard Lowe 	.t_name_to_map = (const mdb_map_t *(*)())mdb_tgt_null,
140*0c1b95beSRichard Lowe 	.t_addr_to_ctf = (struct ctf_file *(*)())mdb_tgt_null,
141*0c1b95beSRichard Lowe 	.t_name_to_ctf = (struct ctf_file *(*)())mdb_tgt_null,
142*0c1b95beSRichard Lowe 	.t_status = (int (*)())(uintptr_t)mdb_tgt_notsup,
143*0c1b95beSRichard Lowe 	.t_run = (int (*)())(uintptr_t)mdb_tgt_notsup,
144*0c1b95beSRichard Lowe 	.t_step = (int (*)())(uintptr_t)mdb_tgt_notsup,
145*0c1b95beSRichard Lowe 	.t_step_out = (int (*)())(uintptr_t)mdb_tgt_notsup,
146*0c1b95beSRichard Lowe 	.t_next = (int (*)())(uintptr_t)mdb_tgt_notsup,
147*0c1b95beSRichard Lowe 	.t_cont = (int (*)())(uintptr_t)mdb_tgt_notsup,
148*0c1b95beSRichard Lowe 	.t_signal = (int (*)())(uintptr_t)mdb_tgt_notsup,
149*0c1b95beSRichard Lowe 	.t_add_vbrkpt = (int (*)())(uintptr_t)mdb_tgt_null,
150*0c1b95beSRichard Lowe 	.t_add_sbrkpt = (int (*)())(uintptr_t)mdb_tgt_null,
151*0c1b95beSRichard Lowe 	.t_add_pwapt = (int (*)())(uintptr_t)mdb_tgt_null,
152*0c1b95beSRichard Lowe 	.t_add_vwapt = (int (*)())(uintptr_t)mdb_tgt_null,
153*0c1b95beSRichard Lowe 	.t_add_iowapt = (int (*)())(uintptr_t)mdb_tgt_null,
154*0c1b95beSRichard Lowe 	.t_add_sysenter = (int (*)())(uintptr_t)mdb_tgt_null,
155*0c1b95beSRichard Lowe 	.t_add_sysexit = (int (*)())(uintptr_t)mdb_tgt_null,
156*0c1b95beSRichard Lowe 	.t_add_signal = (int (*)())(uintptr_t)mdb_tgt_null,
157*0c1b95beSRichard Lowe 	.t_add_fault = (int (*)())(uintptr_t)mdb_tgt_null,
158*0c1b95beSRichard Lowe 	.t_getareg = (int (*)())(uintptr_t)mdb_tgt_notsup,
159*0c1b95beSRichard Lowe 	.t_putareg = (int (*)())(uintptr_t)mdb_tgt_notsup,
160*0c1b95beSRichard Lowe 	.t_stack_iter = (int (*)())(uintptr_t)mdb_tgt_nop,
161*0c1b95beSRichard Lowe 	.t_auxv = (int (*)())(uintptr_t)mdb_tgt_notsup,
162*0c1b95beSRichard Lowe 	.t_thread_name = (int (*)())(uintptr_t)mdb_tgt_notsup,
1637c478bd9Sstevel@tonic-gate };
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate int
mdb_value_tgt_create(mdb_tgt_t * t,int argc,const char * argv[])1667c478bd9Sstevel@tonic-gate mdb_value_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	mdb_value_data_t *data;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (argc < 1 || argv[0] == NULL)
1717c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
1727c478bd9Sstevel@tonic-gate 	if (argc == 2 && argv[1] == NULL)
1737c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
1747c478bd9Sstevel@tonic-gate 	if (argc > 2)
1757c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	t->t_ops = &value_ops;
1787c478bd9Sstevel@tonic-gate 	data = mdb_zalloc(sizeof (mdb_value_data_t), UM_SLEEP);
1797c478bd9Sstevel@tonic-gate 	t->t_data = data;
1807c478bd9Sstevel@tonic-gate 	data->mvd_data = *((uintmax_t *)(void *)argv[0]);
1817c478bd9Sstevel@tonic-gate 	if (argc == 2)
1827c478bd9Sstevel@tonic-gate 		data->mvd_typesize = *((size_t *)(void *)argv[1]);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	return (0);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate void
mdb_value_tgt_destroy(mdb_tgt_t * t)1887c478bd9Sstevel@tonic-gate mdb_value_tgt_destroy(mdb_tgt_t *t)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	mdb_free(t->t_data, sizeof (mdb_value_data_t));
1917c478bd9Sstevel@tonic-gate }
192