Home | History | Annotate | Download | only in mdb
      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 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     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 (*)()) mdb_tgt_notsup,		/* t_setflags */
    111 	(int (*)()) mdb_tgt_notsup,		/* t_setcontext */
    112 	(void (*)()) mdb_tgt_nop,		/* t_activate */
    113 	(void (*)()) mdb_tgt_nop,		/* t_deactivate */
    114 	(void (*)()) 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 (*)()) mdb_tgt_notsup,		/* t_uname */
    120 	(int (*)()) 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 (*)()) mdb_tgt_notsup,		/* t_vtop */
    132 	(int (*)()) mdb_tgt_notsup,		/* t_lookup_by_name */
    133 	(int (*)()) mdb_tgt_notsup,		/* t_lookup_by_addr */
    134 	(int (*)()) mdb_tgt_notsup,		/* t_symbol_iter */
    135 	(int (*)()) mdb_tgt_notsup,		/* t_mapping_iter */
    136 	(int (*)()) 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 (*)()) mdb_tgt_notsup,		/* t_status */
    142 	(int (*)()) mdb_tgt_notsup,		/* t_run */
    143 	(int (*)()) mdb_tgt_notsup,		/* t_step */
    144 	(int (*)()) mdb_tgt_notsup,		/* t_step_out */
    145 	(int (*)()) mdb_tgt_notsup,		/* t_step_branch */
    146 	(int (*)()) mdb_tgt_notsup,		/* t_next */
    147 	(int (*)()) mdb_tgt_notsup,		/* t_cont */
    148 	(int (*)()) mdb_tgt_notsup,		/* t_signal */
    149 	(int (*)()) mdb_tgt_null,		/* t_add_vbrkpt */
    150 	(int (*)()) mdb_tgt_null,		/* t_add_sbrkpt */
    151 	(int (*)()) mdb_tgt_null,		/* t_add_pwapt */
    152 	(int (*)()) mdb_tgt_null,		/* t_add_vwapt */
    153 	(int (*)()) mdb_tgt_null,		/* t_add_iowapt */
    154 	(int (*)()) mdb_tgt_null,		/* t_add_sysenter */
    155 	(int (*)()) mdb_tgt_null,		/* t_add_sysexit */
    156 	(int (*)()) mdb_tgt_null,		/* t_add_signal */
    157 	(int (*)()) mdb_tgt_null,		/* t_add_fault */
    158 	(int (*)()) mdb_tgt_notsup,		/* t_getareg */
    159 	(int (*)()) mdb_tgt_notsup,		/* t_putareg */
    160 	(int (*)()) mdb_tgt_nop,		/* t_stack_iter */
    161 	(int (*)()) mdb_tgt_notsup		/* t_auxv */
    162 };
    163 
    164 int
    165 mdb_value_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
    166 {
    167 	mdb_value_data_t *data;
    168 
    169 	if (argc < 1 || argv[0] == NULL)
    170 		return (set_errno(EINVAL));
    171 	if (argc == 2 && argv[1] == NULL)
    172 		return (set_errno(EINVAL));
    173 	if (argc > 2)
    174 		return (set_errno(EINVAL));
    175 
    176 	t->t_ops = &value_ops;
    177 	data = mdb_zalloc(sizeof (mdb_value_data_t), UM_SLEEP);
    178 	t->t_data = data;
    179 	data->mvd_data = *((uintmax_t *)(void *)argv[0]);
    180 	if (argc == 2)
    181 		data->mvd_typesize = *((size_t *)(void *)argv[1]);
    182 
    183 	return (0);
    184 }
    185 
    186 void
    187 mdb_value_tgt_destroy(mdb_tgt_t *t)
    188 {
    189 	mdb_free(t->t_data, sizeof (mdb_value_data_t));
    190 }
    191