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