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 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #include <stdlib.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <msg.h>
  32 #include <_elfdump.h>
  33 #include <struct_layout.h>
  34 #include <conv.h>
  35 
  36 
  37 /*
  38  * Functions for extracting and formatting numeric values from
  39  * structure data.
  40  */
  41 
  42 
  43 
  44 
  45 /*
  46  * Extract the integral field into the value union given and
  47  * perform any necessary byte swapping to make the result readable
  48  * on the elfdump host.
  49  */
  50 void
  51 sl_extract_num_field(const char *data, int do_swap, const sl_field_t *fdesc,
  52     sl_data_t *field_data)
  53 {
  54         /* Copy the value bytes into our union */
  55         (void) memcpy(field_data, data + fdesc->slf_offset,
  56             fdesc->slf_eltlen);
  57 
  58         /* Do byte swapping as necessary */
  59         if (do_swap) {
  60                 switch (fdesc->slf_eltlen) {
  61                 case 2:
  62                         field_data->sld_ui16 = BSWAP_HALF(field_data->sld_ui16);
  63                         break;
  64 
  65                 case 4:
  66                         field_data->sld_ui32 = BSWAP_WORD(field_data->sld_ui32);
  67                         break;
  68 
  69                 case 8:
  70                         field_data->sld_ui64 =
  71                             BSWAP_LWORD(field_data->sld_ui64);
  72                         break;
  73                 }
  74         }
  75 }
  76 
  77 /*
  78  * Extract the given integer field, and return its value, cast
  79  * to Word. Note that this operation must not be used on values
  80  * that can be negative, or larger than 32-bits, as information
  81  * can be lost.
  82  */
  83 Word
  84 sl_extract_as_word(const char *data, int do_swap, const sl_field_t *fdesc)
  85 {
  86         sl_data_t       v;
  87 
  88         /* Extract the value from the raw data */
  89         sl_extract_num_field(data, do_swap, fdesc, &v);
  90 
  91         if (fdesc->slf_sign) {
  92                 switch (fdesc->slf_eltlen) {
  93                         case 1:
  94                                 return ((Word) v.sld_i8);
  95                         case 2:
  96                                 return ((Word) v.sld_i16);
  97                         case 4:
  98                                 return ((Word) v.sld_i32);
  99                         case 8:
 100                                 return ((Word) v.sld_i64);
 101                 }
 102         } else {
 103                 switch (fdesc->slf_eltlen) {
 104                         case 1:
 105                                 return ((Word) v.sld_ui8);
 106                         case 2:
 107                                 return ((Word) v.sld_ui16);
 108                         case 4:
 109                                 return ((Word) v.sld_ui32);
 110                         case 8:
 111                                 return ((Word) v.sld_ui64);
 112                 }
 113         }
 114 
 115         /* This should not be reached */
 116         assert(0);
 117         return (0);
 118 }
 119 
 120 
 121 /*
 122  * Extract the given integer field, and return its value, cast
 123  * to Word. Note that this operation must not be used on values
 124  * that can be negative, as information can be lost.
 125  */
 126 Lword
 127 sl_extract_as_lword(const char *data, int do_swap, const sl_field_t *fdesc)
 128 {
 129         sl_data_t       v;
 130 
 131         /* Extract the value from the raw data */
 132         sl_extract_num_field(data, do_swap, fdesc, &v);
 133 
 134         if (fdesc->slf_sign) {
 135                 switch (fdesc->slf_eltlen) {
 136                         case 1:
 137                                 return ((Lword) v.sld_i8);
 138                         case 2:
 139                                 return ((Lword) v.sld_i16);
 140                         case 4:
 141                                 return ((Lword) v.sld_i32);
 142                         case 8:
 143                                 return ((Lword) v.sld_i64);
 144                 }
 145         } else {
 146                 switch (fdesc->slf_eltlen) {
 147                         case 1:
 148                                 return ((Lword) v.sld_ui8);
 149                         case 2:
 150                                 return ((Lword) v.sld_ui16);
 151                         case 4:
 152                                 return ((Lword) v.sld_ui32);
 153                         case 8:
 154                                 return ((Lword) v.sld_ui64);
 155                 }
 156         }
 157 
 158         /* This should not be reached */
 159         assert(0);
 160         return (0);
 161 }
 162 
 163 
 164 /*
 165  * Extract the given integer field, and return its value, cast
 166  * to int32_t. Note that this operation must not be used on unsigned
 167  * values larger than 31-bits, or on signed values larger than 32-bits,
 168  * as information can be lost.
 169  */
 170 Sword
 171 sl_extract_as_sword(const char *data, int do_swap, const sl_field_t *fdesc)
 172 {
 173         sl_data_t       v;
 174 
 175         /* Extract the value from the raw data */
 176         sl_extract_num_field(data, do_swap, fdesc, &v);
 177 
 178         if (fdesc->slf_sign) {
 179                 switch (fdesc->slf_eltlen) {
 180                         case 1:
 181                                 return ((Sword)v.sld_i8);
 182                         case 2:
 183                                 return ((Sword)v.sld_i16);
 184                         case 4:
 185                                 return ((Sword)v.sld_i32);
 186                         case 8:
 187                                 return ((Sword)v.sld_i64);
 188                 }
 189         } else {
 190                 switch (fdesc->slf_eltlen) {
 191                         case 1:
 192                                 return ((Sword)v.sld_ui8);
 193                         case 2:
 194                                 return ((Sword)v.sld_ui16);
 195                         case 4:
 196                                 return ((Sword)v.sld_ui32);
 197                         case 8:
 198                                 return ((Sword)v.sld_ui64);
 199                 }
 200         }
 201 
 202         /* This should not be reached */
 203         assert(0);
 204         return (0);
 205 }
 206 
 207 
 208 /*
 209  * Extract the integral field and format it into the supplied buffer.
 210  */
 211 const char *
 212 sl_fmt_num(const char *data, int do_swap, const sl_field_t *fdesc,
 213     sl_fmt_num_t fmt_type, sl_fmtbuf_t buf)
 214 {
 215         /*
 216          * These static arrays are indexed by [fdesc->slf_sign][fmt_type]
 217          * to get a format string to use for the specified combination.
 218          */
 219         static const char *fmt_i8[2][3] = {
 220                 {
 221                         MSG_ORIG(MSG_CNOTE_FMT_U),
 222                         MSG_ORIG(MSG_CNOTE_FMT_X),
 223                         MSG_ORIG(MSG_CNOTE_FMT_Z2X)
 224                 },
 225                 {
 226                         MSG_ORIG(MSG_CNOTE_FMT_D),
 227                         MSG_ORIG(MSG_CNOTE_FMT_X),
 228                         MSG_ORIG(MSG_CNOTE_FMT_Z2X)
 229                 }
 230         };
 231         static const char *fmt_i16[2][3] = {
 232                 {
 233                         MSG_ORIG(MSG_CNOTE_FMT_U),
 234                         MSG_ORIG(MSG_CNOTE_FMT_X),
 235                         MSG_ORIG(MSG_CNOTE_FMT_Z4X)
 236                 },
 237                 {
 238                         MSG_ORIG(MSG_CNOTE_FMT_D),
 239                         MSG_ORIG(MSG_CNOTE_FMT_X),
 240                         MSG_ORIG(MSG_CNOTE_FMT_Z4X)
 241                 }
 242         };
 243         static const char *fmt_i32[2][3] = {
 244                 {
 245                         MSG_ORIG(MSG_CNOTE_FMT_U),
 246                         MSG_ORIG(MSG_CNOTE_FMT_X),
 247                         MSG_ORIG(MSG_CNOTE_FMT_Z8X)
 248                 },
 249                 {
 250                         MSG_ORIG(MSG_CNOTE_FMT_D),
 251                         MSG_ORIG(MSG_CNOTE_FMT_X),
 252                         MSG_ORIG(MSG_CNOTE_FMT_Z8X)
 253                 }
 254         };
 255         static const char *fmt_i64[2][3] = {
 256                 {
 257                         MSG_ORIG(MSG_CNOTE_FMT_LLU),
 258                         MSG_ORIG(MSG_CNOTE_FMT_LLX),
 259                         MSG_ORIG(MSG_CNOTE_FMT_Z16LLX)
 260                 },
 261                 {
 262                         MSG_ORIG(MSG_CNOTE_FMT_LLD),
 263                         MSG_ORIG(MSG_CNOTE_FMT_LLX),
 264                         MSG_ORIG(MSG_CNOTE_FMT_Z16LLX)
 265                 }
 266         };
 267 
 268         sl_data_t       v;
 269 
 270         /* Extract the value from the raw data */
 271         sl_extract_num_field(data, do_swap, fdesc, &v);
 272 
 273         /*
 274          * Format into the buffer. Note that we depend on the signed
 275          * and unsigned versions of each width being equivalent as long
 276          * as the format specifies the proper formatting.
 277          */
 278         switch (fdesc->slf_eltlen) {
 279         case 1:
 280                 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
 281                     fmt_i8[fdesc->slf_sign][fmt_type], (uint32_t)v.sld_ui8);
 282                 break;
 283 
 284         case 2:
 285                 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
 286                     fmt_i16[fdesc->slf_sign][fmt_type], (uint32_t)v.sld_ui16);
 287                 break;
 288 
 289         case 4:
 290                 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
 291                     fmt_i32[fdesc->slf_sign][fmt_type], v.sld_ui32);
 292                 break;
 293 
 294         case 8:
 295                 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
 296                     fmt_i64[fdesc->slf_sign][fmt_type], v.sld_ui64);
 297                 break;
 298         }
 299 
 300         return (buf);
 301 }
 302 
 303 /*
 304  * Return structure layout definition for the given machine type,
 305  * or NULL if the specified machine is not supported.
 306  */
 307 const sl_arch_layout_t  *
 308 sl_mach(Half mach)
 309 {
 310         switch (mach) {
 311         case EM_386:
 312                 return (struct_layout_i386());
 313 
 314         case EM_AMD64:
 315                 return (struct_layout_amd64());
 316 
 317         case EM_SPARC:
 318         case EM_SPARC32PLUS:
 319                 return (struct_layout_sparc());
 320 
 321         case EM_SPARCV9:
 322                 return (struct_layout_sparcv9());
 323         }
 324 
 325         /* Unsupported architecture */
 326         return (NULL);
 327 }