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 2006 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) 46 { 47 static char string[CONV_INV_STRSIZE]; 48 static const Msg classes[] = { 49 MSG_ELFCLASSNONE, MSG_ELFCLASS32, MSG_ELFCLASS64 50 }; 51 static const Msg classes_alt[] = { 52 MSG_ELFCLASSNONE_ALT, MSG_ELFCLASS32_ALT, MSG_ELFCLASS64_ALT 53 }; 54 55 return (conv_map2str(string, sizeof (string), class, fmt_flags, 56 ARRAY_NELTS(classes), classes, classes_alt, classes_alt)); 57 } 58 59 const char * 60 conv_ehdr_data(uchar_t data, int fmt_flags) 61 { 62 static char string[CONV_INV_STRSIZE]; 63 static const Msg datas[] = { 64 MSG_ELFDATANONE, MSG_ELFDATA2LSB, MSG_ELFDATA2MSB 65 }; 66 static const Msg datas_dump[] = { 67 MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT1, MSG_ELFDATA2MSB_ALT1 68 }; 69 static const Msg datas_file[] = { 70 MSG_ELFDATANONE_ALT, MSG_ELFDATA2LSB_ALT2, MSG_ELFDATA2MSB_ALT2 71 }; 72 73 return (conv_map2str(string, sizeof (string), data, fmt_flags, 74 ARRAY_NELTS(datas), datas, datas_dump, datas_file)); 75 } 76 77 static const Msg machines[EM_NUM] = { 78 MSG_EM_NONE, MSG_EM_M32, MSG_EM_SPARC, 79 MSG_EM_386, MSG_EM_68K, MSG_EM_88K, 80 MSG_EM_486, MSG_EM_860, MSG_EM_MIPS, 81 MSG_EM_UNKNOWN9, MSG_EM_MIPS_RS3_LE, MSG_EM_RS6000, 82 MSG_EM_UNKNOWN12, MSG_EM_UNKNOWN13, MSG_EM_UNKNOWN14, 83 MSG_EM_PA_RISC, MSG_EM_nCUBE, MSG_EM_VPP500, 84 MSG_EM_SPARC32PLUS, MSG_EM_UNKNOWN19, MSG_EM_PPC, 85 MSG_EM_PPC64, MSG_EM_UNKNOWN22, MSG_EM_UNKNOWN23, 86 MSG_EM_UNKNOWN24, MSG_EM_UNKNOWN25, MSG_EM_UNKNOWN26, 87 MSG_EM_UNKNOWN27, MSG_EM_UNKNOWN28, MSG_EM_UNKNOWN29, 88 MSG_EM_UNKNOWN30, MSG_EM_UNKNOWN31, MSG_EM_UNKNOWN32, 89 MSG_EM_UNKNOWN33, MSG_EM_UNKNOWN34, MSG_EM_UNKNOWN35, 90 MSG_EM_Y800, MSG_EM_FR20, MSG_EM_RH32, 91 MSG_EM_RCE, MSG_EM_ARM, MSG_EM_ALPHA, 92 MSG_EM_SH, MSG_EM_SPARCV9, MSG_EM_TRICORE, 93 MSG_EM_ARC, MSG_EM_H8_300, MSG_EM_H8_300H, 94 MSG_EM_H8S, MSG_EM_H8_500, MSG_EM_IA_64, 95 MSG_EM_MIPS_X, MSG_EM_COLDFIRE, MSG_EM_68HC12, 96 MSG_EM_MMA, MSG_EM_PCP, MSG_EM_NCPU, 97 MSG_EM_NDR1, MSG_EM_STARCORE, MSG_EM_ME16, 98 MSG_EM_ST100, MSG_EM_TINYJ, MSG_EM_AMD64, 99 MSG_EM_UNKNOWN63, MSG_EM_UNKNOWN64, MSG_EM_UNKNOWN65, 100 MSG_EM_FX66, MSG_EM_ST9PLUS, MSG_EM_ST7, 101 MSG_EM_68HC16, MSG_EM_68HC11, MSG_EM_68HC08, 102 MSG_EM_68HC05, MSG_EM_SVX, MSG_EM_ST19, 103 MSG_EM_VAX, MSG_EM_CRIS, MSG_EM_JAVELIN, 104 MSG_EM_FIREPATH, MSG_EM_ZSP, MSG_EM_MMIX, 105 MSG_EM_HUANY, MSG_EM_PRISM, MSG_EM_AVR, 106 MSG_EM_FR30, MSG_EM_D10V, MSG_EM_D30V, 107 MSG_EM_V850, MSG_EM_M32R, MSG_EM_MN10300, 108 MSG_EM_MN10200, MSG_EM_PJ, MSG_EM_OPENRISC, 109 MSG_EM_ARC_A5, MSG_EM_XTENSA 110 }; 111 static const Msg machines_alt[EM_NUM] = { 112 MSG_EM_NONE_ALT, MSG_EM_M32_ALT, MSG_EM_SPARC_ALT, 113 MSG_EM_386_ALT, MSG_EM_68K_ALT, MSG_EM_88K_ALT, 114 MSG_EM_486_ALT, MSG_EM_860_ALT, MSG_EM_MIPS_ALT, 115 MSG_EM_UNKNOWN9, MSG_EM_MIPS_RS3_LE_ALT, MSG_EM_RS6000_ALT, 116 MSG_EM_UNKNOWN12, MSG_EM_UNKNOWN13, MSG_EM_UNKNOWN14, 117 MSG_EM_PA_RISC_ALT, MSG_EM_nCUBE_ALT, MSG_EM_VPP500_ALT, 118 MSG_EM_SPARC32PLUS_ALT, MSG_EM_UNKNOWN19, MSG_EM_PPC_ALT, 119 MSG_EM_PPC64_ALT, MSG_EM_UNKNOWN22, MSG_EM_UNKNOWN23, 120 MSG_EM_UNKNOWN24, MSG_EM_UNKNOWN25, MSG_EM_UNKNOWN26, 121 MSG_EM_UNKNOWN27, MSG_EM_UNKNOWN28, MSG_EM_UNKNOWN29, 122 MSG_EM_UNKNOWN30, MSG_EM_UNKNOWN31, MSG_EM_UNKNOWN32, 123 MSG_EM_UNKNOWN33, MSG_EM_UNKNOWN34, MSG_EM_UNKNOWN35, 124 MSG_EM_Y800, MSG_EM_FR20, MSG_EM_RH32, 125 MSG_EM_RCE, MSG_EM_ARM_ALT, MSG_EM_ALPHA_ALT, 126 MSG_EM_SH, MSG_EM_SPARCV9_ALT, MSG_EM_TRICORE, 127 MSG_EM_ARC, MSG_EM_H8_300, MSG_EM_H8_300H, 128 MSG_EM_H8S, MSG_EM_H8_500, MSG_EM_IA_64_ALT, 129 MSG_EM_MIPS_X, MSG_EM_COLDFIRE, MSG_EM_68HC12, 130 MSG_EM_MMA, MSG_EM_PCP, MSG_EM_NCPU, 131 MSG_EM_NDR1, MSG_EM_STARCORE, MSG_EM_ME16, 132 MSG_EM_ST100, MSG_EM_TINYJ, MSG_EM_AMD64_ALT, 133 MSG_EM_UNKNOWN63, MSG_EM_UNKNOWN64, MSG_EM_UNKNOWN65, 134 MSG_EM_FX66, MSG_EM_ST9PLUS, MSG_EM_ST7, 135 MSG_EM_68HC16, MSG_EM_68HC11, MSG_EM_68HC08, 136 MSG_EM_68HC05, MSG_EM_SVX, MSG_EM_ST19, 137 MSG_EM_VAX_ALT, MSG_EM_CRIS, MSG_EM_JAVELIN, 138 MSG_EM_FIREPATH, MSG_EM_ZSP, MSG_EM_MMIX, 139 MSG_EM_HUANY, MSG_EM_PRISM, MSG_EM_AVR, 140 MSG_EM_FR30, MSG_EM_D10V, MSG_EM_D30V, 141 MSG_EM_V850, MSG_EM_M32R, MSG_EM_MN10300, 142 MSG_EM_MN10200, MSG_EM_PJ, MSG_EM_OPENRISC, 143 MSG_EM_ARC_A5, MSG_EM_XTENSA 144 }; 145 #if (EM_NUM != (EM_XTENSA + 1)) 146 #error "EM_NUM has grown" 147 #endif 148 149 const char * 150 conv_ehdr_mach(Half machine, int fmt_flags) 151 { 152 static char string[CONV_INV_STRSIZE]; 153 154 return (conv_map2str(string, sizeof (string), machine, fmt_flags, 155 ARRAY_NELTS(machines), machines, machines_alt, machines_alt)); 156 } 157 158 159 const char * 160 conv_ehdr_type(Half etype, int fmt_flags) 161 { 162 static char string[CONV_INV_STRSIZE]; 163 static const Msg etypes[] = { 164 MSG_ET_NONE, MSG_ET_REL, MSG_ET_EXEC, 165 MSG_ET_DYN, MSG_ET_CORE 166 }; 167 static const Msg etypes_alt[] = { 168 MSG_ET_NONE_ALT, MSG_ET_REL_ALT, MSG_ET_EXEC_ALT, 169 MSG_ET_DYN_ALT, MSG_ET_CORE_ALT 170 }; 171 172 if (etype == ET_SUNWPSEUDO) { 173 return ((fmt_flags & CONV_FMTALTMASK) 174 ? MSG_ORIG(MSG_ET_SUNWPSEUDO_ALT) 175 : MSG_ORIG(MSG_ET_SUNWPSEUDO)); 176 } 177 178 return (conv_map2str(string, sizeof (string), etype, fmt_flags, 179 ARRAY_NELTS(etypes), etypes, etypes_alt, etypes_alt)); 180 181 } 182 183 const char * 184 conv_ehdr_vers(Word version, int fmt_flags) 185 { 186 static char string[CONV_INV_STRSIZE]; 187 static const Msg versions[] = { 188 MSG_EV_NONE, MSG_EV_CURRENT 189 }; 190 static const Msg versions_alt[] = { 191 MSG_EV_NONE_ALT, MSG_EV_CURRENT_ALT 192 }; 193 194 return (conv_map2str(string, sizeof (string), version, fmt_flags, 195 ARRAY_NELTS(versions), versions, versions_alt, versions_alt)); 196 } 197 198 #define EFLAGSZ MSG_GBL_OSQBRKT_SIZE + \ 199 MSG_EF_SPARCV9_TSO_SIZE + \ 200 MSG_EF_SPARC_SUN_US1_SIZE + \ 201 MSG_EF_SPARC_HAL_R1_SIZE + \ 202 MSG_EF_SPARC_SUN_US3_SIZE + \ 203 CONV_INV_STRSIZE + MSG_GBL_CSQBRKT_SIZE 204 205 /* 206 * Make a string representation of the e_flags field. 207 */ 208 const char * 209 conv_ehdr_flags(Half mach, Word flags) 210 { 211 static char string[EFLAGSZ]; 212 static Val_desc vda[] = { 213 { EF_SPARC_32PLUS, MSG_ORIG(MSG_EF_SPARC_32PLUS) }, 214 { EF_SPARC_SUN_US1, MSG_ORIG(MSG_EF_SPARC_SUN_US1) }, 215 { EF_SPARC_HAL_R1, MSG_ORIG(MSG_EF_SPARC_HAL_R1) }, 216 { EF_SPARC_SUN_US3, MSG_ORIG(MSG_EF_SPARC_SUN_US3) }, 217 { 0, 0 } 218 }; 219 static const Msg mm_flags[] = { 220 MSG_EF_SPARCV9_TSO, MSG_EF_SPARCV9_PSO, 221 MSG_EF_SPARCV9_RMO 222 }; 223 Word _flags = flags; 224 225 /* 226 * Non-SPARC architectures presently provide no known flags. 227 */ 228 if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) || 229 (mach == EM_SPARC32PLUS)) && flags)) { 230 /* 231 * Valid vendor extension bits for SPARCV9. These must be 232 * updated along with elf_SPARC.h. 233 */ 234 (void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT)); 235 236 if ((mach == EM_SPARCV9) && (flags <= EF_SPARCV9_RMO)) { 237 if (strlcat(string, 238 MSG_ORIG(mm_flags[flags & EF_SPARCV9_MM]), 239 EFLAGSZ) >= EFLAGSZ) 240 return (conv_invalid_val(string, EFLAGSZ, 241 flags, 0)); 242 _flags &= ~EF_SPARCV9_MM; 243 } 244 245 if (conv_expn_field(string, EFLAGSZ, vda, flags, _flags, 0, 0)) 246 (void) strlcat(string, MSG_ORIG(MSG_GBL_CSQBRKT), 247 EFLAGSZ); 248 249 return (string); 250 } 251 return (conv_invalid_val(string, EFLAGSZ, flags, CONV_FMT_DECIMAL)); 252 } 253 254 /* 255 * A generic means of returning additional information for a rejected file in 256 * terms of a string. 257 */ 258 const char * 259 conv_reject_desc(Rej_desc * rej) 260 { 261 static char string[CONV_INV_STRSIZE]; 262 263 ushort_t type = rej->rej_type; 264 uint_t info = rej->rej_info; 265 266 if (type == SGS_REJ_MACH) 267 /* LINTED */ 268 return (conv_ehdr_mach((Half)info, 0)); 269 else if (type == SGS_REJ_CLASS) 270 /* LINTED */ 271 return (conv_ehdr_class((uchar_t)info, 0)); 272 else if (type == SGS_REJ_DATA) 273 /* LINTED */ 274 return (conv_ehdr_data((uchar_t)info, 0)); 275 else if (type == SGS_REJ_TYPE) 276 /* LINTED */ 277 return (conv_ehdr_type((Half)info, 0)); 278 else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) || 279 (type == SGS_REJ_HAL) || (type == SGS_REJ_US3)) 280 /* 281 * Only called from ld.so.1, thus M_MACH is hardcoded. 282 */ 283 return (conv_ehdr_flags(M_MACH, (Word)info)); 284 else if (type == SGS_REJ_UNKFILE) 285 return ((const char *)0); 286 else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) { 287 if (rej->rej_str) 288 return ((const char *)rej->rej_str); 289 else 290 return (MSG_ORIG(MSG_STR_EMPTY)); 291 } else 292 return (conv_invalid_val(string, CONV_INV_STRSIZE, info, 293 CONV_FMT_DECIMAL)); 294 } 295