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 /* 28 * String conversion routines for ELF header attributes. 29 */ 30 #include <stdio.h> 31 #include <string.h> 32 #include "_conv.h" 33 #include "elf_msg.h" 34 #include <sys/elf_SPARC.h> 35 36 37 38 /* Instantiate a local copy of conv_map2str() from _conv.h */ 39 DEFINE_conv_map2str 40 41 42 43 const char * 44 conv_ehdr_class(uchar_t class, Conv_fmt_flags_t fmt_flags, 45 Conv_inv_buf_t *inv_buf) 46 { 47 static const Msg classes[] = { 48 MSG_ELFCLASSNONE, MSG_ELFCLASS32, MSG_ELFCLASS64 49 }; 50 static const Msg classes_alt[] = { 51 MSG_ELFCLASSNONE_ALT, MSG_ELFCLASS32_ALT, MSG_ELFCLASS64_ALT 52 }; 53 54 /* Use alternative strings? */ 55 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 56 case CONV_FMT_ALT_DUMP: 57 case CONV_FMT_ALT_FILE: 58 return (conv_map2str(inv_buf, class, fmt_flags, 59 ARRAY_NELTS(classes_alt), classes_alt)); 60 } 61 62 /* Use default strings */ 63 return (conv_map2str(inv_buf, class, fmt_flags, 64 ARRAY_NELTS(classes), classes)); 65 } 66 67 const char * 68 conv_ehdr_data(uchar_t data, Conv_fmt_flags_t fmt_flags, 69 Conv_inv_buf_t *inv_buf) 70 { 71 static const Msg datas[] = { 72 MSG_ELFDATANONE, MSG_ELFDATA2LSB, MSG_ELFDATA2MSB 73 }; 74 static const Msg datas_dump[] = { 75 MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT1, MSG_ELFDATA2MSB_ALT1 76 }; 77 static const Msg datas_file[] = { 78 MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT2, MSG_ELFDATA2MSB_ALT2 79 }; 80 81 /* Use alternative strings? */ 82 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 83 case CONV_FMT_ALT_DUMP: 84 return (conv_map2str(inv_buf, data, fmt_flags, 85 ARRAY_NELTS(datas_dump), datas_dump)); 86 case CONV_FMT_ALT_FILE: 87 return (conv_map2str(inv_buf, data, fmt_flags, 88 ARRAY_NELTS(datas_file), datas_file)); 89 } 90 91 /* Use default strings */ 92 return (conv_map2str(inv_buf, data, fmt_flags, 93 ARRAY_NELTS(datas), datas)); 94 } 95 96 static const Msg machines[EM_NUM] = { 97 MSG_EM_NONE, MSG_EM_M32, MSG_EM_SPARC, 98 MSG_EM_386, MSG_EM_68K, MSG_EM_88K, 99 MSG_EM_486, MSG_EM_860, MSG_EM_MIPS, 100 MSG_EM_S370, MSG_EM_MIPS_RS3_LE, MSG_EM_RS6000, 101 MSG_EM_UNKNOWN12, MSG_EM_UNKNOWN13, MSG_EM_UNKNOWN14, 102 MSG_EM_PA_RISC, MSG_EM_nCUBE, MSG_EM_VPP500, 103 MSG_EM_SPARC32PLUS, MSG_EM_960, MSG_EM_PPC, 104 MSG_EM_PPC64, MSG_EM_S390, MSG_EM_UNKNOWN23, 105 MSG_EM_UNKNOWN24, MSG_EM_UNKNOWN25, MSG_EM_UNKNOWN26, 106 MSG_EM_UNKNOWN27, MSG_EM_UNKNOWN28, MSG_EM_UNKNOWN29, 107 MSG_EM_UNKNOWN30, MSG_EM_UNKNOWN31, MSG_EM_UNKNOWN32, 108 MSG_EM_UNKNOWN33, MSG_EM_UNKNOWN34, MSG_EM_UNKNOWN35, 109 MSG_EM_V800, MSG_EM_FR20, MSG_EM_RH32, 110 MSG_EM_RCE, MSG_EM_ARM, MSG_EM_ALPHA, 111 MSG_EM_SH, MSG_EM_SPARCV9, MSG_EM_TRICORE, 112 MSG_EM_ARC, MSG_EM_H8_300, MSG_EM_H8_300H, 113 MSG_EM_H8S, MSG_EM_H8_500, MSG_EM_IA_64, 114 MSG_EM_MIPS_X, MSG_EM_COLDFIRE, MSG_EM_68HC12, 115 MSG_EM_MMA, MSG_EM_PCP, MSG_EM_NCPU, 116 MSG_EM_NDR1, MSG_EM_STARCORE, MSG_EM_ME16, 117 MSG_EM_ST100, MSG_EM_TINYJ, MSG_EM_AMD64, 118 MSG_EM_PDSP, MSG_EM_UNKNOWN64, MSG_EM_UNKNOWN65, 119 MSG_EM_FX66, MSG_EM_ST9PLUS, MSG_EM_ST7, 120 MSG_EM_68HC16, MSG_EM_68HC11, MSG_EM_68HC08, 121 MSG_EM_68HC05, MSG_EM_SVX, MSG_EM_ST19, 122 MSG_EM_VAX, MSG_EM_CRIS, MSG_EM_JAVELIN, 123 MSG_EM_FIREPATH, MSG_EM_ZSP, MSG_EM_MMIX, 124 MSG_EM_HUANY, MSG_EM_PRISM, MSG_EM_AVR, 125 MSG_EM_FR30, MSG_EM_D10V, MSG_EM_D30V, 126 MSG_EM_V850, MSG_EM_M32R, MSG_EM_MN10300, 127 MSG_EM_MN10200, MSG_EM_PJ, MSG_EM_OPENRISC, 128 MSG_EM_ARC_A5, MSG_EM_XTENSA 129 }; 130 static const Msg machines_alt[EM_NUM] = { 131 MSG_EM_NONE_ALT, MSG_EM_M32_ALT, MSG_EM_SPARC_ALT, 132 MSG_EM_386_ALT, MSG_EM_68K_ALT, MSG_EM_88K_ALT, 133 MSG_EM_486_ALT, MSG_EM_860_ALT, MSG_EM_MIPS_ALT, 134 MSG_EM_S370, MSG_EM_MIPS_RS3_LE_ALT, MSG_EM_RS6000_ALT, 135 MSG_EM_UNKNOWN12, MSG_EM_UNKNOWN13, MSG_EM_UNKNOWN14, 136 MSG_EM_PA_RISC_ALT, MSG_EM_nCUBE_ALT, MSG_EM_VPP500_ALT, 137 MSG_EM_SPARC32PLUS_ALT, MSG_EM_960, MSG_EM_PPC_ALT, 138 MSG_EM_PPC64_ALT, MSG_EM_S390, MSG_EM_UNKNOWN23, 139 MSG_EM_UNKNOWN24, MSG_EM_UNKNOWN25, MSG_EM_UNKNOWN26, 140 MSG_EM_UNKNOWN27, MSG_EM_UNKNOWN28, MSG_EM_UNKNOWN29, 141 MSG_EM_UNKNOWN30, MSG_EM_UNKNOWN31, MSG_EM_UNKNOWN32, 142 MSG_EM_UNKNOWN33, MSG_EM_UNKNOWN34, MSG_EM_UNKNOWN35, 143 MSG_EM_V800, MSG_EM_FR20, MSG_EM_RH32, 144 MSG_EM_RCE, MSG_EM_ARM_ALT, MSG_EM_ALPHA_ALT, 145 MSG_EM_SH, MSG_EM_SPARCV9_ALT, MSG_EM_TRICORE, 146 MSG_EM_ARC, MSG_EM_H8_300, MSG_EM_H8_300H, 147 MSG_EM_H8S, MSG_EM_H8_500, MSG_EM_IA_64_ALT, 148 MSG_EM_MIPS_X, MSG_EM_COLDFIRE, MSG_EM_68HC12, 149 MSG_EM_MMA, MSG_EM_PCP, MSG_EM_NCPU, 150 MSG_EM_NDR1, MSG_EM_STARCORE, MSG_EM_ME16, 151 MSG_EM_ST100, MSG_EM_TINYJ, MSG_EM_AMD64_ALT, 152 MSG_EM_PDSP, MSG_EM_UNKNOWN64, MSG_EM_UNKNOWN65, 153 MSG_EM_FX66, MSG_EM_ST9PLUS, MSG_EM_ST7, 154 MSG_EM_68HC16, MSG_EM_68HC11, MSG_EM_68HC08, 155 MSG_EM_68HC05, MSG_EM_SVX, MSG_EM_ST19, 156 MSG_EM_VAX_ALT, MSG_EM_CRIS, MSG_EM_JAVELIN, 157 MSG_EM_FIREPATH, MSG_EM_ZSP, MSG_EM_MMIX, 158 MSG_EM_HUANY, MSG_EM_PRISM, MSG_EM_AVR, 159 MSG_EM_FR30, MSG_EM_D10V, MSG_EM_D30V, 160 MSG_EM_V850, MSG_EM_M32R, MSG_EM_MN10300, 161 MSG_EM_MN10200, MSG_EM_PJ, MSG_EM_OPENRISC, 162 MSG_EM_ARC_A5, MSG_EM_XTENSA 163 }; 164 #if (EM_NUM != (EM_XTENSA + 1)) 165 #error "EM_NUM has grown" 166 #endif 167 168 const char * 169 conv_ehdr_mach(Half machine, Conv_fmt_flags_t fmt_flags, 170 Conv_inv_buf_t *inv_buf) 171 { 172 /* Use alternative strings? */ 173 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 174 case CONV_FMT_ALT_DUMP: 175 case CONV_FMT_ALT_FILE: 176 return (conv_map2str(inv_buf, machine, fmt_flags, 177 ARRAY_NELTS(machines_alt), machines_alt)); 178 } 179 180 /* Use default strings */ 181 return (conv_map2str(inv_buf, machine, fmt_flags, 182 ARRAY_NELTS(machines), machines)); 183 } 184 185 186 const char * 187 conv_ehdr_type(Half etype, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf) 188 { 189 static const Msg etypes[] = { 190 MSG_ET_NONE, MSG_ET_REL, MSG_ET_EXEC, 191 MSG_ET_DYN, MSG_ET_CORE 192 }; 193 static const Msg etypes_alt[] = { 194 MSG_ET_NONE_ALT, MSG_ET_REL_ALT, MSG_ET_EXEC_ALT, 195 MSG_ET_DYN_ALT, MSG_ET_CORE_ALT 196 }; 197 198 if (etype == ET_SUNWPSEUDO) { 199 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 200 case CONV_FMT_ALT_DUMP: 201 case CONV_FMT_ALT_FILE: 202 return (MSG_ORIG(MSG_ET_SUNWPSEUDO_ALT)); 203 default: 204 return (MSG_ORIG(MSG_ET_SUNWPSEUDO)); 205 } 206 } 207 208 /* Use alternative strings? */ 209 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 210 case CONV_FMT_ALT_DUMP: 211 case CONV_FMT_ALT_FILE: 212 return (conv_map2str(inv_buf, etype, fmt_flags, 213 ARRAY_NELTS(etypes_alt), etypes_alt)); 214 } 215 216 /* Use default strings */ 217 return (conv_map2str(inv_buf, etype, fmt_flags, 218 ARRAY_NELTS(etypes), etypes)); 219 220 } 221 222 const char * 223 conv_ehdr_vers(Word version, Conv_fmt_flags_t fmt_flags, 224 Conv_inv_buf_t *inv_buf) 225 { 226 static const Msg versions[] = { 227 MSG_EV_NONE, MSG_EV_CURRENT 228 }; 229 static const Msg versions_alt[] = { 230 MSG_EV_NONE_ALT, MSG_EV_CURRENT_ALT 231 }; 232 233 /* Use alternative strings? */ 234 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 235 case CONV_FMT_ALT_DUMP: 236 case CONV_FMT_ALT_FILE: 237 return (conv_map2str(inv_buf, version, fmt_flags, 238 ARRAY_NELTS(versions_alt), versions_alt)); 239 } 240 241 /* Use default strings */ 242 return (conv_map2str(inv_buf, version, fmt_flags, 243 ARRAY_NELTS(versions), versions)); 244 } 245 246 #define EFLAGSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 247 MSG_EF_SPARCV9_TSO_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 248 MSG_EF_SPARC_SUN_US1_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 249 MSG_EF_SPARC_HAL_R1_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 250 MSG_EF_SPARC_SUN_US3_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 251 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 252 253 /* 254 * Ensure that Conv_ehdr_flags_buf_t is large enough: 255 * 256 * EFLAGSZ is the real minimum size of the buffer required by conv_ehdr_flags(). 257 * However, Conv_ehdr_flags_buf_t uses CONV_EHDR_FLAG_BUFSIZE to set the 258 * buffer size. We do things this way because the definition of EFLAGSZ uses 259 * information that is not available in the environment of other programs 260 * that include the conv.h header file. 261 */ 262 #if (CONV_EHDR_FLAGS_BUFSIZE != EFLAGSZ) && !defined(__lint) 263 #define REPORT_BUFSIZE EFLAGSZ 264 #include "report_bufsize.h" 265 #error "CONV_EHDR_FLAGS_BUFSIZE does not match EFLAGSZ" 266 #endif 267 268 /* 269 * Make a string representation of the e_flags field. 270 */ 271 const char * 272 conv_ehdr_flags(Half mach, Word flags, Conv_fmt_flags_t fmt_flags, 273 Conv_ehdr_flags_buf_t *flags_buf) 274 { 275 static Val_desc vda[] = { 276 { EF_SPARC_32PLUS, MSG_ORIG(MSG_EF_SPARC_32PLUS) }, 277 { EF_SPARC_SUN_US1, MSG_ORIG(MSG_EF_SPARC_SUN_US1) }, 278 { EF_SPARC_HAL_R1, MSG_ORIG(MSG_EF_SPARC_HAL_R1) }, 279 { EF_SPARC_SUN_US3, MSG_ORIG(MSG_EF_SPARC_SUN_US3) }, 280 { 0, 0 } 281 }; 282 static const Msg mm_flags[] = { 283 MSG_EF_SPARCV9_TSO, MSG_EF_SPARCV9_PSO, 284 MSG_EF_SPARCV9_RMO 285 }; 286 static const char *leading_str_arr[2]; 287 static CONV_EXPN_FIELD_ARG conv_arg = { 288 NULL, sizeof (flags_buf->buf), vda, leading_str_arr }; 289 290 const char **lstr = leading_str_arr; 291 292 conv_arg.buf = flags_buf->buf; 293 294 /* 295 * Non-SPARC architectures presently provide no known flags. 296 */ 297 if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) || 298 (mach == EM_SPARC32PLUS)) && flags)) { 299 /* 300 * Valid vendor extension bits for SPARCV9. These must be 301 * updated along with elf_SPARC.h. 302 */ 303 304 conv_arg.oflags = conv_arg.rflags = flags; 305 if ((mach == EM_SPARCV9) && (flags <= EF_SPARCV9_RMO)) { 306 *lstr++ = MSG_ORIG(mm_flags[flags & EF_SPARCV9_MM]); 307 conv_arg.rflags &= ~EF_SPARCV9_MM; 308 } 309 *lstr = NULL; 310 311 (void) conv_expn_field(&conv_arg, fmt_flags); 312 313 return (conv_arg.buf); 314 } 315 316 return (conv_invalid_val(&flags_buf->inv_buf, flags, CONV_FMT_DECIMAL)); 317 } 318 319 /* 320 * Make a string representation of the e_ident[EI_OSABI] field. 321 */ 322 const char * 323 conv_ehdr_osabi(uchar_t osabi, Conv_fmt_flags_t fmt_flags, 324 Conv_inv_buf_t *inv_buf) 325 { 326 static const Msg osabi_arr[] = { 327 MSG_OSABI_NONE, MSG_OSABI_HPUX, 328 MSG_OSABI_NETBSD, MSG_OSABI_LINUX, 329 MSG_OSABI_UNKNOWN4, MSG_OSABI_UNKNOWN5, 330 MSG_OSABI_SOLARIS, MSG_OSABI_AIX, 331 MSG_OSABI_IRIX, MSG_OSABI_FREEBSD, 332 MSG_OSABI_TRU64, MSG_OSABI_MODESTO, 333 MSG_OSABI_OPENBSD, MSG_OSABI_OPENVMS, 334 MSG_OSABI_NSK, MSG_OSABI_AROS 335 }; 336 static const Msg osabi_arr_alt[] = { 337 MSG_OSABI_NONE_ALT, MSG_OSABI_HPUX_ALT, 338 MSG_OSABI_NETBSD_ALT, MSG_OSABI_LINUX_ALT, 339 MSG_OSABI_UNKNOWN4, MSG_OSABI_UNKNOWN5, 340 MSG_OSABI_SOLARIS_ALT, MSG_OSABI_AIX_ALT, 341 MSG_OSABI_IRIX_ALT, MSG_OSABI_FREEBSD_ALT, 342 MSG_OSABI_TRU64_ALT, MSG_OSABI_MODESTO_ALT, 343 MSG_OSABI_OPENBSD_ALT, MSG_OSABI_OPENVMS_ALT, 344 MSG_OSABI_NSK_ALT, MSG_OSABI_AROS_ALT 345 }; 346 347 const char *str; 348 349 switch (osabi) { 350 case ELFOSABI_ARM: 351 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 352 case CONV_FMT_ALT_DUMP: 353 case CONV_FMT_ALT_FILE: 354 str = MSG_ORIG(MSG_OSABI_ARM_ALT); 355 break; 356 default: 357 str = MSG_ORIG(MSG_OSABI_ARM); 358 } 359 break; 360 361 case ELFOSABI_STANDALONE: 362 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 363 case CONV_FMT_ALT_DUMP: 364 case CONV_FMT_ALT_FILE: 365 str = MSG_ORIG(MSG_OSABI_STANDALONE_ALT); 366 break; 367 default: 368 str = MSG_ORIG(MSG_OSABI_STANDALONE); 369 } 370 break; 371 372 default: 373 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 374 case CONV_FMT_ALT_DUMP: 375 case CONV_FMT_ALT_FILE: 376 str = conv_map2str(inv_buf, osabi, fmt_flags, 377 ARRAY_NELTS(osabi_arr_alt), osabi_arr_alt); 378 break; 379 default: 380 str = conv_map2str(inv_buf, osabi, fmt_flags, 381 ARRAY_NELTS(osabi_arr), osabi_arr); 382 } 383 break; 384 } 385 386 return (str); 387 } 388 389 /* 390 * A generic means of returning additional information for a rejected file in 391 * terms of a string. 392 */ 393 const char * 394 conv_reject_desc(Rej_desc * rej, Conv_reject_desc_buf_t *reject_desc_buf, 395 Half mach) 396 { 397 ushort_t type = rej->rej_type; 398 uint_t info = rej->rej_info; 399 400 switch (type) { 401 case SGS_REJ_MACH: 402 return (conv_ehdr_mach((Half)info, 0, 403 &reject_desc_buf->inv_buf)); 404 case SGS_REJ_CLASS: 405 return (conv_ehdr_class((uchar_t)info, 0, 406 &reject_desc_buf->inv_buf)); 407 case SGS_REJ_DATA: 408 return (conv_ehdr_data((uchar_t)info, 0, 409 &reject_desc_buf->inv_buf)); 410 case SGS_REJ_TYPE: 411 return (conv_ehdr_type((Half)info, 0, 412 &reject_desc_buf->inv_buf)); 413 case SGS_REJ_BADFLAG: 414 case SGS_REJ_MISFLAG: 415 case SGS_REJ_HAL: 416 case SGS_REJ_US3: 417 return (conv_ehdr_flags(mach, (Word)info, 0, 418 &reject_desc_buf->flags_buf)); 419 case SGS_REJ_UNKFILE: 420 return ((const char *)0); 421 case SGS_REJ_STR: 422 case SGS_REJ_HWCAP_1: 423 case SGS_REJ_SFCAP_1: 424 if (rej->rej_str) 425 return ((const char *)rej->rej_str); 426 else 427 return (MSG_ORIG(MSG_STR_EMPTY)); 428 default: 429 return (conv_invalid_val(&reject_desc_buf->inv_buf, info, 430 CONV_FMT_DECIMAL)); 431 } 432 } 433