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