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