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) 94 { 95 static Conv_inv_buf_t string; 96 97 if (sec < SHT_NUM) { 98 return (conv_map2str(string, sizeof (string), sec, fmt_flags, 99 ARRAY_NELTS(secs), secs, secs_alt, NULL)); 100 } else if ((sec >= SHT_LOSUNW) && (sec <= SHT_HISUNW)) { 101 return (conv_map2str(string, sizeof (string), sec - SHT_LOSUNW, 102 fmt_flags, ARRAY_NELTS(usecs), usecs, usecs_alt, NULL)); 103 } else if ((sec >= SHT_LOPROC) && (sec <= SHT_HIPROC)) { 104 switch (mach) { 105 case EM_SPARC: 106 case EM_SPARC32PLUS: 107 case EM_SPARCV9: 108 if (sec == SHT_SPARC_GOTDATA) { 109 return (fmt_flags & CONV_FMT_ALTDUMP) 110 ? MSG_ORIG(MSG_SHT_SPARC_GOTDATA_ALT) 111 : MSG_ORIG(MSG_SHT_SPARC_GOTDATA); 112 } 113 break; 114 case EM_AMD64: 115 if (sec == SHT_AMD64_UNWIND) { 116 return (fmt_flags & CONV_FMT_ALTDUMP) 117 ? MSG_ORIG(MSG_SHT_AMD64_UNWIND_ALT) 118 : MSG_ORIG(MSG_SHT_AMD64_UNWIND); 119 } 120 } 121 } 122 123 /* If we get here, it's an unknown type */ 124 return (conv_invalid_val(string, CONV_INV_STRSIZE, sec, fmt_flags)); 125 } 126 127 #define FLAGSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 128 MSG_SHF_WRITE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 129 MSG_SHF_ALLOC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 130 MSG_SHF_EXECINSTR_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 131 MSG_SHF_MERGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 132 MSG_SHF_STRINGS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 133 MSG_SHF_INFO_LINK_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 134 MSG_SHF_LINK_ORDER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 135 MSG_SHF_OS_NONCONFORMING_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 136 MSG_SHF_GROUP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 137 MSG_SHF_TLS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 138 MSG_SHF_EXCLUDE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 139 MSG_SHF_ORDERED_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 140 MSG_SHF_AMD64_LARGE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 141 CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 142 143 const char * 144 conv_sec_flags(Xword flags) 145 { 146 static char string[FLAGSZ]; 147 static Val_desc vda[] = { 148 { SHF_WRITE, MSG_ORIG(MSG_SHF_WRITE) }, 149 { SHF_ALLOC, MSG_ORIG(MSG_SHF_ALLOC) }, 150 { SHF_EXECINSTR, MSG_ORIG(MSG_SHF_EXECINSTR) }, 151 { SHF_MERGE, MSG_ORIG(MSG_SHF_MERGE) }, 152 { SHF_STRINGS, MSG_ORIG(MSG_SHF_STRINGS) }, 153 { SHF_INFO_LINK, MSG_ORIG(MSG_SHF_INFO_LINK) }, 154 { SHF_LINK_ORDER, MSG_ORIG(MSG_SHF_LINK_ORDER) }, 155 { SHF_OS_NONCONFORMING, MSG_ORIG(MSG_SHF_OS_NONCONFORMING) }, 156 { SHF_GROUP, MSG_ORIG(MSG_SHF_GROUP) }, 157 { SHF_TLS, MSG_ORIG(MSG_SHF_TLS) }, 158 { SHF_EXCLUDE, MSG_ORIG(MSG_SHF_EXCLUDE) }, 159 { SHF_ORDERED, MSG_ORIG(MSG_SHF_ORDERED) }, 160 { SHF_AMD64_LARGE, MSG_ORIG(MSG_SHF_AMD64_LARGE) }, 161 { 0, 0 } 162 }; 163 static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda }; 164 165 if (flags == 0) 166 return (MSG_ORIG(MSG_GBL_ZERO)); 167 168 conv_arg.oflags = conv_arg.rflags = flags; 169 (void) conv_expn_field(&conv_arg); 170 171 return ((const char *)string); 172 } 173 174 /* 175 * conv_sec_linkinfo() is one of the few conversion routines that can be called 176 * twice for the same diagnostic (see liblddbg:Elf_Shdr()), hence the caller 177 * has to supply different string buffers. 178 */ 179 const char * 180 conv_sec_linkinfo(Word info, Xword flags, Conv_inv_buf_t buffer) 181 { 182 if (flags & ALL_SHF_ORDER) { 183 if (info == SHN_BEFORE) 184 return (MSG_ORIG(MSG_SHN_BEFORE)); 185 else if (info == SHN_AFTER) 186 return (MSG_ORIG(MSG_SHN_AFTER)); 187 } 188 (void) conv_invalid_val(buffer, CONV_INV_STRSIZE, info, 1); 189 return ((const char *)buffer); 190 } 191