Home | History | Annotate | Download | only in common
      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 }
    328