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 routine for .dynamic tag entries. 30 */ 31 #include <stdio.h> 32 #include <string.h> 33 #include <sys/elf_SPARC.h> 34 #include "rtld.h" 35 #include "_conv.h" 36 #include "dynamic_msg.h" 37 38 39 40 /* Instantiate a local copy of conv_map2str() from _conv.h */ 41 DEFINE_conv_map2str 42 43 44 45 #define POSSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 46 MSG_DFP_LAZYLOAD_ALT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 47 MSG_DFP_GROUPPERM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 48 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 49 50 /* 51 * Ensure that Conv_dyn_posflag1_buf_t is large enough: 52 * 53 * POSSZ is the real minimum size of the buffer required by conv_dyn_posflag1(). 54 * However, Conv_dyn_posflag1_buf_t uses CONV_DYN_POSFLAG1_BUFSIZE to set the 55 * buffer size. We do things this way because the definition of POSSZ uses 56 * information that is not available in the environment of other programs 57 * that include the conv.h header file. 58 */ 59 #if CONV_DYN_POSFLAG1_BUFSIZE < POSSZ 60 #error "CONV_DYN_POSFLAG1_BUFSIZE is not large enough" 61 #endif 62 63 const char * 64 conv_dyn_posflag1(Xword flags, int fmt_flags, 65 Conv_dyn_posflag1_buf_t *dyn_posflag1_buf) 66 { 67 static Val_desc vda[] = { 68 { DF_P1_LAZYLOAD, MSG_ORIG(MSG_DFP_LAZYLOAD) }, 69 { DF_P1_GROUPPERM, MSG_ORIG(MSG_DFP_GROUPPERM) }, 70 { 0, 0 } 71 }; 72 static CONV_EXPN_FIELD_ARG conv_arg = { 73 NULL, sizeof (dyn_posflag1_buf->buf), vda }; 74 static Val_desc vda_alt[] = { 75 { DF_P1_LAZYLOAD, MSG_ORIG(MSG_DFP_LAZYLOAD_ALT) }, 76 { DF_P1_GROUPPERM, MSG_ORIG(MSG_DFP_GROUPPERM) }, 77 { 0, 0 } 78 }; 79 static CONV_EXPN_FIELD_ARG conv_arg_alt = { 80 NULL, sizeof (dyn_posflag1_buf->buf), vda_alt, NULL, 0, 0, 81 MSG_ORIG(MSG_STR_EMPTY), NULL, MSG_ORIG(MSG_STR_EMPTY) }; 82 83 CONV_EXPN_FIELD_ARG *arg; 84 85 if (flags == 0) 86 return (MSG_ORIG(MSG_GBL_ZERO)); 87 88 arg = (fmt_flags & CONV_FMT_ALTDUMP) ? &conv_arg_alt : &conv_arg; 89 arg->buf = dyn_posflag1_buf->buf; 90 arg->oflags = arg->rflags = flags; 91 (void) conv_expn_field(arg); 92 93 return ((const char *)dyn_posflag1_buf); 94 } 95 96 #define FLAGSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 97 MSG_DF_ORIGIN_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 98 MSG_DF_SYMBOLIC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 99 MSG_DF_TEXTREL_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 100 MSG_DF_BIND_NOW_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 101 MSG_DF_STATIC_TLS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 102 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 103 104 /* 105 * Ensure that Conv_dyn_flag_buf_t is large enough: 106 * 107 * FLAGSZ is the real minimum size of the buffer required by conv_dyn_flag(). 108 * However, Conv_dyn_flag_buf_t uses CONV_DYN_FLAG_BUFSIZE to set the 109 * buffer size. We do things this way because the definition of FLAGSZ uses 110 * information that is not available in the environment of other programs 111 * that include the conv.h header file. 112 */ 113 #if CONV_DYN_FLAG_BUFSIZE < FLAGSZ 114 #error "CONV_DYN_FLAG_BUFSIZE is not large enough" 115 #endif 116 117 const char * 118 conv_dyn_flag(Xword flags, int fmt_flags, Conv_dyn_flag_buf_t *dyn_flag_buf) 119 { 120 static Val_desc vda[] = { 121 { DF_ORIGIN, MSG_ORIG(MSG_DF_ORIGIN) }, 122 { DF_SYMBOLIC, MSG_ORIG(MSG_DF_SYMBOLIC) }, 123 { DF_TEXTREL, MSG_ORIG(MSG_DF_TEXTREL) }, 124 { DF_BIND_NOW, MSG_ORIG(MSG_DF_BIND_NOW) }, 125 { DF_STATIC_TLS, MSG_ORIG(MSG_DF_STATIC_TLS) }, 126 { 0, 0 } 127 }; 128 static CONV_EXPN_FIELD_ARG conv_arg = { 129 NULL, sizeof (dyn_flag_buf->buf), vda }; 130 131 if (flags == 0) 132 return (MSG_ORIG(MSG_GBL_ZERO)); 133 134 conv_arg.buf = dyn_flag_buf->buf; 135 conv_arg.oflags = conv_arg.rflags = flags; 136 if (fmt_flags & CONV_FMT_ALTDUMP) { 137 conv_arg.prefix = conv_arg.suffix = MSG_ORIG(MSG_STR_EMPTY); 138 } else { 139 conv_arg.prefix = conv_arg.suffix = NULL; 140 } 141 (void) conv_expn_field(&conv_arg); 142 143 return ((const char *)dyn_flag_buf->buf); 144 } 145 146 #define FLAG1SZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 147 MSG_DF1_NOW_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 148 MSG_DF1_GLOBAL_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 149 MSG_DF1_GROUP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 150 MSG_DF1_NODELETE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 151 MSG_DF1_LOADFLTR_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 152 MSG_DF1_INITFIRST_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 153 MSG_DF1_NOOPEN_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 154 MSG_DF1_ORIGIN_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 155 MSG_DF1_DIRECT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 156 MSG_DF1_TRANS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 157 MSG_DF1_INTERPOSE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 158 MSG_DF1_NODEFLIB_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 159 MSG_DF1_NODUMP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 160 MSG_DF1_CONFALT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 161 MSG_DF1_ENDFILTEE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 162 MSG_DF1_DISPRELPND_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 163 MSG_DF1_DISPRELDNE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 164 MSG_DF1_NODIRECT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 165 MSG_DF1_IGNMULDEF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 166 MSG_DF1_NOKSYMS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 167 MSG_DF1_NOHDR_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 168 MSG_DF1_NORELOC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 169 MSG_DF1_SYMINTPOSE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 170 MSG_DF1_GLOBAUDIT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 171 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 172 173 /* 174 * Ensure that Conv_dyn_flag1_buf_t is large enough: 175 * 176 * FLAG1SZ is the real minimum size of the buffer required by conv_dyn_flag1(). 177 * However, Conv_dyn_flag1_buf_t uses CONV_DYN_FLAG1_BUFSIZE to set the 178 * buffer size. We do things this way because the definition of FLAG1SZ uses 179 * information that is not available in the environment of other programs 180 * that include the conv.h header file. 181 */ 182 #if CONV_DYN_FLAG1_BUFSIZE < FLAG1SZ 183 #error "CONV_DYN_FLAG1_BUFSIZE is not large enough" 184 #endif 185 186 const char * 187 conv_dyn_flag1(Xword flags, Conv_dyn_flag1_buf_t *dyn_flag1_buf) 188 { 189 static Val_desc vda[] = { 190 { DF_1_NOW, MSG_ORIG(MSG_DF1_NOW) }, 191 { DF_1_GLOBAL, MSG_ORIG(MSG_DF1_GLOBAL) }, 192 { DF_1_GROUP, MSG_ORIG(MSG_DF1_GROUP) }, 193 { DF_1_NODELETE, MSG_ORIG(MSG_DF1_NODELETE) }, 194 { DF_1_LOADFLTR, MSG_ORIG(MSG_DF1_LOADFLTR) }, 195 { DF_1_INITFIRST, MSG_ORIG(MSG_DF1_INITFIRST) }, 196 { DF_1_NOOPEN, MSG_ORIG(MSG_DF1_NOOPEN) }, 197 { DF_1_ORIGIN, MSG_ORIG(MSG_DF1_ORIGIN) }, 198 { DF_1_DIRECT, MSG_ORIG(MSG_DF1_DIRECT) }, 199 { DF_1_TRANS, MSG_ORIG(MSG_DF1_TRANS) }, 200 { DF_1_INTERPOSE, MSG_ORIG(MSG_DF1_INTERPOSE) }, 201 { DF_1_NODEFLIB, MSG_ORIG(MSG_DF1_NODEFLIB) }, 202 { DF_1_NODUMP, MSG_ORIG(MSG_DF1_NODUMP) }, 203 { DF_1_CONFALT, MSG_ORIG(MSG_DF1_CONFALT) }, 204 { DF_1_ENDFILTEE, MSG_ORIG(MSG_DF1_ENDFILTEE) }, 205 { DF_1_DISPRELDNE, MSG_ORIG(MSG_DF1_DISPRELDNE) }, 206 { DF_1_DISPRELPND, MSG_ORIG(MSG_DF1_DISPRELPND) }, 207 { DF_1_NODIRECT, MSG_ORIG(MSG_DF1_NODIRECT) }, 208 { DF_1_IGNMULDEF, MSG_ORIG(MSG_DF1_IGNMULDEF) }, 209 { DF_1_NOKSYMS, MSG_ORIG(MSG_DF1_NOKSYMS) }, 210 { DF_1_NOHDR, MSG_ORIG(MSG_DF1_NOHDR) }, 211 { DF_1_EDITED, MSG_ORIG(MSG_DF1_EDITED) }, 212 { DF_1_NORELOC, MSG_ORIG(MSG_DF1_NORELOC) }, 213 { DF_1_SYMINTPOSE, MSG_ORIG(MSG_DF1_SYMINTPOSE) }, 214 { DF_1_GLOBAUDIT, MSG_ORIG(MSG_DF1_GLOBAUDIT) }, 215 { 0, 0 } 216 }; 217 static CONV_EXPN_FIELD_ARG conv_arg = { 218 NULL, sizeof (dyn_flag1_buf->buf), vda }; 219 220 if (flags == 0) 221 return (MSG_ORIG(MSG_GBL_ZERO)); 222 223 conv_arg.oflags = conv_arg.rflags = flags; 224 conv_arg.buf = dyn_flag1_buf->buf; 225 (void) conv_expn_field(&conv_arg); 226 227 return ((const char *)dyn_flag1_buf->buf); 228 } 229 230 #define FEATSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 231 MSG_DTF_PARINIT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 232 MSG_DTF_CONFEXP_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 233 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 234 235 /* 236 * Ensure that Conv_dyn_feature1_buf_t is large enough: 237 * 238 * FEATSZ is the real min size of the buffer required by conv_dyn_feature1(). 239 * However, Conv_dyn_feature1_buf_t uses CONV_DYN_FEATURE1_BUFSIZE to set the 240 * buffer size. We do things this way because the definition of FEATSZ uses 241 * information that is not available in the environment of other programs 242 * that include the conv.h header file. 243 */ 244 #if CONV_DYN_FEATURE1_BUFSIZE < FEATSZ 245 #error "CONV_DYN_FEATURE1_BUFSIZE is not large enough" 246 #endif 247 248 const char * 249 conv_dyn_feature1(Xword flags, int fmt_flags, 250 Conv_dyn_feature1_buf_t *dyn_feature1_buf) 251 { 252 static Val_desc vda[] = { 253 { DTF_1_PARINIT, MSG_ORIG(MSG_DTF_PARINIT) }, 254 { DTF_1_CONFEXP, MSG_ORIG(MSG_DTF_CONFEXP) }, 255 { 0, 0 } 256 }; 257 static CONV_EXPN_FIELD_ARG conv_arg = { 258 NULL, sizeof (dyn_feature1_buf->buf), vda }; 259 260 if (flags == 0) 261 return (MSG_ORIG(MSG_GBL_ZERO)); 262 263 conv_arg.buf = dyn_feature1_buf->buf; 264 conv_arg.oflags = conv_arg.rflags = flags; 265 if (fmt_flags & CONV_FMT_ALTDUMP) { 266 conv_arg.prefix = conv_arg.suffix = MSG_ORIG(MSG_STR_EMPTY); 267 } else { 268 conv_arg.prefix = conv_arg.suffix = NULL; 269 } 270 (void) conv_expn_field(&conv_arg); 271 272 return ((const char *)dyn_feature1_buf->buf); 273 } 274 275 const char * 276 conv_dyn_tag(Xword tag, Half mach, int fmt_flags, Conv_inv_buf_t *inv_buf) 277 { 278 /* 279 * Dynamic tag values are sparse, cover a wide range, and have 280 * holes. To handle this efficiently, we fall through a series 281 * of tests below, in increasing tag order, returning at the first 282 * match. 283 * 284 * If we fall all the way to the end, the tag is unknown, 285 * and its numeric value is printed. 286 */ 287 288 /* 289 * Most of the tag values are clustered in contiguous ranges. 290 * Each contiguous range of defined values is handled with 291 * an array that contains the message index corresponding to 292 * each value in that range. The DYN_RANGE macro checks the 293 * tag value against range of values starting at _start_tag. 294 * If there is a match, the index of the appropriate name is 295 * pulled from _array and returned to the caller. 296 */ 297 #define DYN_RANGE(_start_tag, _array) \ 298 if ((tag >= _start_tag) && (tag < (_start_tag + ARRAY_NELTS(_array)))) \ 299 return (MSG_ORIG(_array[tag - _start_tag])); 300 301 302 /* 303 * Generic dynamic tags: 304 * - Note hole between DT_FLAGS and DT_PREINIT_ARRAY 305 * - The first range has alternative names for dump, 306 * requiring a second array. 307 */ 308 static const Msg tags_null[] = { 309 MSG_DYN_NULL, MSG_DYN_NEEDED, 310 MSG_DYN_PLTRELSZ, MSG_DYN_PLTGOT, 311 MSG_DYN_HASH, MSG_DYN_STRTAB, 312 MSG_DYN_SYMTAB, MSG_DYN_RELA, 313 MSG_DYN_RELASZ, MSG_DYN_RELAENT, 314 MSG_DYN_STRSZ, MSG_DYN_SYMENT, 315 MSG_DYN_INIT, MSG_DYN_FINI, 316 MSG_DYN_SONAME, MSG_DYN_RPATH, 317 MSG_DYN_SYMBOLIC, MSG_DYN_REL, 318 MSG_DYN_RELSZ, MSG_DYN_RELENT, 319 MSG_DYN_PLTREL, MSG_DYN_DEBUG, 320 MSG_DYN_TEXTREL, MSG_DYN_JMPREL, 321 MSG_DYN_BIND_NOW, MSG_DYN_INIT_ARRAY, 322 MSG_DYN_FINI_ARRAY, MSG_DYN_INIT_ARRAYSZ, 323 MSG_DYN_FINI_ARRAYSZ, MSG_DYN_RUNPATH, 324 MSG_DYN_FLAGS 325 }; 326 static const Msg tags_null_alt[] = { 327 MSG_DYN_NULL, MSG_DYN_NEEDED, 328 MSG_DYN_PLTRELSZ_ALT, MSG_DYN_PLTGOT, 329 MSG_DYN_HASH, MSG_DYN_STRTAB, 330 MSG_DYN_SYMTAB, MSG_DYN_RELA, 331 MSG_DYN_RELASZ, MSG_DYN_RELAENT, 332 MSG_DYN_STRSZ, MSG_DYN_SYMENT, 333 MSG_DYN_INIT, MSG_DYN_FINI, 334 MSG_DYN_SONAME, MSG_DYN_RPATH, 335 MSG_DYN_SYMBOLIC_ALT, MSG_DYN_REL, 336 MSG_DYN_RELSZ, MSG_DYN_RELENT, 337 MSG_DYN_PLTREL, MSG_DYN_DEBUG, 338 MSG_DYN_TEXTREL, MSG_DYN_JMPREL, 339 MSG_DYN_BIND_NOW, MSG_DYN_INIT_ARRAY, 340 MSG_DYN_FINI_ARRAY, MSG_DYN_INIT_ARRAYSZ, 341 MSG_DYN_FINI_ARRAYSZ, MSG_DYN_RUNPATH, 342 MSG_DYN_FLAGS 343 }; 344 static const Msg tags_preinit_array[] = { 345 MSG_DYN_PREINIT_ARRAY, MSG_DYN_PREINIT_ARRAYSZ 346 }; 347 348 /* 349 * SUNW: DT_LOOS -> DT_HIOS range. Note hole between DT_SUNW_TLSSORTSZ 350 * and DT_SUNW_STRPAD. We handle DT_SUNW_STRPAD as a single value below. 351 */ 352 static const Msg tags_sunw_auxiliary[] = { 353 MSG_DYN_SUNW_AUXILIARY, MSG_DYN_SUNW_RTLDINF, 354 MSG_DYN_SUNW_FILTER, MSG_DYN_SUNW_CAP, 355 MSG_DYN_SUNW_SYMTAB, MSG_DYN_SUNW_SYMSZ, 356 MSG_DYN_SUNW_SORTENT, MSG_DYN_SUNW_SYMSORT, 357 MSG_DYN_SUNW_SYMSORTSZ, MSG_DYN_SUNW_TLSSORT, 358 MSG_DYN_SUNW_TLSSORTSZ 359 }; 360 361 /* 362 * SUNW: DT_VALRNGLO - DT_VALRNGHI range. 363 */ 364 static const Msg tags_checksum[] = { 365 MSG_DYN_CHECKSUM, MSG_DYN_PLTPADSZ, 366 MSG_DYN_MOVEENT, MSG_DYN_MOVESZ, 367 MSG_DYN_FEATURE_1, MSG_DYN_POSFLAG_1, 368 MSG_DYN_SYMINSZ, MSG_DYN_SYMINENT 369 }; 370 371 /* 372 * SUNW: DT_ADDRRNGLO - DT_ADDRRNGHI range. 373 */ 374 static const Msg tags_config[] = { 375 MSG_DYN_CONFIG, MSG_DYN_DEPAUDIT, 376 MSG_DYN_AUDIT, MSG_DYN_PLTPAD, 377 MSG_DYN_MOVETAB, MSG_DYN_SYMINFO 378 }; 379 380 /* 381 * SUNW: generic range. Note hole between DT_VERSYM and DT_RELACOUNT. 382 * We handle DT_VERSYM as a single value below. 383 */ 384 static const Msg tags_relacount[] = { 385 MSG_DYN_RELACOUNT, MSG_DYN_RELCOUNT, 386 MSG_DYN_FLAGS_1, MSG_DYN_VERDEF, 387 MSG_DYN_VERDEFNUM, MSG_DYN_VERNEED, 388 MSG_DYN_VERNEEDNUM 389 }; 390 391 /* 392 * DT_LOPROC - DT_HIPROC range. 393 */ 394 static const Msg tags_auxiliary[] = { 395 MSG_DYN_AUXILIARY, MSG_DYN_USED, 396 MSG_DYN_FILTER 397 }; 398 399 400 401 402 if (tag <= DT_FLAGS) 403 return (conv_map2str(inv_buf, tag, fmt_flags, 404 ARRAY_NELTS(tags_null), tags_null, tags_null_alt, NULL)); 405 DYN_RANGE(DT_PREINIT_ARRAY, tags_preinit_array); 406 DYN_RANGE(DT_SUNW_AUXILIARY, tags_sunw_auxiliary); 407 if (tag == DT_SUNW_STRPAD) 408 return (MSG_ORIG(MSG_DYN_SUNW_STRPAD)); 409 DYN_RANGE(DT_CHECKSUM, tags_checksum); 410 DYN_RANGE(DT_CONFIG, tags_config); 411 if (tag == DT_VERSYM) 412 return (MSG_ORIG(MSG_DYN_VERSYM)); 413 DYN_RANGE(DT_RELACOUNT, tags_relacount); 414 DYN_RANGE(DT_AUXILIARY, tags_auxiliary); 415 416 /* 417 * SUNW: machine specific range. 418 */ 419 if (((mach == EM_SPARC) || (mach == EM_SPARCV9) || 420 (mach == EM_SPARC32PLUS)) && (tag == DT_SPARC_REGISTER)) 421 /* this is so x86 can display a sparc binary */ 422 return (MSG_ORIG(MSG_DYN_REGISTER)); 423 424 if (tag == DT_DEPRECATED_SPARC_REGISTER) 425 return (MSG_ORIG(MSG_DYN_REGISTER)); 426 427 /* Unknown item */ 428 return (conv_invalid_val(inv_buf, tag, fmt_flags)); 429 430 #undef DYN_RANGE 431 } 432 433 #define BINDTSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 434 MSG_BND_NEEDED_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 435 MSG_BND_REFER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 436 MSG_BND_FILTER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 437 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 438 439 /* 440 * Ensure that Conv_bnd_type_buf_t is large enough: 441 * 442 * BINDTSZ is the real minimum size of the buffer required by conv_bnd_type(). 443 * However, Conv_bnd_type_buf_t uses CONV_BND_TYPE_BUFSIZE to set the 444 * buffer size. We do things this way because the definition of BINDTSZ uses 445 * information that is not available in the environment of other programs 446 * that include the conv.h header file. 447 */ 448 #if CONV_BND_TYPE_BUFSIZE < BINDTSZ 449 #error "CONV_BND_TYPE_BUFSIZE is not large enough" 450 #endif 451 452 const char * 453 conv_bnd_type(uint_t flags, Conv_bnd_type_buf_t *bnd_type_buf) 454 { 455 static Val_desc vda[] = { 456 { BND_NEEDED, MSG_ORIG(MSG_BND_NEEDED) }, 457 { BND_REFER, MSG_ORIG(MSG_BND_REFER) }, 458 { BND_FILTER, MSG_ORIG(MSG_BND_FILTER) }, 459 { 0, 0 } 460 }; 461 static CONV_EXPN_FIELD_ARG conv_arg = { 462 NULL, sizeof (bnd_type_buf->buf), vda }; 463 464 if (flags == 0) 465 return (MSG_ORIG(MSG_STR_EMPTY)); 466 467 conv_arg.buf = bnd_type_buf->buf; 468 conv_arg.oflags = conv_arg.rflags = flags; 469 (void) conv_expn_field(&conv_arg); 470 471 return ((const char *)bnd_type_buf->buf); 472 } 473 474 /* 475 * Note, conv_bnd_obj() is called with either: 476 * LML_FLG_OBJADDED (possibly with LML_FLG_OBJREEVAL added), or 477 * LML_FLG_OBJDELETED, or 478 * LML_FLG_ATEXIT. 479 */ 480 #define BINDOSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ 481 MSG_BND_ADDED_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 482 MSG_BND_REEVAL_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ 483 CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE 484 485 /* 486 * Ensure that Conv_bnd_obj_buf_t is large enough: 487 * 488 * BINDOSZ is the real minimum size of the buffer required by conv_bnd_obj(). 489 * However, Conv_bnd_obj_buf_t uses CONV_BND_OBJ_BUFSIZE to set the 490 * buffer size. We do things this way because the definition of BINDOSZ uses 491 * information that is not available in the environment of other programs 492 * that include the conv.h header file. 493 */ 494 #if CONV_BND_OBJ_BUFSIZE < BINDOSZ 495 #error "CONV_BND_OBJ_BUFSIZE is not large enough" 496 #endif 497 498 const char * 499 conv_bnd_obj(uint_t flags, Conv_bnd_obj_buf_t *bnd_obj_buf) 500 { 501 static Val_desc vda[] = { 502 { LML_FLG_OBJADDED, MSG_ORIG(MSG_BND_ADDED) }, 503 { LML_FLG_OBJREEVAL, MSG_ORIG(MSG_BND_REEVAL) }, 504 { LML_FLG_OBJDELETED, MSG_ORIG(MSG_BND_DELETED) }, 505 { LML_FLG_ATEXIT, MSG_ORIG(MSG_BND_ATEXIT) }, 506 { 0, 0 } 507 }; 508 static CONV_EXPN_FIELD_ARG conv_arg = { 509 NULL, sizeof (bnd_obj_buf->buf), vda }; 510 511 if ((flags & (LML_FLG_OBJADDED | LML_FLG_OBJREEVAL | 512 LML_FLG_OBJDELETED | LML_FLG_ATEXIT)) == 0) 513 return (MSG_ORIG(MSG_BND_REVISIT)); 514 515 /* 516 * Note, we're not worried about unknown flags for this family, only 517 * the selected flags are of interest, so we leave conv_arg.rflags 518 * set to 0. 519 */ 520 conv_arg.buf = bnd_obj_buf->buf; 521 conv_arg.oflags = flags; 522 (void) conv_expn_field(&conv_arg); 523 524 return ((const char *)bnd_obj_buf->buf); 525 } 526