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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * String conversion routines for symbol attributes. 29 */ 30 #include <stdio.h> 31 #include <sys/elf_SPARC.h> 32 #include <sys/elf_amd64.h> 33 #include "_conv.h" 34 #include "symbols_msg.h" 35 36 const char * 37 conv_sym_other(uchar_t other, Conv_inv_buf_t *inv_buf) 38 { 39 static const char visibility[7] = { 40 'D', /* STV_DEFAULT */ 41 'I', /* STV_INTERNAL */ 42 'H', /* STV_HIDDEN */ 43 'P', /* STV_PROTECTED */ 44 'X', /* STV_EXPORTED */ 45 'S', /* STV_SINGLETON */ 46 'E' /* STV_ELIMINATE */ 47 }; 48 uchar_t vis = ELF_ST_VISIBILITY(other); 49 uint_t ndx = 0; 50 51 inv_buf->buf[ndx++] = visibility[vis]; 52 53 /* 54 * If unknown bits are present in st_other - throw out a '?' 55 */ 56 if (other & ~MSK_SYM_VISIBILITY) 57 inv_buf->buf[ndx++] = '?'; 58 inv_buf->buf[ndx++] = '\0'; 59 60 return (inv_buf->buf); 61 } 62 63 static const conv_ds_t ** 64 conv_sym_other_vis_strings(Conv_fmt_flags_t fmt_flags) 65 { 66 static const Msg vis_def[] = { 67 MSG_STV_DEFAULT_DEF, MSG_STV_INTERNAL_DEF, 68 MSG_STV_HIDDEN_DEF, MSG_STV_PROTECTED_DEF, 69 MSG_STV_EXPORTED_DEF, MSG_STV_SINGLETON_DEF, 70 MSG_STV_ELIMINATE_DEF 71 }; 72 static const Msg vis_cf[] = { 73 MSG_STV_DEFAULT_CF, MSG_STV_INTERNAL_CF, 74 MSG_STV_HIDDEN_CF, MSG_STV_PROTECTED_CF, 75 MSG_STV_EXPORTED_CF, MSG_STV_SINGLETON_CF, 76 MSG_STV_ELIMINATE_CF 77 }; 78 static const Msg vis_nf[] = { 79 MSG_STV_DEFAULT_NF, MSG_STV_INTERNAL_NF, 80 MSG_STV_HIDDEN_NF, MSG_STV_PROTECTED_NF, 81 MSG_STV_EXPORTED_NF, MSG_STV_SINGLETON_NF, 82 MSG_STV_ELIMINATE_NF 83 }; 84 static const conv_ds_msg_t ds_vis_def = { 85 CONV_DS_MSG_INIT(STV_DEFAULT, vis_def) }; 86 static const conv_ds_msg_t ds_vis_cf = { 87 CONV_DS_MSG_INIT(STV_DEFAULT, vis_cf) }; 88 static const conv_ds_msg_t ds_vis_nf = { 89 CONV_DS_MSG_INIT(STV_DEFAULT, vis_nf) }; 90 91 /* Build NULL terminated return arrays for each string style */ 92 static const conv_ds_t *ds_def[] = { 93 CONV_DS_ADDR(ds_vis_def), NULL }; 94 static const conv_ds_t *ds_cf[] = { 95 CONV_DS_ADDR(ds_vis_cf), NULL }; 96 static const conv_ds_t *ds_nf[] = { 97 CONV_DS_ADDR(ds_vis_nf), NULL }; 98 99 /* Select the strings to use */ 100 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 101 case CONV_FMT_ALT_CF: 102 return (ds_cf); 103 case CONV_FMT_ALT_NF: 104 return (ds_nf); 105 } 106 107 return (ds_def); 108 } 109 110 const char * 111 conv_sym_other_vis(uchar_t value, Conv_fmt_flags_t fmt_flags, 112 Conv_inv_buf_t *inv_buf) 113 { 114 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, value, 115 conv_sym_other_vis_strings(fmt_flags), fmt_flags, inv_buf)); 116 } 117 118 conv_iter_ret_t 119 conv_iter_sym_other_vis(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, 120 void *uvalue) 121 { 122 return (conv_iter_ds(ELFOSABI_NONE, EM_NONE, 123 conv_sym_other_vis_strings(fmt_flags), func, uvalue)); 124 } 125 126 static const conv_ds_t ** 127 conv_sym_info_type_strings(Half mach, Conv_fmt_flags_t fmt_flags) 128 { 129 /* 130 * This routine can return an array with 1 generic array, and 131 * a machine array, plus the NULL termination. 132 */ 133 #define MAX_RET 3 134 135 static const Msg types_def[] = { 136 MSG_STT_NOTYPE_DEF, MSG_STT_OBJECT_DEF, 137 MSG_STT_FUNC_DEF, MSG_STT_SECTION_DEF, 138 MSG_STT_FILE_DEF, MSG_STT_COMMON_DEF, 139 MSG_STT_TLS_DEF, MSG_STT_IFUNC_DEF 140 }; 141 static const Msg types_cf[] = { 142 MSG_STT_NOTYPE_CF, MSG_STT_OBJECT_CF, 143 MSG_STT_FUNC_CF, MSG_STT_SECTION_CF, 144 MSG_STT_FILE_CF, MSG_STT_COMMON_CF, 145 MSG_STT_TLS_CF, MSG_STT_IFUNC_CF 146 }; 147 static const Msg types_cfnp[] = { 148 MSG_STT_NOTYPE_CFNP, MSG_STT_OBJECT_CFNP, 149 MSG_STT_FUNC_CFNP, MSG_STT_SECTION_CFNP, 150 MSG_STT_FILE_CFNP, MSG_STT_COMMON_CFNP, 151 MSG_STT_TLS_CFNP, MSG_STT_IFUNC_CFNP 152 }; 153 static const Msg types_nf[] = { 154 MSG_STT_NOTYPE_NF, MSG_STT_OBJECT_NF, 155 MSG_STT_FUNC_NF, MSG_STT_SECTION_NF, 156 MSG_STT_FILE_NF, MSG_STT_COMMON_NF, 157 MSG_STT_TLS_NF, MSG_STT_IFUNC_NF 158 }; 159 static const conv_ds_msg_t ds_types_def = { 160 CONV_DS_MSG_INIT(STT_NOTYPE, types_def) }; 161 static const conv_ds_msg_t ds_types_cf = { 162 CONV_DS_MSG_INIT(STT_NOTYPE, types_cf) }; 163 static const conv_ds_msg_t ds_types_cfnp = { 164 CONV_DS_MSG_INIT(STT_NOTYPE, types_cfnp) }; 165 static const conv_ds_msg_t ds_types_nf = { 166 CONV_DS_MSG_INIT(STT_NOTYPE, types_nf) }; 167 168 169 static const Msg sparc_def[] = { MSG_STT_SPARC_REGISTER_DEF }; 170 static const Msg sparc_cf[] = { MSG_STT_SPARC_REGISTER_CF }; 171 static const Msg sparc_cfnp[] = { MSG_STT_SPARC_REGISTER_CFNP }; 172 static const Msg sparc_nf[] = { MSG_STT_SPARC_REGISTER_NF }; 173 static const conv_ds_msg_t ds_sparc_def = { 174 CONV_DS_MSG_INIT(STT_SPARC_REGISTER, sparc_def) }; 175 static const conv_ds_msg_t ds_sparc_cf = { 176 CONV_DS_MSG_INIT(STT_SPARC_REGISTER, sparc_cf) }; 177 static const conv_ds_msg_t ds_sparc_cfnp = { 178 CONV_DS_MSG_INIT(STT_SPARC_REGISTER, sparc_cfnp) }; 179 static const conv_ds_msg_t ds_sparc_nf = { 180 CONV_DS_MSG_INIT(STT_SPARC_REGISTER, sparc_nf) }; 181 182 183 static const conv_ds_t *retarr[MAX_RET]; 184 185 int retndx = 0; 186 int is_sparc; 187 188 is_sparc = (mach == EM_SPARC) || (mach == EM_SPARCV9) || 189 (mach == EM_SPARC32PLUS) || (mach == CONV_MACH_ALL); 190 191 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 192 case CONV_FMT_ALT_CF: 193 retarr[retndx++] = CONV_DS_ADDR(ds_types_cf); 194 if (is_sparc) 195 retarr[retndx++] = CONV_DS_ADDR(ds_sparc_cf); 196 break; 197 case CONV_FMT_ALT_CFNP: 198 retarr[retndx++] = CONV_DS_ADDR(ds_types_cfnp); 199 if (is_sparc) 200 retarr[retndx++] = CONV_DS_ADDR(ds_sparc_cfnp); 201 break; 202 case CONV_FMT_ALT_NF: 203 retarr[retndx++] = CONV_DS_ADDR(ds_types_nf); 204 if (is_sparc) 205 retarr[retndx++] = CONV_DS_ADDR(ds_sparc_nf); 206 break; 207 default: 208 retarr[retndx++] = CONV_DS_ADDR(ds_types_def); 209 if (is_sparc) 210 retarr[retndx++] = CONV_DS_ADDR(ds_sparc_def); 211 break; 212 } 213 214 retarr[retndx++] = NULL; 215 assert(retndx <= MAX_RET); 216 return (retarr); 217 } 218 219 const char * 220 conv_sym_info_type(Half mach, uchar_t type, Conv_fmt_flags_t fmt_flags, 221 Conv_inv_buf_t *inv_buf) 222 { 223 return (conv_map_ds(ELFOSABI_NONE, mach, type, 224 conv_sym_info_type_strings(mach, fmt_flags), fmt_flags, inv_buf)); 225 } 226 227 conv_iter_ret_t 228 conv_iter_sym_info_type(Half mach, Conv_fmt_flags_t fmt_flags, 229 conv_iter_cb_t func, void *uvalue) 230 { 231 return (conv_iter_ds(ELFOSABI_NONE, mach, 232 conv_sym_info_type_strings(mach, fmt_flags), func, uvalue)); 233 } 234 235 static const conv_ds_t ** 236 conv_sym_info_bind_strings(Conv_fmt_flags_t fmt_flags) 237 { 238 static const Msg binds_def[] = { 239 MSG_STB_LOCAL_DEF, MSG_STB_GLOBAL_DEF, 240 MSG_STB_WEAK_DEF 241 }; 242 static const Msg binds_cf[] = { 243 MSG_STB_LOCAL_CF, MSG_STB_GLOBAL_CF, 244 MSG_STB_WEAK_CF 245 }; 246 static const Msg binds_cfnp[] = { 247 MSG_STB_LOCAL_CFNP, MSG_STB_GLOBAL_CFNP, 248 MSG_STB_WEAK_CFNP 249 }; 250 static const Msg binds_nf[] = { 251 MSG_STB_LOCAL_NF, MSG_STB_GLOBAL_NF, 252 MSG_STB_WEAK_NF 253 }; 254 static const conv_ds_msg_t ds_binds_def = { 255 CONV_DS_MSG_INIT(STB_LOCAL, binds_def) }; 256 static const conv_ds_msg_t ds_binds_cf = { 257 CONV_DS_MSG_INIT(STB_LOCAL, binds_cf) }; 258 static const conv_ds_msg_t ds_binds_cfnp = { 259 CONV_DS_MSG_INIT(STB_LOCAL, binds_cfnp) }; 260 static const conv_ds_msg_t ds_binds_nf = { 261 CONV_DS_MSG_INIT(STB_LOCAL, binds_nf) }; 262 263 264 /* Build NULL terminated return arrays for each string style */ 265 static const conv_ds_t *ds_def[] = { 266 CONV_DS_ADDR(ds_binds_def), NULL }; 267 static const conv_ds_t *ds_cf[] = { 268 CONV_DS_ADDR(ds_binds_cf), NULL }; 269 static const conv_ds_t *ds_cfnp[] = { 270 CONV_DS_ADDR(ds_binds_cfnp), NULL }; 271 static const conv_ds_t *ds_nf[] = { 272 CONV_DS_ADDR(ds_binds_nf), NULL }; 273 274 275 /* Select the strings to use */ 276 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 277 case CONV_FMT_ALT_CF: 278 return (ds_cf); 279 case CONV_FMT_ALT_CFNP: 280 return (ds_cfnp); 281 case CONV_FMT_ALT_NF: 282 return (ds_nf); 283 } 284 285 return (ds_def); 286 } 287 288 const char * 289 conv_sym_info_bind(uchar_t bind, Conv_fmt_flags_t fmt_flags, 290 Conv_inv_buf_t *inv_buf) 291 { 292 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, bind, 293 conv_sym_info_bind_strings(fmt_flags), fmt_flags, inv_buf)); 294 } 295 296 conv_iter_ret_t 297 conv_iter_sym_info_bind(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, 298 void *uvalue) 299 { 300 return (conv_iter_ds(ELFOSABI_NONE, EM_NONE, 301 conv_sym_info_bind_strings(fmt_flags), func, uvalue)); 302 } 303 304 static const conv_ds_t ** 305 conv_sym_shndx_strings(Conv_fmt_flags_t fmt_flags) 306 { 307 #define ALL ELFOSABI_NONE, EM_NONE 308 #define SOL ELFOSABI_SOLARIS, EM_NONE 309 #define AMD ELFOSABI_NONE, EM_AMD64 310 311 /* 312 * There aren't many of these values, and they are sparse, 313 * so rather than separate them into different ranges, I use 314 * a single Val_desc2 array for all of them. 315 */ 316 static const Val_desc2 shn_def[] = { 317 { SHN_UNDEF, ALL, MSG_SHN_UNDEF_CFNP }, 318 { SHN_BEFORE, ALL, MSG_SHN_BEFORE_CFNP }, 319 { SHN_AFTER, ALL, MSG_SHN_AFTER_CFNP }, 320 { SHN_AMD64_LCOMMON, AMD, MSG_SHN_AMD64_LCOMMON_DEF }, 321 { SHN_SUNW_IGNORE, SOL, MSG_SHN_SUNW_IGNORE_DEF }, 322 { SHN_ABS, ALL, MSG_SHN_ABS_CFNP }, 323 { SHN_COMMON, ALL, MSG_SHN_COMMON_CFNP }, 324 { SHN_XINDEX, ALL, MSG_SHN_XINDEX_CFNP }, 325 { 0 } 326 }; 327 static const Val_desc2 shn_cf[] = { 328 { SHN_UNDEF, ALL, MSG_SHN_UNDEF_CF }, 329 { SHN_BEFORE, ALL, MSG_SHN_BEFORE_CF }, 330 { SHN_AFTER, ALL, MSG_SHN_AFTER_CF }, 331 { SHN_AMD64_LCOMMON, AMD, MSG_SHN_AMD64_LCOMMON_CF }, 332 { SHN_SUNW_IGNORE, SOL, MSG_SHN_SUNW_IGNORE_CF }, 333 { SHN_ABS, ALL, MSG_SHN_ABS_CF }, 334 { SHN_COMMON, ALL, MSG_SHN_COMMON_CF }, 335 { SHN_XINDEX, ALL, MSG_SHN_XINDEX_CF }, 336 { 0 } 337 }; 338 static const Val_desc2 shn_cfnp[] = { 339 { SHN_UNDEF, ALL, MSG_SHN_UNDEF_CFNP }, 340 { SHN_BEFORE, ALL, MSG_SHN_BEFORE_CFNP }, 341 { SHN_AFTER, ALL, MSG_SHN_AFTER_CFNP }, 342 { SHN_AMD64_LCOMMON, AMD, MSG_SHN_AMD64_LCOMMON_CFNP }, 343 { SHN_SUNW_IGNORE, SOL, MSG_SHN_SUNW_IGNORE_CFNP }, 344 { SHN_ABS, ALL, MSG_SHN_ABS_CFNP }, 345 { SHN_COMMON, ALL, MSG_SHN_COMMON_CFNP }, 346 { SHN_XINDEX, ALL, MSG_SHN_XINDEX_CFNP }, 347 { 0 } 348 }; 349 static const Val_desc2 shn_nf[] = { 350 { SHN_UNDEF, ALL, MSG_SHN_UNDEF_NF }, 351 { SHN_BEFORE, ALL, MSG_SHN_BEFORE_NF }, 352 { SHN_AFTER, ALL, MSG_SHN_AFTER_NF }, 353 { SHN_AMD64_LCOMMON, AMD, MSG_SHN_AMD64_LCOMMON_NF }, 354 { SHN_SUNW_IGNORE, SOL, MSG_SHN_SUNW_IGNORE_NF }, 355 { SHN_ABS, ALL, MSG_SHN_ABS_NF }, 356 { SHN_COMMON, ALL, MSG_SHN_COMMON_NF }, 357 { SHN_XINDEX, ALL, MSG_SHN_XINDEX_NF }, 358 { 0 } 359 }; 360 static const conv_ds_vd2_t ds_shn_def = { 361 CONV_DS_VD2, SHN_UNDEF, SHN_XINDEX, shn_def }; 362 static const conv_ds_vd2_t ds_shn_cf = { 363 CONV_DS_VD2, SHN_UNDEF, SHN_XINDEX, shn_cf }; 364 static const conv_ds_vd2_t ds_shn_cfnp = { 365 CONV_DS_VD2, SHN_UNDEF, SHN_XINDEX, shn_cfnp }; 366 static const conv_ds_vd2_t ds_shn_nf = { 367 CONV_DS_VD2, SHN_UNDEF, SHN_XINDEX, shn_nf }; 368 369 /* Build NULL terminated return arrays for each string style */ 370 static const conv_ds_t *ds_def[] = { 371 CONV_DS_ADDR(ds_shn_def), NULL }; 372 static const conv_ds_t *ds_cf[] = { 373 CONV_DS_ADDR(ds_shn_cf), NULL }; 374 static const conv_ds_t *ds_cfnp[] = { 375 CONV_DS_ADDR(ds_shn_cfnp), NULL }; 376 static const conv_ds_t *ds_nf[] = { 377 CONV_DS_ADDR(ds_shn_nf), NULL }; 378 379 /* Select the strings to use */ 380 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 381 case CONV_FMT_ALT_CF: 382 return (ds_cf); 383 case CONV_FMT_ALT_CFNP: 384 return (ds_cfnp); 385 case CONV_FMT_ALT_NF: 386 return (ds_nf); 387 } 388 389 return (ds_def); 390 391 #undef ALL 392 #undef SOL 393 #undef AMD 394 } 395 396 const char * 397 conv_sym_shndx(uchar_t osabi, Half mach, Half shndx, Conv_fmt_flags_t fmt_flags, 398 Conv_inv_buf_t *inv_buf) 399 { 400 return (conv_map_ds(osabi, mach, shndx, 401 conv_sym_shndx_strings(fmt_flags), fmt_flags, inv_buf)); 402 } 403 404 conv_iter_ret_t 405 conv_iter_sym_shndx(conv_iter_osabi_t osabi, Half mach, 406 Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue) 407 { 408 static const Msg amd64_alias_cf[] = { MSG_SHN_X86_64_LCOMMON_CF }; 409 static const conv_ds_msg_t ds_msg_amd64_alias_cf = { 410 CONV_DS_MSG_INIT(SHN_X86_64_LCOMMON, amd64_alias_cf) }; 411 static const conv_ds_t *ds_amd64_alias_cf[] = { 412 CONV_DS_ADDR(ds_msg_amd64_alias_cf), NULL }; 413 414 static const Msg amd64_alias_cfnp[] = { MSG_SHN_X86_64_LCOMMON_CFNP }; 415 static const conv_ds_msg_t ds_msg_amd64_alias_cfnp = { 416 CONV_DS_MSG_INIT(SHN_X86_64_LCOMMON, amd64_alias_cfnp) }; 417 static const conv_ds_t *ds_amd64_alias_cfnp[] = { 418 CONV_DS_ADDR(ds_msg_amd64_alias_cfnp), NULL }; 419 420 static const Msg amd64_alias_nf[] = { MSG_SHN_X86_64_LCOMMON_NF }; 421 static const conv_ds_msg_t ds_msg_amd64_alias_nf = { 422 CONV_DS_MSG_INIT(SHN_X86_64_LCOMMON, amd64_alias_nf) }; 423 static const conv_ds_t *ds_amd64_alias_nf[] = { 424 CONV_DS_ADDR(ds_msg_amd64_alias_nf), NULL }; 425 426 427 if (conv_iter_ds(osabi, mach, conv_sym_shndx_strings(fmt_flags), 428 func, uvalue) == CONV_ITER_DONE) 429 return (CONV_ITER_DONE); 430 431 /* 432 * SHN_AMD64_LCOMMON is also known as SHN_X86_64_LCOMMON 433 */ 434 if (mach == EM_AMD64) { 435 const conv_ds_t **ds; 436 437 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 438 case CONV_FMT_ALT_CF: 439 ds = ds_amd64_alias_cf; 440 break; 441 case CONV_FMT_ALT_NF: 442 ds = ds_amd64_alias_nf; 443 break; 444 default: 445 ds = ds_amd64_alias_cfnp; 446 break; 447 } 448 return (conv_iter_ds(ELFOSABI_NONE, mach, ds, func, uvalue)); 449 } 450 451 return (CONV_ITER_CONT); 452 } 453