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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 static const Msg classes[] = { 38 MSG_ELFCLASSNONE, MSG_ELFCLASS32, MSG_ELFCLASS64 39 }; 40 41 const char * 42 conv_eclass_str(uchar_t class) 43 { 44 static char string[STRSIZE] = { '\0' }; 45 46 if (class >= ELFCLASSNUM) 47 return (conv_invalid_str(string, STRSIZE, class, 0)); 48 else 49 return (MSG_ORIG(classes[class])); 50 51 } 52 53 static const Msg datas[] = { 54 MSG_ELFDATANONE, MSG_ELFDATA2LSB, MSG_ELFDATA2MSB 55 }; 56 57 const char * 58 conv_edata_str(uchar_t data) 59 { 60 static char string[STRSIZE] = { '\0' }; 61 62 if (data >= ELFDATANUM) 63 return (conv_invalid_str(string, STRSIZE, data, 0)); 64 else 65 return (MSG_ORIG(datas[data])); 66 67 } 68 69 static const Msg machines[EM_NUM] = { 70 MSG_EM_NONE, 71 MSG_EM_M32, 72 MSG_EM_SPARC, 73 MSG_EM_386, 74 MSG_EM_68K, 75 MSG_EM_88K, 76 MSG_EM_486, 77 MSG_EM_860, 78 MSG_EM_MIPS, 79 MSG_EM_UNKNOWN9, 80 MSG_EM_MIPS_RS3_LE, 81 MSG_EM_RS6000, 82 MSG_EM_UNKNOWN12, 83 MSG_EM_UNKNOWN13, 84 MSG_EM_UNKNOWN14, 85 MSG_EM_PA_RISC, 86 MSG_EM_nCUBE, 87 MSG_EM_VPP500, 88 MSG_EM_SPARC32PLUS, 89 MSG_EM_UNKNOWN19, 90 MSG_EM_PPC, 91 MSG_EM_PPC64, 92 MSG_EM_UNKNOWN22, 93 MSG_EM_UNKNOWN23, 94 MSG_EM_UNKNOWN24, 95 MSG_EM_UNKNOWN25, 96 MSG_EM_UNKNOWN26, 97 MSG_EM_UNKNOWN27, 98 MSG_EM_UNKNOWN28, 99 MSG_EM_UNKNOWN29, 100 MSG_EM_UNKNOWN30, 101 MSG_EM_UNKNOWN31, 102 MSG_EM_UNKNOWN32, 103 MSG_EM_UNKNOWN33, 104 MSG_EM_UNKNOWN34, 105 MSG_EM_UNKNOWN35, 106 MSG_EM_Y800, 107 MSG_EM_FR20, 108 MSG_EM_RH32, 109 MSG_EM_RCE, 110 MSG_EM_ARM, 111 MSG_EM_ALPHA, 112 MSG_EM_SH, 113 MSG_EM_SPARCV9, 114 MSG_EM_TRICORE, 115 MSG_EM_ARC, 116 MSG_EM_H8_300, 117 MSG_EM_H8_300H, 118 MSG_EM_H8S, 119 MSG_EM_H8_500, 120 MSG_EM_IA_64, 121 MSG_EM_MIPS_X, 122 MSG_EM_COLDFIRE, 123 MSG_EM_68HC12, 124 MSG_EM_MMA, 125 MSG_EM_PCP, 126 MSG_EM_NCPU, 127 MSG_EM_NDR1, 128 MSG_EM_STARCORE, 129 MSG_EM_ME16, 130 MSG_EM_ST100, 131 MSG_EM_TINYJ, 132 MSG_EM_AMD64, 133 MSG_EM_UNKNOWN63, 134 MSG_EM_UNKNOWN64, 135 MSG_EM_UNKNOWN65, 136 MSG_EM_FX66, 137 MSG_EM_ST9PLUS, 138 MSG_EM_ST7, 139 MSG_EM_68HC16, 140 MSG_EM_68HC11, 141 MSG_EM_68HC08, 142 MSG_EM_68HC05, 143 MSG_EM_SVX, 144 MSG_EM_ST19, 145 MSG_EM_VAX, 146 MSG_EM_CRIS, 147 MSG_EM_JAVELIN, 148 MSG_EM_FIREPATH, 149 MSG_EM_ZSP, 150 MSG_EM_MMIX, 151 MSG_EM_HUANY, 152 MSG_EM_PRISM, 153 MSG_EM_AVR, 154 MSG_EM_FR30, 155 MSG_EM_D10V, 156 MSG_EM_D30V, 157 MSG_EM_V850, 158 MSG_EM_M32R, 159 MSG_EM_MN10300, 160 MSG_EM_MN10200, 161 MSG_EM_PJ, 162 MSG_EM_OPENRISC, 163 MSG_EM_ARC_A5, 164 MSG_EM_XTENSA 165 }; 166 167 const char * 168 conv_emach_str(ushort_t machine) 169 { 170 static char string[STRSIZE] = { '\0' }; 171 172 /* 173 * In order to assure that all values included in sys/elf.h::EM_* are 174 * included in libconv/elfdump for decoding - we have the below 175 * #define trap. Each time the machines[] table is updated, make 176 * sure the following entry is updated. 177 */ 178 #if (EM_NUM != (EM_XTENSA + 1)) 179 #error "EM_NUM has grown" 180 #endif 181 if (machine >= (EM_NUM)) 182 return (conv_invalid_str(string, STRSIZE, machine, 0)); 183 else 184 return (MSG_ORIG(machines[machine])); 185 186 } 187 188 static const Msg etypes[] = { 189 MSG_ET_NONE, MSG_ET_REL, MSG_ET_EXEC, 190 MSG_ET_DYN, MSG_ET_CORE 191 }; 192 193 const char * 194 conv_etype_str(ushort_t etype) 195 { 196 static char string[STRSIZE] = { '\0' }; 197 198 if (etype == ET_SUNWPSEUDO) 199 return (MSG_ORIG(MSG_ET_SUNWPSEUDO)); 200 else if (etype >= ET_NUM) 201 return (conv_invalid_str(string, STRSIZE, etype, 0)); 202 else 203 return (MSG_ORIG(etypes[etype])); 204 } 205 206 static const Msg versions[] = { 207 MSG_EV_NONE, MSG_EV_CURRENT 208 }; 209 210 const char * 211 conv_ever_str(uint_t version) 212 { 213 static char string[STRSIZE] = { '\0' }; 214 215 if (version >= EV_NUM) 216 return (conv_invalid_str(string, STRSIZE, version, 0)); 217 else 218 return (MSG_ORIG(versions[version])); 219 } 220 221 222 static const Msg mm_flags[] = { 223 MSG_EF_SPARCV9_TSO, MSG_EF_SPARCV9_PSO, MSG_EF_SPARCV9_RMO 224 }; 225 226 #define EFLAGSZ MSG_GBL_OSQBRKT_SIZE + \ 227 MSG_EF_SPARCV9_TSO_SIZE + \ 228 MSG_EF_SPARC_SUN_US1_SIZE + \ 229 MSG_EF_SPARC_HAL_R1_SIZE + \ 230 MSG_EF_SPARC_SUN_US3_SIZE + \ 231 MSG_GBL_CSQBRKT_SIZE 232 233 /* 234 * Valid vendor extension bits for SPARCV9. This must be updated along with 235 * elf_SPARC.h. 236 */ 237 const char * 238 conv_eflags_str(ushort_t mach, uint_t flags) 239 { 240 static char string[EFLAGSZ] = { '\0' }; 241 242 /* 243 * Make a string representation of the e_flags field. If any bogus 244 * bits are set, then just return a string containing the numeric value. 245 */ 246 if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) || 247 (mach == EM_SPARC32PLUS)) && flags)) { 248 uint_t _flags = flags; 249 250 (void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT)); 251 252 if (mach == EM_SPARCV9) { 253 (void) strcat(string, MSG_ORIG(mm_flags[flags & 254 EF_SPARCV9_MM])); 255 _flags &= ~EF_SPARCV9_MM; 256 } 257 258 if (flags & EF_SPARC_32PLUS) { 259 (void) strcat(string, MSG_ORIG(MSG_EF_SPARC_32PLUS)); 260 _flags &= ~EF_SPARC_32PLUS; 261 } 262 if (flags & EF_SPARC_SUN_US1) { 263 (void) strcat(string, MSG_ORIG(MSG_EF_SPARC_SUN_US1)); 264 _flags &= ~EF_SPARC_SUN_US1; 265 } 266 if (flags & EF_SPARC_HAL_R1) { 267 (void) strcat(string, MSG_ORIG(MSG_EF_SPARC_HAL_R1)); 268 _flags &= ~EF_SPARC_HAL_R1; 269 } 270 if (flags & EF_SPARC_SUN_US3) { 271 (void) strcat(string, MSG_ORIG(MSG_EF_SPARC_SUN_US3)); 272 _flags &= ~EF_SPARC_SUN_US3; 273 } 274 if (_flags) 275 (void) sprintf(&string[strlen(string)], 276 MSG_ORIG(MSG_EF_GEN_1_FLAGS), _flags); 277 278 (void) strcat(string, MSG_ORIG(MSG_GBL_CSQBRKT)); 279 } else 280 (void) sprintf(string, MSG_ORIG(MSG_EF_GEN_2_FLAGS), flags); 281 282 return (string); 283 } 284 285 /* 286 * A generic means of returning additional information for a rejected file in 287 * terms of a string. 288 */ 289 const char * 290 conv_reject_str(Rej_desc * rej) 291 { 292 static char string[STRSIZE] = { '\0' }; 293 294 ushort_t type = rej->rej_type; 295 uint_t info = rej->rej_info; 296 297 if (type == SGS_REJ_MACH) 298 /* LINTED */ 299 return (conv_emach_str((ushort_t)info)); 300 else if (type == SGS_REJ_CLASS) 301 /* LINTED */ 302 return (conv_eclass_str((uchar_t)info)); 303 else if (type == SGS_REJ_DATA) 304 /* LINTED */ 305 return (conv_edata_str((uchar_t)info)); 306 else if (type == SGS_REJ_TYPE) 307 /* LINTED */ 308 return (conv_etype_str((ushort_t)info)); 309 else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) || 310 (type == SGS_REJ_HAL) || (type == SGS_REJ_US3)) 311 /* 312 * Only called from ld.so.1, thus M_MACH is hardcoded. 313 */ 314 return (conv_eflags_str(M_MACH, info)); 315 else if (type == SGS_REJ_UNKFILE) 316 return ((const char *)0); 317 else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) { 318 if (rej->rej_str) 319 return ((const char *)rej->rej_str); 320 else 321 return (MSG_ORIG(MSG_STR_EMPTY)); 322 } else 323 return (conv_invalid_str(string, STRSIZE, info, 1)); 324 } 325