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 const char * 38 conv_ehdr_class(uchar_t class) 39 { 40 static char string[CONV_INV_STRSIZE]; 41 static const Msg classes[] = { 42 MSG_ELFCLASSNONE, MSG_ELFCLASS32, MSG_ELFCLASS64 43 }; 44 45 if (class >= ELFCLASSNUM) 46 return (conv_invalid_val(string, CONV_INV_STRSIZE, class, 0)); 47 else 48 return (MSG_ORIG(classes[class])); 49 } 50 51 const char * 52 conv_ehdr_data(uchar_t data) 53 { 54 static char string[CONV_INV_STRSIZE]; 55 static const Msg datas[] = { 56 MSG_ELFDATANONE, MSG_ELFDATA2LSB, MSG_ELFDATA2MSB 57 }; 58 59 if (data >= ELFDATANUM) 60 return (conv_invalid_val(string, CONV_INV_STRSIZE, data, 0)); 61 else 62 return (MSG_ORIG(datas[data])); 63 } 64 65 static const Msg machines[EM_NUM] = { 66 MSG_EM_NONE, MSG_EM_M32, MSG_EM_SPARC, 67 MSG_EM_386, MSG_EM_68K, MSG_EM_88K, 68 MSG_EM_486, MSG_EM_860, MSG_EM_MIPS, 69 MSG_EM_UNKNOWN9, MSG_EM_MIPS_RS3_LE, MSG_EM_RS6000, 70 MSG_EM_UNKNOWN12, MSG_EM_UNKNOWN13, MSG_EM_UNKNOWN14, 71 MSG_EM_PA_RISC, MSG_EM_nCUBE, MSG_EM_VPP500, 72 MSG_EM_SPARC32PLUS, MSG_EM_UNKNOWN19, MSG_EM_PPC, 73 MSG_EM_PPC64, MSG_EM_UNKNOWN22, MSG_EM_UNKNOWN23, 74 MSG_EM_UNKNOWN24, MSG_EM_UNKNOWN25, MSG_EM_UNKNOWN26, 75 MSG_EM_UNKNOWN27, MSG_EM_UNKNOWN28, MSG_EM_UNKNOWN29, 76 MSG_EM_UNKNOWN30, MSG_EM_UNKNOWN31, MSG_EM_UNKNOWN32, 77 MSG_EM_UNKNOWN33, MSG_EM_UNKNOWN34, MSG_EM_UNKNOWN35, 78 MSG_EM_Y800, MSG_EM_FR20, MSG_EM_RH32, 79 MSG_EM_RCE, MSG_EM_ARM, MSG_EM_ALPHA, 80 MSG_EM_SH, MSG_EM_SPARCV9, MSG_EM_TRICORE, 81 MSG_EM_ARC, MSG_EM_H8_300, MSG_EM_H8_300H, 82 MSG_EM_H8S, MSG_EM_H8_500, MSG_EM_IA_64, 83 MSG_EM_MIPS_X, MSG_EM_COLDFIRE, MSG_EM_68HC12, 84 MSG_EM_MMA, MSG_EM_PCP, MSG_EM_NCPU, 85 MSG_EM_NDR1, MSG_EM_STARCORE, MSG_EM_ME16, 86 MSG_EM_ST100, MSG_EM_TINYJ, MSG_EM_AMD64, 87 MSG_EM_UNKNOWN63, MSG_EM_UNKNOWN64, MSG_EM_UNKNOWN65, 88 MSG_EM_FX66, MSG_EM_ST9PLUS, MSG_EM_ST7, 89 MSG_EM_68HC16, MSG_EM_68HC11, MSG_EM_68HC08, 90 MSG_EM_68HC05, MSG_EM_SVX, MSG_EM_ST19, 91 MSG_EM_VAX, MSG_EM_CRIS, MSG_EM_JAVELIN, 92 MSG_EM_FIREPATH, MSG_EM_ZSP, MSG_EM_MMIX, 93 MSG_EM_HUANY, MSG_EM_PRISM, MSG_EM_AVR, 94 MSG_EM_FR30, MSG_EM_D10V, MSG_EM_D30V, 95 MSG_EM_V850, MSG_EM_M32R, MSG_EM_MN10300, 96 MSG_EM_MN10200, MSG_EM_PJ, MSG_EM_OPENRISC, 97 MSG_EM_ARC_A5, MSG_EM_XTENSA 98 }; 99 #if (EM_NUM != (EM_XTENSA + 1)) 100 #error "EM_NUM has grown" 101 #endif 102 103 const char * 104 conv_ehdr_mach(Half machine) 105 { 106 static char string[CONV_INV_STRSIZE]; 107 108 if (machine >= (EM_NUM)) 109 return (conv_invalid_val(string, CONV_INV_STRSIZE, machine, 0)); 110 else 111 return (MSG_ORIG(machines[machine])); 112 } 113 114 const char * 115 conv_ehdr_type(Half etype) 116 { 117 static char string[CONV_INV_STRSIZE]; 118 static const Msg etypes[] = { 119 MSG_ET_NONE, MSG_ET_REL, MSG_ET_EXEC, 120 MSG_ET_DYN, MSG_ET_CORE 121 }; 122 123 if (etype == ET_SUNWPSEUDO) 124 return (MSG_ORIG(MSG_ET_SUNWPSEUDO)); 125 else if (etype >= ET_NUM) 126 return (conv_invalid_val(string, CONV_INV_STRSIZE, etype, 0)); 127 else 128 return (MSG_ORIG(etypes[etype])); 129 } 130 131 const char * 132 conv_ehdr_vers(Word version) 133 { 134 static char string[CONV_INV_STRSIZE]; 135 static const Msg versions[] = { 136 MSG_EV_NONE, MSG_EV_CURRENT 137 }; 138 139 if (version >= EV_NUM) 140 return (conv_invalid_val(string, CONV_INV_STRSIZE, version, 0)); 141 else 142 return (MSG_ORIG(versions[version])); 143 } 144 145 #define EFLAGSZ MSG_GBL_OSQBRKT_SIZE + \ 146 MSG_EF_SPARCV9_TSO_SIZE + \ 147 MSG_EF_SPARC_SUN_US1_SIZE + \ 148 MSG_EF_SPARC_HAL_R1_SIZE + \ 149 MSG_EF_SPARC_SUN_US3_SIZE + \ 150 CONV_INV_STRSIZE + MSG_GBL_CSQBRKT_SIZE 151 152 /* 153 * Make a string representation of the e_flags field. 154 */ 155 const char * 156 conv_ehdr_flags(Half mach, Word flags) 157 { 158 static char string[EFLAGSZ]; 159 static Val_desc vda[] = { 160 { EF_SPARC_32PLUS, MSG_ORIG(MSG_EF_SPARC_32PLUS) }, 161 { EF_SPARC_SUN_US1, MSG_ORIG(MSG_EF_SPARC_SUN_US1) }, 162 { EF_SPARC_HAL_R1, MSG_ORIG(MSG_EF_SPARC_HAL_R1) }, 163 { EF_SPARC_SUN_US3, MSG_ORIG(MSG_EF_SPARC_SUN_US3) }, 164 { 0, 0 } 165 }; 166 static const Msg mm_flags[] = { 167 MSG_EF_SPARCV9_TSO, MSG_EF_SPARCV9_PSO, 168 MSG_EF_SPARCV9_RMO 169 }; 170 Word _flags = flags; 171 172 /* 173 * Non-SPARC architectures presently provide no known flags. 174 */ 175 if ((mach == EM_SPARCV9) || (((mach == EM_SPARC) || 176 (mach == EM_SPARC32PLUS)) && flags)) { 177 /* 178 * Valid vendor extension bits for SPARCV9. These must be 179 * updated along with elf_SPARC.h. 180 */ 181 (void) strcpy(string, MSG_ORIG(MSG_GBL_OSQBRKT)); 182 183 if ((mach == EM_SPARCV9) && (flags <= EF_SPARCV9_RMO)) { 184 if (strlcat(string, 185 MSG_ORIG(mm_flags[flags & EF_SPARCV9_MM]), 186 EFLAGSZ) >= EFLAGSZ) 187 return (conv_invalid_val(string, EFLAGSZ, 188 flags, 0)); 189 _flags &= ~EF_SPARCV9_MM; 190 } 191 192 if (conv_expn_field(string, EFLAGSZ, vda, flags, _flags, 0, 0)) 193 (void) strlcat(string, MSG_ORIG(MSG_GBL_CSQBRKT), 194 EFLAGSZ); 195 196 return (string); 197 } 198 return (conv_invalid_val(string, EFLAGSZ, flags, CONV_INV_DECIMAL)); 199 } 200 201 /* 202 * A generic means of returning additional information for a rejected file in 203 * terms of a string. 204 */ 205 const char * 206 conv_reject_desc(Rej_desc * rej) 207 { 208 static char string[CONV_INV_STRSIZE]; 209 210 ushort_t type = rej->rej_type; 211 uint_t info = rej->rej_info; 212 213 if (type == SGS_REJ_MACH) 214 /* LINTED */ 215 return (conv_ehdr_mach((Half)info)); 216 else if (type == SGS_REJ_CLASS) 217 /* LINTED */ 218 return (conv_ehdr_class((uchar_t)info)); 219 else if (type == SGS_REJ_DATA) 220 /* LINTED */ 221 return (conv_ehdr_data((uchar_t)info)); 222 else if (type == SGS_REJ_TYPE) 223 /* LINTED */ 224 return (conv_ehdr_type((Half)info)); 225 else if ((type == SGS_REJ_BADFLAG) || (type == SGS_REJ_MISFLAG) || 226 (type == SGS_REJ_HAL) || (type == SGS_REJ_US3)) 227 /* 228 * Only called from ld.so.1, thus M_MACH is hardcoded. 229 */ 230 return (conv_ehdr_flags(M_MACH, (Word)info)); 231 else if (type == SGS_REJ_UNKFILE) 232 return ((const char *)0); 233 else if ((type == SGS_REJ_STR) || (type == SGS_REJ_HWCAP_1)) { 234 if (rej->rej_str) 235 return ((const char *)rej->rej_str); 236 else 237 return (MSG_ORIG(MSG_STR_EMPTY)); 238 } else 239 return (conv_invalid_val(string, CONV_INV_STRSIZE, info, 240 CONV_INV_DECIMAL)); 241 } 242