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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <libintl.h> 28 #include <sys/varargs.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <alist.h> 33 #include <debug.h> 34 #include <_debug.h> 35 #include <msg.h> 36 37 /* 38 * Define a debug descriptor. Note, although this provides the default 39 * definition to which most users bind, ld.so.1 must provide its own definition, 40 * and thus interposition is expected. This item should be defined NODIRECT. 41 */ 42 static Dbg_desc _dbg_desc = { 0, 0, NULL, { 0, 0 }, { 0, 0 } }; 43 Dbg_desc *dbg_desc = &_dbg_desc; 44 45 int _Dbg_cnt = 0; 46 47 /* 48 * Debugging initialization and processing. The dbg_options[] array defines 49 * a set of option strings that can be specified using the -D flag or from an 50 * environment variable. For each option, a class is enabled in the d_class 51 * bit mask, or an extra flag is enabled in the d_extra bit mask. 52 */ 53 static DBG_options _Dbg_options[] = { /* Options accepted by both linkers */ 54 {MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL}, 55 {MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG}, 56 {MSG_ORIG(MSG_TOK_HELP), 0, DBG_E_HELP}, 57 {MSG_ORIG(MSG_TOK_TTIME), 0, DBG_E_TTIME}, 58 {MSG_ORIG(MSG_TOK_DTIME), 0, DBG_E_DTIME}, 59 60 {MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL & ~DBG_C_DEMANGLE, 0}, 61 {MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0}, 62 {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, 63 {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, 64 {MSG_ORIG(MSG_TOK_FILES), DBG_C_FILES, 0}, 65 {MSG_ORIG(MSG_TOK_LIBS), DBG_C_LIBS, 0}, 66 {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, 67 {MSG_ORIG(MSG_TOK_RELOC), DBG_C_RELOC, 0}, 68 {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_C_SYMBOLS, 0}, 69 {MSG_ORIG(MSG_TOK_TLS), DBG_C_TLS, 0}, 70 {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, 71 {MSG_ORIG(MSG_TOK_VERSIONS), DBG_C_VERSIONS, 0}, 72 {NULL, 0, 0}, 73 }; 74 75 static DBG_options _Dbg_options_ld[] = { /* ld only options */ 76 {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, 77 {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, 78 {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, 79 80 {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, 81 {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, 82 {MSG_ORIG(MSG_TOK_GOT), DBG_C_GOT, 0}, 83 {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, 84 {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, 85 {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, 86 {MSG_ORIG(MSG_TOK_STATS), DBG_C_STATS, 0}, 87 {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, 88 {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, 89 {NULL, 0, 0}, 90 }; 91 92 static DBG_options _Dbg_options_rtld[] = { /* ld.so.1 only options */ 93 {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, 94 {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, 95 {MSG_ORIG(MSG_TOK_CALLBACK), DBG_C_CALLBACK, 0}, 96 {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, 97 {NULL, 0, 0}, 98 }; 99 100 /* 101 * Compare name to the options found in optarr. If one matches, 102 * update *dbp and return TRUE. Otherwise, FALSE. 103 */ 104 static Boolean 105 process_options(const char *name, Boolean set, Dbg_desc *dbp, 106 DBG_options *optarr) 107 { 108 DBG_options *opt; 109 110 for (opt = optarr; opt->o_name != NULL; opt++) { 111 if (strcmp(name, opt->o_name) != 0) 112 continue; 113 114 if (set == TRUE) { 115 if (opt->o_class) 116 dbp->d_class |= opt->o_class; 117 if (opt->o_extra) 118 dbp->d_extra |= opt->o_extra; 119 } else { 120 if (opt->o_class) 121 dbp->d_class &= ~(opt->o_class); 122 if (opt->o_extra) 123 dbp->d_extra &= ~(opt->o_extra); 124 } 125 return (TRUE); 126 } 127 128 return (FALSE); 129 } 130 131 /* 132 * Provide a debugging usage message 133 */ 134 void 135 Dbg_help(void) 136 { 137 Dbg_util_nl(0, DBG_NL_STD); 138 dbg_print(0, MSG_INTL(MSG_USE_R1_A)); 139 dbg_print(0, MSG_INTL(MSG_USE_R1_B)); 140 dbg_print(0, MSG_INTL(MSG_USE_R1_C)); 141 dbg_print(0, MSG_INTL(MSG_USE_R1_D)); 142 dbg_print(0, MSG_INTL(MSG_USE_R1_E)); 143 dbg_print(0, MSG_INTL(MSG_USE_R1_F)); 144 dbg_print(0, MSG_INTL(MSG_USE_R1_G)); 145 146 Dbg_util_nl(0, DBG_NL_FRC); 147 dbg_print(0, MSG_INTL(MSG_USE_R2_A)); 148 dbg_print(0, MSG_INTL(MSG_USE_R2_B)); 149 dbg_print(0, MSG_INTL(MSG_USE_R2_C)); 150 dbg_print(0, MSG_INTL(MSG_USE_R2_D)); 151 dbg_print(0, MSG_INTL(MSG_USE_R2_E)); 152 dbg_print(0, MSG_INTL(MSG_USE_R2_F)); 153 dbg_print(0, MSG_INTL(MSG_USE_R2_G)); 154 dbg_print(0, MSG_INTL(MSG_USE_R2_H)); 155 dbg_print(0, MSG_INTL(MSG_USE_R2_I)); 156 dbg_print(0, MSG_INTL(MSG_USE_R2_J)); 157 dbg_print(0, MSG_INTL(MSG_USE_R2_K)); 158 dbg_print(0, MSG_INTL(MSG_USE_R2_L)); 159 dbg_print(0, MSG_INTL(MSG_USE_R2_M)); 160 dbg_print(0, MSG_INTL(MSG_USE_R2_N)); 161 dbg_print(0, MSG_INTL(MSG_USE_R2_O)); 162 dbg_print(0, MSG_INTL(MSG_USE_R2_P)); 163 dbg_print(0, MSG_INTL(MSG_USE_R2_Q)); 164 165 Dbg_util_nl(0, DBG_NL_FRC); 166 dbg_print(0, MSG_INTL(MSG_USE_R2_R)); 167 dbg_print(0, MSG_INTL(MSG_USE_R2_S)); 168 dbg_print(0, MSG_INTL(MSG_USE_R2_T)); 169 dbg_print(0, MSG_INTL(MSG_USE_R2_U)); 170 dbg_print(0, MSG_INTL(MSG_USE_R2_V)); 171 dbg_print(0, MSG_INTL(MSG_USE_R2_W)); 172 173 Dbg_util_nl(0, DBG_NL_FRC); 174 dbg_print(0, MSG_INTL(MSG_USE_R3_A)); 175 dbg_print(0, MSG_INTL(MSG_USE_R3_B)); 176 dbg_print(0, MSG_INTL(MSG_USE_R3_C)); 177 dbg_print(0, MSG_INTL(MSG_USE_R3_D)); 178 dbg_print(0, MSG_INTL(MSG_USE_R3_E)); 179 dbg_print(0, MSG_INTL(MSG_USE_R3_F)); 180 dbg_print(0, MSG_INTL(MSG_USE_R3_G)); 181 182 Dbg_util_nl(0, DBG_NL_FRC); 183 dbg_print(0, MSG_INTL(MSG_USE_R3_H)); 184 dbg_print(0, MSG_INTL(MSG_USE_R3_F)); 185 dbg_print(0, MSG_INTL(MSG_USE_R3_I)); 186 dbg_print(0, MSG_INTL(MSG_USE_R3_J)); 187 dbg_print(0, MSG_INTL(MSG_USE_R3_K)); 188 dbg_print(0, MSG_INTL(MSG_USE_R3_L)); 189 dbg_print(0, MSG_INTL(MSG_USE_R3_M)); 190 191 Dbg_util_nl(0, DBG_NL_FRC); 192 dbg_print(0, MSG_INTL(MSG_USE_R3_N)); 193 194 Dbg_util_nl(0, DBG_NL_FRC); 195 dbg_print(0, MSG_INTL(MSG_USE_HDR_DCT)); 196 dbg_print(0, MSG_INTL(MSG_USE_HDR_BOTH)); 197 dbg_print(0, MSG_INTL(MSG_USE_R4_A)); 198 dbg_print(0, MSG_INTL(MSG_USE_R4_B)); 199 dbg_print(0, MSG_INTL(MSG_USE_R4_B2)); 200 dbg_print(0, MSG_INTL(MSG_USE_R4_C)); 201 dbg_print(0, MSG_INTL(MSG_USE_R4_C2)); 202 dbg_print(0, MSG_INTL(MSG_USE_R4_C3)); 203 dbg_print(0, MSG_INTL(MSG_USE_R4_D)); 204 dbg_print(0, MSG_INTL(MSG_USE_R4_E)); 205 dbg_print(0, MSG_INTL(MSG_USE_R4_E2)); 206 dbg_print(0, MSG_INTL(MSG_USE_R4_E3)); 207 dbg_print(0, MSG_INTL(MSG_USE_R4_F)); 208 dbg_print(0, MSG_INTL(MSG_USE_R4_F2)); 209 dbg_print(0, MSG_INTL(MSG_USE_R4_F3)); 210 dbg_print(0, MSG_INTL(MSG_USE_R4_F4)); 211 dbg_print(0, MSG_INTL(MSG_USE_R4_F5)); 212 dbg_print(0, MSG_INTL(MSG_USE_R4_F6)); 213 214 Dbg_util_nl(0, DBG_NL_FRC); 215 dbg_print(0, MSG_INTL(MSG_USE_HDR_RTLD)); 216 dbg_print(0, MSG_INTL(MSG_USE_R5_A)); 217 dbg_print(0, MSG_INTL(MSG_USE_R5_A2)); 218 dbg_print(0, MSG_INTL(MSG_USE_R5_A3)); 219 dbg_print(0, MSG_INTL(MSG_USE_R5_A4)); 220 dbg_print(0, MSG_INTL(MSG_USE_R5_A5)); 221 dbg_print(0, MSG_INTL(MSG_USE_R5_A6)); 222 dbg_print(0, MSG_INTL(MSG_USE_R5_A7)); 223 dbg_print(0, MSG_INTL(MSG_USE_R5_A8)); 224 dbg_print(0, MSG_INTL(MSG_USE_R5_A9)); 225 dbg_print(0, MSG_INTL(MSG_USE_R5_A0)); 226 dbg_print(0, MSG_INTL(MSG_USE_R5_B)); 227 dbg_print(0, MSG_INTL(MSG_USE_R5_C)); 228 dbg_print(0, MSG_INTL(MSG_USE_R5_D)); 229 dbg_print(0, MSG_INTL(MSG_USE_R5_E)); 230 dbg_print(0, MSG_INTL(MSG_USE_R5_F)); 231 232 Dbg_util_nl(0, DBG_NL_FRC); 233 dbg_print(0, MSG_INTL(MSG_USE_HDR_LD)); 234 dbg_print(0, MSG_INTL(MSG_USE_R6_A)); 235 dbg_print(0, MSG_INTL(MSG_USE_R6_B)); 236 dbg_print(0, MSG_INTL(MSG_USE_R6_C)); 237 dbg_print(0, MSG_INTL(MSG_USE_R6_C2)); 238 239 Dbg_util_nl(0, DBG_NL_FRC); 240 dbg_print(0, MSG_INTL(MSG_USE_HDR_CST)); 241 dbg_print(0, MSG_INTL(MSG_USE_HDR_BOTH)); 242 dbg_print(0, MSG_INTL(MSG_USE_R7_A)); 243 dbg_print(0, MSG_INTL(MSG_USE_R7_B)); 244 dbg_print(0, MSG_INTL(MSG_USE_R7_C)); 245 dbg_print(0, MSG_INTL(MSG_USE_R7_D)); 246 dbg_print(0, MSG_INTL(MSG_USE_R7_E)); 247 dbg_print(0, MSG_INTL(MSG_USE_R7_F)); 248 dbg_print(0, MSG_INTL(MSG_USE_R7_F2)); 249 dbg_print(0, MSG_INTL(MSG_USE_R7_G)); 250 dbg_print(0, MSG_INTL(MSG_USE_R7_H)); 251 dbg_print(0, MSG_INTL(MSG_USE_R7_I)); 252 dbg_print(0, MSG_INTL(MSG_USE_R7_I2)); 253 dbg_print(0, MSG_INTL(MSG_USE_R7_J)); 254 dbg_print(0, MSG_INTL(MSG_USE_R7_K)); 255 dbg_print(0, MSG_INTL(MSG_USE_R7_K2)); 256 dbg_print(0, MSG_INTL(MSG_USE_R7_L)); 257 258 Dbg_util_nl(0, DBG_NL_FRC); 259 dbg_print(0, MSG_INTL(MSG_USE_HDR_RTLD)); 260 dbg_print(0, MSG_INTL(MSG_USE_R8_A)); 261 dbg_print(0, MSG_INTL(MSG_USE_R8_B)); 262 dbg_print(0, MSG_INTL(MSG_USE_R8_B2)); 263 dbg_print(0, MSG_INTL(MSG_USE_R8_C)); 264 dbg_print(0, MSG_INTL(MSG_USE_R8_C2)); 265 dbg_print(0, MSG_INTL(MSG_USE_R8_D)); 266 267 Dbg_util_nl(0, DBG_NL_FRC); 268 dbg_print(0, MSG_INTL(MSG_USE_HDR_LD)); 269 dbg_print(0, MSG_INTL(MSG_USE_R9_A)); 270 dbg_print(0, MSG_INTL(MSG_USE_R9_B)); 271 dbg_print(0, MSG_INTL(MSG_USE_R9_C)); 272 dbg_print(0, MSG_INTL(MSG_USE_R9_D)); 273 dbg_print(0, MSG_INTL(MSG_USE_R9_E)); 274 dbg_print(0, MSG_INTL(MSG_USE_R9_F)); 275 dbg_print(0, MSG_INTL(MSG_USE_R9_F2)); 276 dbg_print(0, MSG_INTL(MSG_USE_R9_G)); 277 dbg_print(0, MSG_INTL(MSG_USE_R9_H)); 278 dbg_print(0, MSG_INTL(MSG_USE_R9_H2)); 279 dbg_print(0, MSG_INTL(MSG_USE_R9_I)); 280 281 Dbg_util_nl(0, DBG_NL_FRC); 282 } 283 284 /* 285 * Provide a debugging message showing the version of the linker package 286 */ 287 void 288 Dbg_version(void) 289 { 290 Dbg_util_nl(0, DBG_NL_STD); 291 dbg_print(0, MSG_ORIG(MSG_STR_LDVER), link_ver_string); 292 Dbg_util_nl(0, DBG_NL_STD); 293 } 294 295 /* 296 * Messaging support - funnel everything through dgettext() as this provides 297 * the real binding to libc. 298 */ 299 const char * 300 _liblddbg_msg(Msg mid) 301 { 302 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 303 } 304 305 /* 306 * Given a name starting with "lmid", finish processing it. Return TRUE 307 * if a valid lmid token was seen, and FALSE for any error. 308 * 309 * exit: 310 * On failure, returns FALSE, indicating a syntax error 311 * 312 * On success: 313 * - Appropriate flags in dbg->d_extra have been set 314 * - Any link-map list names specified have been added to 315 * d_list, for the rtld dbg_print() to compare against 316 * link-map list names. 317 * - TRUE is returned. 318 */ 319 static Boolean 320 process_lmid(char *name, Dbg_desc *dbp) 321 { 322 /* 323 * "lmid" can have an optional argument. Allowed values are "all", 324 * "alt[0-9]+", "base", or "ldso". Alt has a variable ending, but 325 * we can use process_options() to handle the other three. 326 */ 327 static DBG_options options_lmid[] = { 328 {MSG_ORIG(MSG_TOK_LMID_ALL), 0, DBG_E_LMID_ALL}, 329 {MSG_ORIG(MSG_TOK_LMID_BASE), 0, DBG_E_LMID_BASE}, 330 {MSG_ORIG(MSG_TOK_LMID_LDSO), 0, DBG_E_LMID_LDSO}, 331 {NULL, NULL}, 332 }; 333 334 Dbg_desc tmp_db; 335 const char *lmid_opt; 336 337 /* If it's a plain "lmid", we can set the flag and return now */ 338 if (name[MSG_TOK_LMID_SIZE] == '\0') { 339 dbp->d_extra |= DBG_E_LMID; 340 return (TRUE); 341 } 342 343 /* If there's no value, its an error */ 344 if (conv_strproc_extract_value(name, MSG_TOK_LMID_SIZE, 345 CONV_SPEXV_F_UCASE, &lmid_opt) == 0) 346 return (FALSE); 347 348 /* 349 * ALL, BASE, or LDSO? 350 */ 351 tmp_db.d_extra = 0; 352 if (process_options(lmid_opt, TRUE, &tmp_db, options_lmid)) { 353 /* 354 * If BASE, and we haven't already seen it, add it to the 355 * rtld name matching list. For the others, setting the 356 * e_extra bit suffices. 357 */ 358 if (((tmp_db.d_extra & DBG_E_LMID_BASE) != 0) && 359 ((dbp->d_extra & DBG_E_LMID_BASE) == 0) && 360 (aplist_append(&dbp->d_list, MSG_ORIG(MSG_TOK_LMID_BASE), 361 AL_CNT_DEBUG) == NULL)) 362 return (FALSE); 363 364 /* Add the resulting flags into the callers descriptor */ 365 dbp->d_extra |= DBG_E_LMID | tmp_db.d_extra; 366 return (TRUE); 367 } 368 369 /* 370 * ALT? 371 */ 372 if (strncmp(lmid_opt, MSG_ORIG(MSG_TOK_LMID_ALT), 373 MSG_TOK_LMID_ALT_SIZE) == 0) { 374 const char *tail = lmid_opt + MSG_TOK_LMID_ALT_SIZE; 375 376 /* 'ALT' without a # means "all alternative link-map lists" */ 377 if (*tail == '\0') { 378 dbp->d_extra |= DBG_E_LMID | DBG_E_LMID_ALT; 379 return (TRUE); 380 } 381 382 /* 383 * It is ALT[0-9]+. Make sure the characters following 'ALT' 384 * are numbers, and then add it to the rtld name matching list. 385 */ 386 for (; *tail; tail++) 387 if ((*tail < '0') || (*tail > '9')) 388 return (FALSE); 389 390 if (aplist_append(&dbp->d_list, lmid_opt, AL_CNT_DEBUG) == NULL) 391 return (FALSE); 392 dbp->d_extra |= DBG_E_LMID; 393 return (TRUE); 394 } 395 396 /* It's nothing we recognize */ 397 return (FALSE); 398 } 399 400 /* 401 * Validate and enable the appropriate debugging classes. 402 * 403 * entry: 404 * string - String to be analyzed for debugging options 405 * dbp - Pointer to debug descriptor to be initialized 406 * outfile_ret - NULL, or pointer to receive result of 'output=' 407 * token. A NULL value means that the 'output=' token 408 * is not accepted. A non-NULL value means that it is. 409 * 410 * exit: 411 * On failure, False (0) is returned. 412 * 413 * On success, string has been parsed, and the descriptor referenced 414 * by dbp has been initialized. If outfile is non-NULL, *outfile will 415 * be set to NULL if the 'output=' token is not present, and to the 416 * user supplied string otherwise. True (1) is returned. 417 */ 418 int 419 Dbg_setup(dbg_setup_caller_t caller, const char *string, Dbg_desc *dbp, 420 const char **outfile) 421 { 422 char *name, *_name; /* buffer in which to perform */ 423 /* strtok_r() operations. */ 424 char *lasts; 425 const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 426 427 /* 428 * Clear the help flags --- these items only apply for a single 429 * call to Dbg_setup(). 430 */ 431 dbp->d_extra &= ~(DBG_E_HELP | DBG_E_HELP_EXIT); 432 433 if ((_name = (char *)malloc(strlen(string) + 1)) == NULL) 434 return (0); 435 (void) strcpy(_name, string); 436 437 if (outfile) 438 *outfile = NULL; /* No output file yet */ 439 440 /* 441 * The token should be of the form "-Dtok,tok,tok,...". Separate the 442 * pieces and build up the appropriate mask, unrecognized options are 443 * flagged. 444 */ 445 if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 446 do { 447 Boolean set; 448 449 /* Remove leading and trailing whitespace */ 450 name = conv_strproc_trim(name); 451 452 if (name[0] == '!') { 453 set = FALSE; 454 name++; 455 } else 456 set = TRUE; 457 458 if (*name == '\0') 459 continue; /* Skip null token */ 460 461 /* 462 * First, determine if the token represents a class or 463 * extra. 464 */ 465 if (process_options(name, set, dbp, _Dbg_options)) 466 continue; 467 switch (caller) { 468 case DBG_CALLER_LD: /* ld only tokens */ 469 if (process_options(name, set, dbp, 470 _Dbg_options_ld)) 471 continue; 472 break; 473 case DBG_CALLER_RTLD: /* rtld only tokens */ 474 if (process_options(name, set, dbp, 475 _Dbg_options_rtld)) 476 continue; 477 break; 478 } 479 480 /* The remaining options do not accept negation */ 481 if (!set) { 482 dbg_print(0, MSG_INTL(MSG_USE_CNTNEGOPT), name); 483 continue; 484 } 485 486 /* 487 * Is it an 'output=' token? This item is a special 488 * case because it depends on the presence of 489 * a non-NULL outfile argument, and because the 490 * part following the '=' is variable. 491 */ 492 if ((outfile != NULL) && 493 strncmp(name, MSG_ORIG(MSG_TOK_OUTFILE), 494 MSG_TOK_OUTFILE_SIZE) == 0) { 495 if (conv_strproc_extract_value(name, 496 MSG_TOK_OUTFILE_SIZE, 0, outfile)) 497 continue; 498 } 499 500 /* 501 * Only the rtld "lmid" token is left. 502 */ 503 if ((caller == DBG_CALLER_RTLD) && (strncmp(name, 504 MSG_ORIG(MSG_TOK_LMID), MSG_TOK_LMID_SIZE) == 0) && 505 process_lmid(name, dbp)) 506 continue; 507 508 /* If we make it here, the token is not understood */ 509 dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); 510 511 } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 512 } 513 514 /* 515 * If the debug help option was specified and this is the only debug 516 * class, return an indication that the user should exit. 517 */ 518 if ((_Dbg_cnt++ == 0) && (dbp->d_extra & DBG_E_HELP) && 519 (dbp->d_class == 0)) 520 dbp->d_extra |= DBG_E_HELP_EXIT; 521 522 return (1); 523 } 524 525 /* 526 * Define our own printing routine. This provides a basic fallback, as ld(1) 527 * and ld.so.1(1) provide their own routines that augment their diagnostic 528 * output, and direct the output to stderr. This item should be defined 529 * NODIRECT. 530 */ 531 /* PRINTFLIKE2 */ 532 void 533 dbg_print(Lm_list *lml, const char *format, ...) 534 { 535 va_list ap; 536 537 #if defined(lint) 538 /* 539 * The lml argument is only meaningful for diagnostics sent to ld.so.1. 540 * Supress the lint error by making a dummy assignment. 541 */ 542 lml = 0; 543 #endif 544 va_start(ap, format); 545 (void) vprintf(format, ap); 546 (void) printf(MSG_ORIG(MSG_STR_NL)); 547 va_end(ap); 548 } 549 550 /* 551 * Return an internationalized state transition string. These are used by 552 * various debugging output. 553 */ 554 const char * 555 Dbg_state_str(dbg_state_t type) 556 { 557 static const Msg state[DBG_STATE_NUM] = { 558 MSG_STR_ADD, /* MSG_INTL(MSG_STR_ADD) */ 559 MSG_STR_CURRENT, /* MSG_INTL(MSG_STR_CURRENT) */ 560 MSG_STR_EXCLUDE, /* MSG_INTL(MSG_STR_EXCLUDE) */ 561 MSG_STR_IGNORE, /* MSG_INTL(MSG_STR_IGNORE) */ 562 MSG_STR_MOD_BEFORE, /* MSG_INTL(MSG_STR_MOD_BEFORE) */ 563 MSG_STR_MOD_AFTER, /* MSG_INTL(MSG_STR_MOD_AFTER) */ 564 MSG_STR_NEW, /* MSG_INTL(MSG_STR_NEW) */ 565 MSG_STR_NEW_IMPLICIT, /* MSG_INTL(MSG_STR_NEW_IMPLICIT) */ 566 MSG_STR_RESET, /* MSG_INTL(MSG_STR_RESET) */ 567 MSG_STR_ORIGINAL, /* MSG_INTL(MSG_STR_ORIGINAL) */ 568 MSG_STR_RESOLVED, /* MSG_INTL(MSG_STR_RESOLVED) */ 569 }; 570 #if DBG_STATE_NUM != (DBG_STATE_RESOLVED + 1) 571 #error DBG_SEG_NUM has changed. Update segtype[] 572 #endif 573 574 assert(type < DBG_STATE_NUM); 575 return (MSG_INTL(state[type])); 576 } 577