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 program header attributes. 29 */ 30 #include <stdio.h> 31 #include <string.h> 32 #include <_conv.h> 33 #include <phdr_msg.h> 34 35 static const conv_ds_t ** 36 conv_phdr_type_strings(Conv_fmt_flags_t fmt_flags) 37 { 38 #define ALL ELFOSABI_NONE, EM_NONE 39 #define SOL ELFOSABI_SOLARIS, EM_NONE 40 #define LIN ELFOSABI_LINUX, EM_NONE 41 42 static const Msg phdrs_def[] = { 43 MSG_PT_NULL, MSG_PT_LOAD, 44 MSG_PT_DYNAMIC, MSG_PT_INTERP, 45 MSG_PT_NOTE, MSG_PT_SHLIB, 46 MSG_PT_PHDR, MSG_PT_TLS 47 }; 48 static const Msg phdrs_dmp[] = { 49 MSG_PT_NULL_CFNP, MSG_PT_LOAD_CFNP, 50 MSG_PT_DYNAMIC_DMP, MSG_PT_INTERP_CFNP, 51 MSG_PT_NOTE_CFNP, MSG_PT_SHLIB_CFNP, 52 MSG_PT_PHDR_CFNP, MSG_PT_TLS_CFNP 53 }; 54 static const Msg phdrs_cf[] = { 55 MSG_PT_NULL_CF, MSG_PT_LOAD_CF, 56 MSG_PT_DYNAMIC_CF, MSG_PT_INTERP_CF, 57 MSG_PT_NOTE_CF, MSG_PT_SHLIB_CF, 58 MSG_PT_PHDR_CF, MSG_PT_TLS_CF 59 }; 60 static const Msg phdrs_cfnp[] = { 61 MSG_PT_NULL_CFNP, MSG_PT_LOAD_CFNP, 62 MSG_PT_DYNAMIC_CFNP, MSG_PT_INTERP_CFNP, 63 MSG_PT_NOTE_CFNP, MSG_PT_SHLIB_CFNP, 64 MSG_PT_PHDR_CFNP, MSG_PT_TLS_CFNP 65 }; 66 static const Msg phdrs_nf[] = { 67 MSG_PT_NULL_NF, MSG_PT_LOAD_NF, 68 MSG_PT_DYNAMIC_NF, MSG_PT_INTERP_NF, 69 MSG_PT_NOTE_NF, MSG_PT_SHLIB_NF, 70 MSG_PT_PHDR_NF, MSG_PT_TLS_NF 71 }; 72 #if PT_NUM != (PT_TLS + 1) 73 error "PT_NUM has grown. Update phdrs[]" 74 #endif 75 static const conv_ds_msg_t ds_phdrs_def = { 76 CONV_DS_MSG_INIT(PT_NULL, phdrs_def) }; 77 static const conv_ds_msg_t ds_phdrs_dmp = { 78 CONV_DS_MSG_INIT(PT_NULL, phdrs_dmp) }; 79 static const conv_ds_msg_t ds_phdrs_cf = { 80 CONV_DS_MSG_INIT(PT_NULL, phdrs_cf) }; 81 static const conv_ds_msg_t ds_phdrs_cfnp = { 82 CONV_DS_MSG_INIT(PT_NULL, phdrs_cfnp) }; 83 static const conv_ds_msg_t ds_phdrs_nf = { 84 CONV_DS_MSG_INIT(PT_NULL, phdrs_nf) }; 85 86 87 static const Val_desc2 phdrs_osabi_def[] = { 88 { PT_SUNWBSS, SOL, MSG_PT_SUNWBSS }, 89 { PT_SUNWSTACK, SOL, MSG_PT_SUNWSTACK }, 90 { PT_SUNWDTRACE, SOL, MSG_PT_SUNWDTRACE }, 91 { PT_SUNWCAP, SOL, MSG_PT_SUNWCAP }, 92 { PT_SUNW_UNWIND, SOL, MSG_PT_SUNW_UNWIND }, 93 { PT_SUNW_EH_FRAME, SOL, MSG_PT_SUNW_EH_FRAME }, 94 95 { PT_GNU_EH_FRAME, LIN, MSG_PT_GNU_EH_FRAME }, 96 { PT_GNU_STACK, LIN, MSG_PT_GNU_STACK }, 97 { PT_GNU_RELRO, LIN, MSG_PT_GNU_RELRO }, 98 99 { 0 } 100 }; 101 static const Val_desc2 phdrs_osabi_cf[] = { 102 { PT_SUNWBSS, SOL, MSG_PT_SUNWBSS_CF }, 103 { PT_SUNWSTACK, SOL, MSG_PT_SUNWSTACK_CF }, 104 { PT_SUNWDTRACE, SOL, MSG_PT_SUNWDTRACE_CF }, 105 { PT_SUNWCAP, SOL, MSG_PT_SUNWCAP_CF }, 106 { PT_SUNW_UNWIND, SOL, MSG_PT_SUNW_UNWIND_CF }, 107 { PT_SUNW_EH_FRAME, SOL, MSG_PT_SUNW_EH_FRAME_CF }, 108 109 { PT_GNU_EH_FRAME, LIN, MSG_PT_GNU_EH_FRAME_CF }, 110 { PT_GNU_STACK, LIN, MSG_PT_GNU_STACK_CF }, 111 { PT_GNU_RELRO, LIN, MSG_PT_GNU_RELRO_CF }, 112 113 { 0 } 114 }; 115 static const Val_desc2 phdrs_osabi_cfnp[] = { 116 { PT_SUNWBSS, SOL, MSG_PT_SUNWBSS_CFNP }, 117 { PT_SUNWSTACK, SOL, MSG_PT_SUNWSTACK_CFNP }, 118 { PT_SUNWDTRACE, SOL, MSG_PT_SUNWDTRACE_CFNP }, 119 { PT_SUNWCAP, SOL, MSG_PT_SUNWCAP_CFNP }, 120 { PT_SUNW_UNWIND, SOL, MSG_PT_SUNW_UNWIND_CFNP }, 121 { PT_SUNW_EH_FRAME, SOL, MSG_PT_SUNW_EH_FRAME_CFNP }, 122 123 { PT_GNU_EH_FRAME, LIN, MSG_PT_GNU_EH_FRAME_CFNP }, 124 { PT_GNU_STACK, LIN, MSG_PT_GNU_STACK_CFNP }, 125 { PT_GNU_RELRO, LIN, MSG_PT_GNU_RELRO_CFNP }, 126 127 { 0 } 128 }; 129 static const Val_desc2 phdrs_osabi_nf[] = { 130 { PT_SUNWBSS, SOL, MSG_PT_SUNWBSS_NF }, 131 { PT_SUNWSTACK, SOL, MSG_PT_SUNWSTACK_NF }, 132 { PT_SUNWDTRACE, SOL, MSG_PT_SUNWDTRACE_NF }, 133 { PT_SUNWCAP, SOL, MSG_PT_SUNWCAP_NF }, 134 { PT_SUNW_UNWIND, SOL, MSG_PT_SUNW_UNWIND_NF }, 135 { PT_SUNW_EH_FRAME, SOL, MSG_PT_SUNW_EH_FRAME_NF }, 136 137 { PT_GNU_EH_FRAME, LIN, MSG_PT_GNU_EH_FRAME_NF }, 138 { PT_GNU_STACK, LIN, MSG_PT_GNU_STACK_NF }, 139 { PT_GNU_RELRO, LIN, MSG_PT_GNU_RELRO_NF }, 140 141 { 0 } 142 }; 143 #if PT_LOSUNW != PT_SUNWBSS 144 #error "PT_LOSUNW has grown. Update phdrs_osabi[]" 145 #endif 146 static const conv_ds_vd2_t ds_phdrs_osabi_def = { 147 CONV_DS_VD2, PT_LOOS, PT_HIOS, phdrs_osabi_def }; 148 static const conv_ds_vd2_t ds_phdrs_osabi_cf = { 149 CONV_DS_VD2, PT_LOOS, PT_HIOS, phdrs_osabi_cf }; 150 static const conv_ds_vd2_t ds_phdrs_osabi_cfnp = { 151 CONV_DS_VD2, PT_LOOS, PT_HIOS, phdrs_osabi_cfnp }; 152 static const conv_ds_vd2_t ds_phdrs_osabi_nf = { 153 CONV_DS_VD2, PT_LOOS, PT_HIOS, phdrs_osabi_nf }; 154 155 156 /* Build NULL terminated return arrays for each string style */ 157 static const conv_ds_t *ds_def[] = { 158 CONV_DS_ADDR(ds_phdrs_def), CONV_DS_ADDR(ds_phdrs_osabi_def), 159 NULL }; 160 static const conv_ds_t *ds_dmp[] = { 161 CONV_DS_ADDR(ds_phdrs_dmp), CONV_DS_ADDR(ds_phdrs_osabi_cfnp), 162 NULL }; 163 static const conv_ds_t *ds_cf[] = { 164 CONV_DS_ADDR(ds_phdrs_cf), CONV_DS_ADDR(ds_phdrs_osabi_cf), 165 NULL }; 166 static const conv_ds_t *ds_cfnp[] = { 167 CONV_DS_ADDR(ds_phdrs_cfnp), CONV_DS_ADDR(ds_phdrs_osabi_cfnp), 168 NULL }; 169 static const conv_ds_t *ds_nf[] = { 170 CONV_DS_ADDR(ds_phdrs_nf), CONV_DS_ADDR(ds_phdrs_osabi_nf), 171 NULL }; 172 173 /* Select the strings to use */ 174 switch (CONV_TYPE_FMT_ALT(fmt_flags)) { 175 case CONV_FMT_ALT_DUMP: 176 return (ds_dmp); 177 case CONV_FMT_ALT_CF: 178 return (ds_cf); 179 case CONV_FMT_ALT_CFNP: 180 return (ds_cfnp); 181 case CONV_FMT_ALT_NF: 182 return (ds_nf); 183 } 184 185 return (ds_def); 186 187 #undef ALL 188 #undef SOL 189 #undef LIN 190 } 191 192 const char * 193 conv_phdr_type(uchar_t osabi, Half mach, Word type, Conv_fmt_flags_t fmt_flags, 194 Conv_inv_buf_t *inv_buf) 195 { 196 return (conv_map_ds(osabi, mach, type, 197 conv_phdr_type_strings(fmt_flags), fmt_flags, inv_buf)); 198 } 199 200 conv_iter_ret_t 201 conv_iter_phdr_type(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags, 202 conv_iter_cb_t func, void *uvalue) 203 { 204 return (conv_iter_ds(osabi, EM_NONE, 205 conv_phdr_type_strings(fmt_flags), func, uvalue)); 206 } 207 208 209 static const Val_desc2 * 210 conv_phdr_flags_strings(Conv_fmt_flags_t fmt_flags) 211 { 212 /* The CF style has the longest strings */ 213 #define PHDRSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 214 MSG_PF_X_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 215 MSG_PF_W_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 216 MSG_PF_R_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 217 MSG_PF_SUNW_FAILURE_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 218 MSG_PF_SUNW_KILLED_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 219 MSG_PF_SUNW_SIGINFO_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 220 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 221 222 /* 223 * Ensure that Conv_phdr_flags_buf_t is large enough: 224 * 225 * PHDRSZ is the real minimum size of the buffer required by 226 * conv_phdr_flags(). However, Conv_phdr_flags_buf_t uses 227 * CONV_PHDR_FLAGS_BUFSIZE to set the buffer size. We do things this 228 * way because the definition of PHDRSZ uses information that is not 229 * available in the environment of other programs that include the 230 * conv.h header file. 231 */ 232 #if (CONV_PHDR_FLAGS_BUFSIZE != PHDRSZ) && !defined(__lint) 233 #define REPORT_BUFSIZE PHDRSZ 234 #include "report_bufsize.h" 235 #error "CONV_PHDR_FLAGS_BUFSIZE does not match PHDRSZ" 236 #endif 237 238 #define ALL ELFOSABI_NONE, EM_NONE 239 #define SOL ELFOSABI_SOLARIS, EM_NONE 240 241 static const Val_desc2 vda_cf[] = { 242 { PF_X, ALL, MSG_PF_X_CF }, 243 { PF_W, ALL, MSG_PF_W_CF }, 244 { PF_R, ALL, MSG_PF_R_CF }, 245 { PF_SUNW_FAILURE, SOL, MSG_PF_SUNW_FAILURE_CF }, 246 { PF_SUNW_KILLED, SOL, MSG_PF_SUNW_KILLED_CF }, 247 { PF_SUNW_SIGINFO, SOL, MSG_PF_SUNW_SIGINFO_CF }, 248 { 0 } 249 }; 250 static const Val_desc2 vda_nf[] = { 251 { PF_X, ALL, MSG_PF_X_NF }, 252 { PF_W, ALL, MSG_PF_W_NF }, 253 { PF_R, ALL, MSG_PF_R_NF }, 254 { PF_SUNW_FAILURE, SOL, MSG_PF_SUNW_FAILURE_NF }, 255 { PF_SUNW_KILLED, SOL, MSG_PF_SUNW_KILLED_NF }, 256 { PF_SUNW_SIGINFO, SOL, MSG_PF_SUNW_SIGINFO_NF }, 257 { 0 } 258 }; 259 260 return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ? 261 vda_nf : vda_cf); 262 263 #undef ALL 264 #undef SOL 265 } 266 267 const char * 268 conv_phdr_flags(uchar_t osabi, Word flags, Conv_fmt_flags_t fmt_flags, 269 Conv_phdr_flags_buf_t *phdr_flags_buf) 270 { 271 static CONV_EXPN_FIELD_ARG conv_arg = { 272 NULL, sizeof (phdr_flags_buf->buf) }; 273 274 if (flags == 0) 275 return (MSG_ORIG(MSG_GBL_ZERO)); 276 277 conv_arg.buf = phdr_flags_buf->buf; 278 conv_arg.oflags = conv_arg.rflags = flags; 279 (void) conv_expn_field2(&conv_arg, osabi, EM_NONE, 280 conv_phdr_flags_strings(fmt_flags), fmt_flags); 281 282 return ((const char *)phdr_flags_buf->buf); 283 } 284 285 conv_iter_ret_t 286 conv_iter_phdr_flags(conv_iter_osabi_t osabi, Conv_fmt_flags_t fmt_flags, 287 conv_iter_cb_t func, void *uvalue) 288 { 289 if (conv_iter_vd2(osabi, EM_NONE, 290 conv_phdr_flags_strings(fmt_flags), 291 func, uvalue) == CONV_ITER_DONE) 292 return (CONV_ITER_DONE); 293 294 return (CONV_ITER_CONT); 295 } 296