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