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, int fmt_flags, Conv_inv_buf_t *inv_buf) 94 { 95 if (sec < SHT_NUM) { 96 return (conv_map2str(inv_buf, sec, fmt_flags, 97 ARRAY_NELTS(secs), secs, secs_alt, NULL)); 98 } else if ((sec >= SHT_LOSUNW) && (sec <= SHT_HISUNW)) { 99 return (conv_map2str(inv_buf, sec - SHT_LOSUNW, 100 fmt_flags, ARRAY_NELTS(usecs), usecs, usecs_alt, NULL)); 101 } else if ((sec >= SHT_LOPROC) && (sec <= SHT_HIPROC)) { 102 switch (mach) { 103 case EM_SPARC: 104 case EM_SPARC32PLUS: 105 case EM_SPARCV9: 106 if (sec == SHT_SPARC_GOTDATA) { 107 return (fmt_flags & CONV_FMT_ALTDUMP) 108 ? MSG_ORIG(MSG_SHT_SPARC_GOTDATA_ALT) 109 : MSG_ORIG(MSG_SHT_SPARC_GOTDATA); 110 } 111 break; 112 case EM_AMD64: 113 if (sec == SHT_AMD64_UNWIND) { 114 return (fmt_flags & CONV_FMT_ALTDUMP) 115 ? MSG_ORIG(MSG_SHT_AMD64_UNWIND_ALT) 116 : MSG_ORIG(MSG_SHT_AMD64_UNWIND); 117 } 118 } 119 } 120 121 /* If we get here, it's an unknown type */ 122 return (conv_invalid_val(inv_buf, sec, fmt_flags)); 123 } 124 125 #define FLAGSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 126 MSG_SHF_WRITE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 127 MSG_SHF_ALLOC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 128 MSG_SHF_EXECINSTR_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 129 MSG_SHF_MERGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 130 MSG_SHF_STRINGS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 131 MSG_SHF_INFO_LINK_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 132 MSG_SHF_LINK_ORDER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 133 MSG_SHF_OS_NONCONFORMING_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 134 MSG_SHF_GROUP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 135 MSG_SHF_TLS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 136 MSG_SHF_EXCLUDE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 137 MSG_SHF_ORDERED_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 138 MSG_SHF_AMD64_LARGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 139 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 140 141 /* 142 * Ensure that Conv_sec_flags_buf_t is large enough: 143 * 144 * FLAGSZ is the real minimum size of the buffer required by conv_sec_flags(). 145 * However, Conv_sec_flags_buf_t uses CONV_SEC_FLAGS_BUFSIZE to set the 146 * buffer size. We do things this way because the definition of FLAGSZ uses 147 * information that is not available in the environment of other programs 148 * that include the conv.h header file. 149 */ 150 #if CONV_SEC_FLAGS_BUFSIZE < FLAGSZ 151 #error "CONV_SEC_FLAGS_BUFSIZE is not large enough" 152 #endif 153 154 const char * 155 conv_sec_flags(Xword flags, Conv_sec_flags_buf_t *sec_flags_buf) 156 { 157 static Val_desc vda[] = { 158 { SHF_WRITE, MSG_ORIG(MSG_SHF_WRITE) }, 159 { SHF_ALLOC, MSG_ORIG(MSG_SHF_ALLOC) }, 160 { SHF_EXECINSTR, MSG_ORIG(MSG_SHF_EXECINSTR) }, 161 { SHF_MERGE, MSG_ORIG(MSG_SHF_MERGE) }, 162 { SHF_STRINGS, MSG_ORIG(MSG_SHF_STRINGS) }, 163 { SHF_INFO_LINK, MSG_ORIG(MSG_SHF_INFO_LINK) }, 164 { SHF_LINK_ORDER, MSG_ORIG(MSG_SHF_LINK_ORDER) }, 165 { SHF_OS_NONCONFORMING, MSG_ORIG(MSG_SHF_OS_NONCONFORMING) }, 166 { SHF_GROUP, MSG_ORIG(MSG_SHF_GROUP) }, 167 { SHF_TLS, MSG_ORIG(MSG_SHF_TLS) }, 168 { SHF_EXCLUDE, MSG_ORIG(MSG_SHF_EXCLUDE) }, 169 { SHF_ORDERED, MSG_ORIG(MSG_SHF_ORDERED) }, 170 { SHF_AMD64_LARGE, MSG_ORIG(MSG_SHF_AMD64_LARGE) }, 171 { 0, 0 } 172 }; 173 static CONV_EXPN_FIELD_ARG conv_arg = { 174 NULL, sizeof (sec_flags_buf->buf), vda }; 175 176 if (flags == 0) 177 return (MSG_ORIG(MSG_GBL_ZERO)); 178 179 conv_arg.buf = sec_flags_buf->buf; 180 conv_arg.oflags = conv_arg.rflags = flags; 181 (void) conv_expn_field(&conv_arg); 182 183 return ((const char *)sec_flags_buf->buf); 184 } 185 186 const char * 187 conv_sec_linkinfo(Word info, Xword flags, Conv_inv_buf_t *inv_buf) 188 { 189 if (flags & ALL_SHF_ORDER) { 190 if (info == SHN_BEFORE) 191 return (MSG_ORIG(MSG_SHN_BEFORE)); 192 else if (info == SHN_AFTER) 193 return (MSG_ORIG(MSG_SHN_AFTER)); 194 } 195 196 (void) conv_invalid_val(inv_buf, info, 1); 197 return ((const char *)inv_buf->buf); 198 } 199