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 section attributes. 30 */ 31 #include <string.h> 32 #include <sys/param.h> 33 #include <sys/elf_SPARC.h> 34 #include <sys/elf_amd64.h> 35 #include <_conv.h> 36 #include <sections_msg.h> 37 38 39 40 /* Instantiate a local copy of conv_map2str() from _conv.h */ 41 DEFINE_conv_map2str 42 43 44 45 static const Msg secs[SHT_NUM] = { 46 MSG_SHT_NULL, MSG_SHT_PROGBITS, MSG_SHT_SYMTAB, 47 MSG_SHT_STRTAB, MSG_SHT_RELA, MSG_SHT_HASH, 48 MSG_SHT_DYNAMIC, MSG_SHT_NOTE, MSG_SHT_NOBITS, 49 MSG_SHT_REL, MSG_SHT_SHLIB, MSG_SHT_DYNSYM, 50 MSG_SHT_UNKNOWN12, MSG_SHT_UNKNOWN13, MSG_SHT_INIT_ARRAY, 51 MSG_SHT_FINI_ARRAY, MSG_SHT_PREINIT_ARRAY, MSG_SHT_GROUP, 52 MSG_SHT_SYMTAB_SHNDX 53 }; 54 static const Msg secs_alt[SHT_NUM] = { 55 MSG_SHT_NULL_ALT, MSG_SHT_PROGBITS_ALT, MSG_SHT_SYMTAB_ALT, 56 MSG_SHT_STRTAB_ALT, MSG_SHT_RELA_ALT, MSG_SHT_HASH_ALT, 57 MSG_SHT_DYNAMIC_ALT, MSG_SHT_NOTE_ALT, MSG_SHT_NOBITS_ALT, 58 MSG_SHT_REL_ALT, MSG_SHT_SHLIB_ALT, MSG_SHT_DYNSYM_ALT, 59 MSG_SHT_UNKNOWN12, MSG_SHT_UNKNOWN13, MSG_SHT_INIT_ARRAY_ALT, 60 MSG_SHT_FINI_ARRAY_ALT, MSG_SHT_PREINIT_ARRAY_ALT, MSG_SHT_GROUP_ALT, 61 MSG_SHT_SYMTAB_SHNDX_ALT 62 }; 63 #if (SHT_NUM != (SHT_SYMTAB_SHNDX + 1)) 64 #error "SHT_NUM has grown" 65 #endif 66 67 static const Msg usecs[SHT_HISUNW - SHT_LOSUNW + 1] = { 68 MSG_SHT_SUNW_symsort, MSG_SHT_SUNW_tlssort, 69 MSG_SHT_SUNW_LDYNSYM, MSG_SHT_SUNW_dof, 70 MSG_SHT_SUNW_cap, MSG_SHT_SUNW_SIGNATURE, 71 MSG_SHT_SUNW_ANNOTATE, MSG_SHT_SUNW_DEBUGSTR, 72 MSG_SHT_SUNW_DEBUG, MSG_SHT_SUNW_move, 73 MSG_SHT_SUNW_COMDAT, MSG_SHT_SUNW_syminfo, 74 MSG_SHT_SUNW_verdef, MSG_SHT_SUNW_verneed, 75 MSG_SHT_SUNW_versym 76 }; 77 static const Msg usecs_alt[SHT_HISUNW - SHT_LOSUNW + 1] = { 78 MSG_SHT_SUNW_symsort_ALT, MSG_SHT_SUNW_tlssort_ALT, 79 MSG_SHT_SUNW_LDYNSYM_ALT, MSG_SHT_SUNW_dof_ALT, 80 MSG_SHT_SUNW_cap_ALT, MSG_SHT_SUNW_SIGNATURE_ALT, 81 MSG_SHT_SUNW_ANNOTATE_ALT, MSG_SHT_SUNW_DEBUGSTR_ALT, 82 MSG_SHT_SUNW_DEBUG_ALT, MSG_SHT_SUNW_move_ALT, 83 MSG_SHT_SUNW_COMDAT_ALT, MSG_SHT_SUNW_syminfo_ALT, 84 MSG_SHT_SUNW_verdef_ALT, MSG_SHT_SUNW_verneed_ALT, 85 MSG_SHT_SUNW_versym_ALT 86 }; 87 #if (SHT_LOSUNW != SHT_SUNW_symsort) 88 #error "SHT_LOSUNW has moved" 89 #endif 90 91 92 const char * 93 conv_sec_type(Half mach, Word sec, Conv_fmt_flags_t fmt_flags, 94 Conv_inv_buf_t *inv_buf) 95 { 96 if (sec < SHT_NUM) { 97 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 98 case CONV_FMT_ALT_DUMP: 99 return (conv_map2str(inv_buf, sec, fmt_flags, 100 ARRAY_NELTS(secs_alt), secs_alt)); 101 default: 102 return (conv_map2str(inv_buf, sec, fmt_flags, 103 ARRAY_NELTS(secs), secs)); 104 } 105 } else if ((sec >= SHT_LOSUNW) && (sec <= SHT_HISUNW)) { 106 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 107 case CONV_FMT_ALT_DUMP: 108 return (conv_map2str(inv_buf, sec - SHT_LOSUNW, 109 fmt_flags, ARRAY_NELTS(usecs_alt), usecs_alt)); 110 default: 111 return (conv_map2str(inv_buf, sec - SHT_LOSUNW, 112 fmt_flags, ARRAY_NELTS(usecs), usecs)); 113 } 114 } else if ((sec >= SHT_LOPROC) && (sec <= SHT_HIPROC)) { 115 switch (mach) { 116 case EM_SPARC: 117 case EM_SPARC32PLUS: 118 case EM_SPARCV9: 119 if (sec != SHT_SPARC_GOTDATA) 120 break; 121 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 122 case CONV_FMT_ALT_DUMP: 123 case CONV_FMT_ALT_FILE: 124 return (MSG_ORIG(MSG_SHT_SPARC_GOTDATA_ALT)); 125 } 126 return (MSG_ORIG(MSG_SHT_SPARC_GOTDATA)); 127 case EM_AMD64: 128 if (sec != SHT_AMD64_UNWIND) 129 break; 130 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 131 case CONV_FMT_ALT_DUMP: 132 case CONV_FMT_ALT_FILE: 133 return (MSG_ORIG(MSG_SHT_AMD64_UNWIND_ALT)); 134 } 135 return (MSG_ORIG(MSG_SHT_AMD64_UNWIND)); 136 } 137 } 138 139 /* If we get here, it's an unknown type */ 140 return (conv_invalid_val(inv_buf, sec, fmt_flags)); 141 } 142 143 #define FLAGSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 144 MSG_SHF_WRITE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 145 MSG_SHF_ALLOC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 146 MSG_SHF_EXECINSTR_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 147 MSG_SHF_MERGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 148 MSG_SHF_STRINGS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 149 MSG_SHF_INFO_LINK_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 150 MSG_SHF_LINK_ORDER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 151 MSG_SHF_OS_NONCONFORMING_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 152 MSG_SHF_GROUP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 153 MSG_SHF_TLS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 154 MSG_SHF_EXCLUDE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 155 MSG_SHF_ORDERED_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 156 MSG_SHF_AMD64_LARGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 157 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 158 159 /* 160 * Ensure that Conv_sec_flags_buf_t is large enough: 161 * 162 * FLAGSZ is the real minimum size of the buffer required by conv_sec_flags(). 163 * However, Conv_sec_flags_buf_t uses CONV_SEC_FLAGS_BUFSIZE to set the 164 * buffer size. We do things this way because the definition of FLAGSZ uses 165 * information that is not available in the environment of other programs 166 * that include the conv.h header file. 167 */ 168 #if CONV_SEC_FLAGS_BUFSIZE < FLAGSZ 169 #error "CONV_SEC_FLAGS_BUFSIZE is not large enough" 170 #endif 171 172 const char * 173 conv_sec_flags(Xword flags, Conv_fmt_flags_t fmt_flags, 174 Conv_sec_flags_buf_t *sec_flags_buf) 175 { 176 static Val_desc vda[] = { 177 { SHF_WRITE, MSG_ORIG(MSG_SHF_WRITE) }, 178 { SHF_ALLOC, MSG_ORIG(MSG_SHF_ALLOC) }, 179 { SHF_EXECINSTR, MSG_ORIG(MSG_SHF_EXECINSTR) }, 180 { SHF_MERGE, MSG_ORIG(MSG_SHF_MERGE) }, 181 { SHF_STRINGS, MSG_ORIG(MSG_SHF_STRINGS) }, 182 { SHF_INFO_LINK, MSG_ORIG(MSG_SHF_INFO_LINK) }, 183 { SHF_LINK_ORDER, MSG_ORIG(MSG_SHF_LINK_ORDER) }, 184 { SHF_OS_NONCONFORMING, MSG_ORIG(MSG_SHF_OS_NONCONFORMING) }, 185 { SHF_GROUP, MSG_ORIG(MSG_SHF_GROUP) }, 186 { SHF_TLS, MSG_ORIG(MSG_SHF_TLS) }, 187 { SHF_EXCLUDE, MSG_ORIG(MSG_SHF_EXCLUDE) }, 188 { SHF_ORDERED, MSG_ORIG(MSG_SHF_ORDERED) }, 189 { SHF_AMD64_LARGE, MSG_ORIG(MSG_SHF_AMD64_LARGE) }, 190 { 0, 0 } 191 }; 192 static CONV_EXPN_FIELD_ARG conv_arg = { 193 NULL, sizeof (sec_flags_buf->buf), vda }; 194 195 if (flags == 0) 196 return (MSG_ORIG(MSG_GBL_ZERO)); 197 198 conv_arg.buf = sec_flags_buf->buf; 199 conv_arg.oflags = conv_arg.rflags = flags; 200 (void) conv_expn_field(&conv_arg, fmt_flags); 201 202 return ((const char *)sec_flags_buf->buf); 203 } 204 205 const char * 206 conv_sec_linkinfo(Word info, Xword flags, Conv_inv_buf_t *inv_buf) 207 { 208 if (flags & ALL_SHF_ORDER) { 209 if (info == SHN_BEFORE) 210 return (MSG_ORIG(MSG_SHN_BEFORE)); 211 else if (info == SHN_AFTER) 212 return (MSG_ORIG(MSG_SHN_AFTER)); 213 } 214 215 (void) conv_invalid_val(inv_buf, info, CONV_FMT_DECIMAL); 216 return ((const char *)inv_buf->buf); 217 } 218