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