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