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 #include <stdio.h> 28 #include <strings.h> 29 #include <_machelf.h> 30 #include "_conv.h" 31 #include "globals_msg.h" 32 33 34 /* 35 * Map an integer into a descriptive string. 36 * 37 * entry: 38 * inv_buf - A buffer into which this routine can format 39 * a result string, if necessary. 40 * val - The value for which a string is desired. 41 * flags - CONV_FMT_* values to be passed to conv_invalid_val() if 42 * necessary. The caller is reponsible for having examined 43 * the CONV_FMT_ALT_* part of flags and passing the proper 44 * msg array. 45 * num_msg - # of Msg entries in msg. 46 * msg - Array of num_msg Msg items corresponding to the possible 47 * strings corresponding to val. 48 * local_sgs_msg - Message string table from module from which 49 * this function is called. 50 * 51 * exit: 52 * If val lies in the range [0-(num_msg-1)], then the string 53 * corresponding to it is returned. If val is outside the range, 54 * conv_invalid_val() is called to format an ASCII representation 55 * of it into inv_buf, and that is returned. 56 */ 57 /*ARGSUSED5*/ 58 static const char * 59 map_msg2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val, 60 Conv_fmt_flags_t flags, size_t num_msg, const Msg *msg, 61 const char *local_sgs_msg) 62 { 63 if ((val < num_msg) && (msg[val] != 0)) 64 return (MSG_ORIG_STRTAB(msg[val], local_sgs_msg)); 65 66 /* If we get here, it's an unknown value */ 67 return (conv_invalid_val(inv_buf, val, flags)); 68 } 69 70 /* 71 * Map an integer into a descriptive string from a NULL terminated 72 * array of Val_desc or Val_desc2 descriptors. 73 * 74 * entry: 75 * inv_buf - A buffer into which this routine can format 76 * a result string, if necessary. 77 * osabi,mach (_conv_vd22str only) - The osab/mach under which 78 * val is to be interpreted. Items with a non-0 osabi or machine 79 * that do not match are quietly ignored. 80 * val - The value for which a string is desired. 81 * flags - CONV_FMT_* values to be passed to conv_invalid_val() if 82 * necessary. The caller is reponsible for having examined 83 * the CONV_FMT_ALT_* part of flags and passing the proper 84 * descriptor array. 85 * vdp - Pointer to NULL terminated array of Val_desc descriptors. 86 * local_sgs_msg - Message string table from module from which 87 * this function is called. 88 * 89 * exit: 90 * If val is found in the vdp array, and in the osabi version of 91 * this function if the osabi matches, then the string corresponding 92 * val is returned. If a string for val is not found, conv_invalid_val() 93 * is called to format an ASCII representation of it into inv_buf, and 94 * that is returned. 95 */ 96 /*ARGSUSED4*/ 97 static const char * 98 map_vd2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val, 99 Conv_fmt_flags_t flags, const Val_desc *vdp, const char *local_sgs_msg) 100 { 101 for (; vdp->v_msg; vdp++) { 102 if (val == vdp->v_val) 103 return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg)); 104 } 105 106 /* If we get here, it's an unknown value */ 107 return (conv_invalid_val(inv_buf, val, flags)); 108 } 109 110 /*ARGSUSED6*/ 111 static const char * 112 map_vd22str(Conv_inv_buf_t *inv_buf, uchar_t osabi, Half mach, 113 Conv_elfvalue_t val, Conv_fmt_flags_t flags, const Val_desc2 *vdp, 114 const char *local_sgs_msg) 115 { 116 for (; vdp->v_msg; vdp++) { 117 if (CONV_VD2_SKIP(osabi, mach, vdp)) 118 continue; 119 120 if (val == vdp->v_val) 121 return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg)); 122 } 123 124 /* If we get here, it's an unknown value */ 125 return (conv_invalid_val(inv_buf, val, flags)); 126 } 127 128 /* 129 * Process an array of conv_ds_XXX_t structures and call the appropriate 130 * map functions for the format of the strings given. 131 */ 132 const char * 133 _conv_map_ds(uchar_t osabi, Half mach, Conv_elfvalue_t value, 134 const conv_ds_t **dsp, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf, 135 const char *local_sgs_msg) 136 { 137 const conv_ds_t *ds; 138 139 for (ds = *dsp; ds != NULL; ds = *(++dsp)) { 140 if ((value < ds->ds_baseval) || (value > ds->ds_topval)) 141 continue; 142 143 switch (ds->ds_type) { 144 case CONV_DS_MSGARR: 145 return (map_msg2str(inv_buf, value - ds->ds_baseval, 146 fmt_flags, ds->ds_topval - ds->ds_baseval + 1, 147 /*LINTED*/ 148 ((conv_ds_msg_t *)ds)->ds_msg, 149 local_sgs_msg)); 150 151 case CONV_DS_VD: 152 return (map_vd2str(inv_buf, value, fmt_flags, 153 /*LINTED*/ 154 ((conv_ds_vd_t *)ds)->ds_vd, 155 local_sgs_msg)); 156 157 case CONV_DS_VD2: 158 return (map_vd22str(inv_buf, osabi, mach, value, 159 fmt_flags, 160 /*LINTED*/ 161 ((conv_ds_vd2_t *)ds)->ds_vd2, 162 local_sgs_msg)); 163 } 164 } 165 166 return (conv_invalid_val(inv_buf, value, fmt_flags)); 167 } 168 169 /* 170 * Iterate over every message string in a given array of Msg codes, 171 * calling a user supplied callback for each one. 172 * 173 * entry: 174 * basevalue - Value corresponding to the first Msg in the array. 175 * local_sgs_msg - Pointer to the __sgs_msg array for the 176 * libconv module making the call. 177 * num_msg - # of items in array referenced by msg 178 * msg - Array of Msg indexes for the strings to iterate over. 179 * The value corresponding to each element of msg must be: 180 * value[i] = basevalue + i 181 * func, uvalue - User supplied function to be called for each 182 * string in msg. uvalue is an arbitrary user supplied pointer 183 * to be passed to func. 184 * local_sgs_msg - Pointer to the __sgs_msg array for the 185 * libconv module making the call. 186 * 187 * exit: 188 * The callback function is called for every non-zero item in 189 * msg[]. If any callback returns CONV_ITER_DONE, execution stops 190 * with that item and the function returns immediately. Otherwise, 191 * it continues to the end of the array. 192 * 193 * The value from the last callback is returned. 194 */ 195 /*ARGSUSED5*/ 196 static conv_iter_ret_t 197 _conv_iter_msgarr(uint32_t basevalue, const Msg *msg, size_t num_msg, 198 conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg) 199 { 200 for (; num_msg-- > 0; basevalue++, msg++) { 201 if (*msg != 0) 202 if ((* func)(MSG_ORIG_STRTAB(*msg, local_sgs_msg), 203 basevalue, uvalue) == CONV_ITER_DONE) 204 return (CONV_ITER_DONE); 205 } 206 207 return (CONV_ITER_CONT); 208 } 209 210 /* 211 * Iterate over every message string in a given array of Val_desc or 212 * Val_desc2 descriptors, calling a user supplied callback for each one. 213 * 214 * entry: 215 * osabi,mach (_conv_iter_vd2 only) - The osabi/mach for which 216 * strings are desired. Strings with a non-0 osabi or machine 217 * that do not match are quietly ignored. 218 * vdp - Pointer to NULL terminated array of Val_desc descriptors. 219 * func, uvalue - User supplied function to be called for each 220 * string in msg. uvalue is an arbitrary user supplied pointer 221 * to be passed to func. 222 * local_sgs_msg - Pointer to the __sgs_msg array for the 223 * libconv module making the call. 224 * 225 * exit: 226 * The callback function is called for every descriptor referenced by 227 * vdp. In the case of the OSABI-version of this function, strings from 228 * the wrong osabi are not used. If any callback returns CONV_ITER_DONE, 229 * execution stops with that item and the function returns immediately. 230 * Otherwise, it continues to the end of the array. 231 * 232 * The value from the last callback is returned. 233 */ 234 /*ARGSUSED3*/ 235 conv_iter_ret_t 236 _conv_iter_vd(const Val_desc *vdp, conv_iter_cb_t func, void *uvalue, 237 const char *local_sgs_msg) 238 { 239 for (; vdp->v_msg; vdp++) { 240 if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg), 241 vdp->v_val, uvalue) == CONV_ITER_DONE) 242 return (CONV_ITER_DONE); 243 } 244 245 return (CONV_ITER_CONT); 246 } 247 248 /*ARGSUSED5*/ 249 conv_iter_ret_t 250 _conv_iter_vd2(conv_iter_osabi_t osabi, Half mach, const Val_desc2 *vdp, 251 conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg) 252 { 253 for (; vdp->v_msg; vdp++) { 254 if (CONV_ITER_VD2_SKIP(osabi, mach, vdp)) 255 continue; 256 257 if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg), 258 vdp->v_val, uvalue) == CONV_ITER_DONE) 259 return (CONV_ITER_DONE); 260 } 261 262 return (CONV_ITER_CONT); 263 } 264 265 /* 266 * Process an array of conv_ds_XXX_t structures and call the appropriate 267 * iteration functions for the format of the strings given. 268 */ 269 conv_iter_ret_t 270 _conv_iter_ds(conv_iter_osabi_t osabi, Half mach, const conv_ds_t **dsp, 271 conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg) 272 { 273 const conv_ds_t *ds; 274 275 for (ds = *dsp; ds != NULL; ds = *(++dsp)) { 276 switch (ds->ds_type) { 277 case CONV_DS_MSGARR: 278 if (_conv_iter_msgarr(ds->ds_baseval, 279 /*LINTED*/ 280 ((conv_ds_msg_t *)ds)->ds_msg, 281 ds->ds_topval - ds->ds_baseval + 1, func, uvalue, 282 local_sgs_msg) == CONV_ITER_DONE) 283 return (CONV_ITER_DONE); 284 break; 285 286 case CONV_DS_VD: 287 /*LINTED*/ 288 if (_conv_iter_vd(((conv_ds_vd_t *)ds)->ds_vd, 289 func, uvalue, local_sgs_msg) == CONV_ITER_DONE) 290 return (CONV_ITER_DONE); 291 break; 292 293 case CONV_DS_VD2: 294 if (_conv_iter_vd2(osabi, mach, 295 /*LINTED*/ 296 ((conv_ds_vd2_t *)ds)->ds_vd2, 297 func, uvalue, local_sgs_msg) == CONV_ITER_DONE) 298 return (CONV_ITER_DONE); 299 break; 300 } 301 } 302 303 return (CONV_ITER_CONT); 304 } 305 306 /* 307 * Initialize the uvalue block prior to use of an interation function 308 * employing conv_iter_strtol(). 309 * 310 * entry: 311 * str - String to be matched to a value 312 * uvalue - Pointer to uninitialized uvalue block 313 * 314 * exit: 315 * Initializes the uvalue block for use. Returns True (1) if a non-empty 316 * string was supplied, and False (0). 317 */ 318 int 319 conv_iter_strtol_init(const char *str, conv_strtol_uvalue_t *uvalue) 320 { 321 const char *tail; 322 323 while (conv_strproc_isspace(*str)) 324 str++; 325 uvalue->csl_str = str; 326 uvalue->csl_found = 0; 327 328 tail = str + strlen(str); 329 while ((tail > str) && conv_strproc_isspace(*(tail - 1))) 330 tail--; 331 uvalue->csl_strlen = tail - str; 332 333 return (uvalue->csl_strlen > 0); 334 } 335 336 /* 337 * conv_iter_strtol() is used with iteration functions to map a string 338 * to the value of its corresponding ELF constant. 339 * 340 * entry: 341 * str - String supplied by this iteration 342 * value - Value of ELF constant corresponding to str 343 * uvalue - Pointer to conv_strtol_uvalue_t block previously 344 * initialized by a call to conv_iter_strtol_init(). 345 */ 346 conv_iter_ret_t 347 conv_iter_strtol(const char *str, uint32_t value, void *uvalue) 348 { 349 conv_strtol_uvalue_t *state = (conv_strtol_uvalue_t *)uvalue; 350 351 if ((strlen(str) == state->csl_strlen) && 352 (strncasecmp(str, state->csl_str, state->csl_strlen) == 0)) { 353 state->csl_found = 1; 354 state->csl_value = value; 355 return (CONV_ITER_DONE); /* Found it. Stop now. */ 356 } 357 358 return (CONV_ITER_CONT); /* Keep looking */ 359 } 360