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 }