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 }