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 (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 1988 AT&T 28 * All Rights Reserved 29 */ 30 31 /* 32 * Copyright (c) 2018, Joyent, Inc. 33 */ 34 35 /* 36 * Utility functions 37 */ 38 #include <unistd.h> 39 #include <stdio.h> 40 #include <stdarg.h> 41 #include <string.h> 42 #include <fcntl.h> 43 #include <sys/types.h> 44 #include <sys/mman.h> 45 #include <errno.h> 46 #include <sgs.h> 47 #include <libintl.h> 48 #include <debug.h> 49 #include "msg.h" 50 #include "_libld.h" 51 52 /* 53 * libld_malloc() and dz_map() are used for both performance and for ease of 54 * programming: 55 * 56 * Performance: 57 * The link-edit is a short lived process which doesn't really free much 58 * of the dynamic memory that it requests. Because of this, it is more 59 * important to optimize for quick memory allocations than the 60 * re-usability of the memory. 61 * 62 * By also mmaping blocks of pages in from /dev/zero we don't need to 63 * waste the overhead of zeroing out these pages for calloc() requests. 64 * 65 * Memory Management: 66 * By doing all libld memory management through the ld_malloc routine 67 * it's much easier to free up all memory at the end by simply unmaping 68 * all of the blocks that were mapped in through dz_map(). This is much 69 * simpler then trying to track all of the libld structures that were 70 * dynamically allocate and are actually pointers into the ELF files. 71 * 72 * It's important that we can free up all of our dynamic memory because 73 * libld is used by ld.so.1 when it performs dlopen()'s of relocatable 74 * objects. 75 * 76 * Format: 77 * The memory blocks for each allocation store the size of the allocation 78 * in the first 8 bytes of the block. The pointer that is returned by 79 * libld_malloc() is actually the address of (block + 8): 80 * 81 * (addr - 8) block_size 82 * (addr) <allocated block> 83 * 84 * The size is retained in order to implement realloc(), and to perform 85 * the required memcpy(). 8 bytes are uses, as the memory area returned 86 * by libld_malloc() must be 8 byte-aligned. Even in a 32-bit environment, 87 * u_longlog_t pointers are employed. 88 * 89 * Map anonymous memory via MAP_ANON (added in Solaris 8). 90 */ 91 static void * 92 dz_map(size_t size) 93 { 94 void *addr; 95 96 if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), 97 (MAP_PRIVATE | MAP_ANON), -1, 0)) == MAP_FAILED) { 98 int err = errno; 99 eprintf(NULL, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON), 100 strerror(err)); 101 return (MAP_FAILED); 102 } 103 return (addr); 104 } 105 106 void * 107 libld_malloc(size_t size) 108 { 109 Ld_heap *chp = ld_heap; 110 void *vptr; 111 size_t asize = size + HEAPALIGN; 112 113 /* 114 * If this is the first allocation, or the allocation request is greater 115 * than the current free space available, allocate a new heap. 116 */ 117 if ((chp == NULL) || 118 (((size_t)chp->lh_end - (size_t)chp->lh_free) <= asize)) { 119 Ld_heap *nhp; 120 size_t hsize = (size_t)S_ROUND(sizeof (Ld_heap), HEAPALIGN); 121 size_t tsize = (size_t)S_ROUND((asize + hsize), HEAPALIGN); 122 123 /* 124 * Allocate a block that is at minimum 'HEAPBLOCK' size 125 */ 126 if (tsize < HEAPBLOCK) 127 tsize = HEAPBLOCK; 128 129 if ((nhp = dz_map(tsize)) == MAP_FAILED) 130 return (NULL); 131 132 nhp->lh_next = chp; 133 nhp->lh_free = (void *)((size_t)nhp + hsize); 134 nhp->lh_end = (void *)((size_t)nhp + tsize); 135 136 ld_heap = chp = nhp; 137 } 138 vptr = chp->lh_free; 139 140 /* 141 * Assign size to head of allocated block (used by realloc), and 142 * memory arena as then next 8-byte aligned offset. 143 */ 144 *((size_t *)vptr) = size; 145 vptr = (void *)((size_t)vptr + HEAPALIGN); 146 147 /* 148 * Increment free to point to next available block 149 */ 150 chp->lh_free = (void *)S_ROUND((size_t)chp->lh_free + asize, 151 HEAPALIGN); 152 153 return (vptr); 154 } 155 156 void * 157 libld_realloc(void *ptr, size_t size) 158 { 159 size_t psize; 160 void *vptr; 161 162 if (ptr == NULL) 163 return (libld_malloc(size)); 164 165 /* 166 * Size of the allocated blocks is stored *just* before the blocks 167 * address. 168 */ 169 psize = *((size_t *)((size_t)ptr - HEAPALIGN)); 170 171 /* 172 * If the block actually fits then just return. 173 */ 174 if (size <= psize) 175 return (ptr); 176 177 if ((vptr = libld_malloc(size)) != NULL) 178 (void) memcpy(vptr, ptr, psize); 179 180 return (vptr); 181 } 182 183 void 184 /* ARGSUSED 0 */ 185 libld_free(void *ptr) 186 { 187 } 188 189 /* 190 * Determine if a shared object definition structure already exists and if 191 * not create one. These definitions provide for recording information 192 * regarding shared objects that are still to be processed. Once processed 193 * shared objects are maintained on the ofl_sos list. The information 194 * recorded in this structure includes: 195 * 196 * o DT_USED requirements. In these cases definitions are added during 197 * mapfile processing of `-' entries (see map_dash()). 198 * 199 * o implicit NEEDED entries. As shared objects are processed from the 200 * command line so any of their dependencies are recorded in these 201 * structures for later processing (see process_dynamic()). 202 * 203 * o version requirements. Any explicit shared objects that have version 204 * dependencies on other objects have their version requirements recorded. 205 * In these cases definitions are added during mapfile processing of `-' 206 * entries (see map_dash()). Also, shared objects may have versioning 207 * requirements on their NEEDED entries. These cases are added during 208 * their version processing (see vers_need_process()). 209 * 210 * Note: Both process_dynamic() and vers_need_process() may generate the 211 * initial version definition structure because you can't rely on what 212 * section (.dynamic or .SUNW_version) may be processed first from any 213 * input file. 214 */ 215 Sdf_desc * 216 sdf_find(const char *name, APlist *alp) 217 { 218 Aliste idx; 219 Sdf_desc *sdf; 220 221 for (APLIST_TRAVERSE(alp, idx, sdf)) 222 if (strcmp(name, sdf->sdf_name) == 0) 223 return (sdf); 224 225 return (NULL); 226 } 227 228 Sdf_desc * 229 sdf_add(const char *name, APlist **alpp) 230 { 231 Sdf_desc *sdf; 232 233 if ((sdf = libld_calloc(sizeof (Sdf_desc), 1)) == NULL) 234 return ((Sdf_desc *)S_ERROR); 235 236 sdf->sdf_name = name; 237 238 if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL) 239 return ((Sdf_desc *)S_ERROR); 240 241 return (sdf); 242 } 243 244 /* 245 * Add a string, separated by a colon, to an existing string. Typically used 246 * to maintain filter, rpath and audit names, of which there is normally only 247 * one string supplied anyway. 248 */ 249 char * 250 add_string(char *old, char *str) 251 { 252 char *new; 253 254 if (old) { 255 char *_str; 256 size_t len; 257 258 /* 259 * If an original string exists, make sure this new string 260 * doesn't get duplicated. 261 */ 262 if ((_str = strstr(old, str)) != NULL) { 263 if (((_str == old) || 264 (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) && 265 (_str += strlen(str)) && 266 ((*_str == '\0') || 267 (*_str == *(MSG_ORIG(MSG_STR_COLON))))) 268 return (old); 269 } 270 271 len = strlen(old) + strlen(str) + 2; 272 if ((new = libld_calloc(1, len)) == NULL) 273 return ((char *)S_ERROR); 274 (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str); 275 } else { 276 if ((new = libld_malloc(strlen(str) + 1)) == NULL) 277 return ((char *)S_ERROR); 278 (void) strcpy(new, str); 279 } 280 281 return (new); 282 } 283 284 /* 285 * The GNU ld '-wrap=XXX' and '--wrap=XXX' options correspond to our 286 * '-z wrap=XXX'. When str2chr() does this conversion, we end up with 287 * the return character set to 'z' and optarg set to 'XXX'. This callback 288 * changes optarg to include the missing wrap= prefix. 289 * 290 * exit: 291 * Returns c on success, or '?' on error. 292 */ 293 static int 294 str2chr_wrap_cb(int c) 295 { 296 char *str; 297 size_t len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1; 298 299 if ((str = libld_malloc(len)) == NULL) 300 return ('?'); 301 (void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT), 302 MSG_ORIG(MSG_ARG_WRAP), optarg); 303 optarg = str; 304 return (c); 305 } 306 307 /* 308 * Determine whether this string, possibly with an associated option, should 309 * be translated to an option character. If so, update the optind and optarg 310 * and optopt as described for short options in getopt(3c). 311 * 312 * entry: 313 * lml - Link map list for debug messages 314 * ndx - Starting optind for current item 315 * argc, argv - Command line arguments 316 * arg - Option to be examined 317 * c, opt - Option character (c) and corresponding long name (opt) 318 * optsz - 0 if option does not accept a value. If option does 319 * accept a value, strlen(opt), giving the offset to the 320 * value if the option and value are combined in one string. 321 * cbfunc - NULL, or pointer to function to call if a translation is 322 * successful. 323 */ 324 static int 325 str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c, 326 const char *opt, size_t optsz, int (*cbfunc)(int)) 327 { 328 if (optsz == 0) { 329 /* 330 * Compare a single option (ie. there's no associated option 331 * argument). 332 */ 333 if (strcmp(arg, opt) == 0) { 334 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c)); 335 optind += 1; 336 optopt = c; 337 return (c); 338 } 339 } else if ((strcmp(arg, opt) == 0) || 340 ((arg[optsz] == '=') && strncmp(arg, opt, optsz) == 0)) { 341 /* 342 * Otherwise, compare the option name, which may be 343 * concatenated with the option argument. 344 */ 345 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c)); 346 347 if (arg[optsz] == '\0') { 348 /* 349 * Optarg is the next argument (white space separated). 350 * Make sure an optarg is available, and if not return 351 * a failure to prevent any fall-through to the generic 352 * getopt() processing. 353 * 354 * Since we'll be completely failing this option we 355 * don't want to update optopt with the translation, 356 * but also need to set it to _something_. Setting it 357 * to the '-' of the argument causes us to behave 358 * correctly. 359 */ 360 if ((++optind + 1) > argc) { 361 optopt = arg[0]; 362 return ('?'); 363 } 364 optarg = argv[optind]; 365 optind++; 366 } else { 367 /* 368 * GNU option/option argument pairs can be represented 369 * with a "=" separator. If this is the case, remove 370 * the separator. 371 */ 372 optarg = &arg[optsz]; 373 optind++; 374 if (*optarg == '=') { 375 if (*(++optarg) == '\0') { 376 optopt = arg[0]; 377 return ('?'); 378 } 379 } 380 } 381 382 if (cbfunc != NULL) 383 c = (*cbfunc)(c); 384 optopt = c; 385 return (c); 386 } 387 return (0); 388 } 389 390 /* 391 * Parse an individual option. The intent of this function is to determine if 392 * any known, non-Solaris options have been passed to ld(1). This condition 393 * can occur as a result of build configuration tools, because of users 394 * familiarity with other systems, or simply the users preferences. If a known 395 * non-Solaris option can be determined, translate that option into the Solaris 396 * counterpart. 397 * 398 * This function will probably never be a complete solution, as new, non-Solaris 399 * options are discovered, their translation will have to be added. Other 400 * non-Solaris options are incompatible with the Solaris link-editor, and will 401 * never be recognized. We support what we can. 402 */ 403 int 404 ld_getopt(Lm_list *lml, int ndx, int argc, char **argv) 405 { 406 int c; 407 408 if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) { 409 char *arg = &argv[optind][1]; 410 411 switch (*arg) { 412 case 'r': 413 /* Translate -rpath <optarg> to -R <optarg> */ 414 if ((c = str2chr(lml, ndx, argc, argv, arg, 'R', 415 MSG_ORIG(MSG_ARG_T_RPATH), 416 MSG_ARG_T_RPATH_SIZE, NULL)) != 0) { 417 return (c); 418 } 419 break; 420 case 's': 421 /* Translate -shared to -G */ 422 if ((c = str2chr(lml, ndx, argc, argv, arg, 'G', 423 MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) { 424 return (c); 425 426 /* Translate -soname <optarg> to -h <optarg> */ 427 } else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h', 428 MSG_ORIG(MSG_ARG_T_SONAME), 429 MSG_ARG_T_SONAME_SIZE, NULL)) != 0) { 430 return (c); 431 } 432 break; 433 case 'w': 434 /* Translate -wrap to -z wrap= */ 435 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 436 MSG_ORIG(MSG_ARG_T_WRAP) + 1, 437 MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) { 438 return (c); 439 } 440 break; 441 case '(': 442 /* 443 * Translate -( to -z rescan-start 444 */ 445 if ((c = str2chr(lml, ndx, argc, argv, 446 arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) != 447 0) { 448 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START); 449 return (c); 450 } 451 break; 452 case ')': 453 /* 454 * Translate -) to -z rescan-end 455 */ 456 if ((c = str2chr(lml, ndx, argc, argv, 457 arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) != 458 0) { 459 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END); 460 return (c); 461 } 462 break; 463 case '-': 464 switch (*(arg + 1)) { 465 case 'a': 466 /* 467 * Translate --allow-multiple-definition to 468 * -zmuldefs 469 */ 470 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 471 MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) != 472 0) { 473 optarg = 474 (char *)MSG_ORIG(MSG_ARG_MULDEFS); 475 return (c); 476 477 /* 478 * Translate --auxiliary <optarg> to 479 * -f <optarg> 480 */ 481 } else if ((c = str2chr(lml, argc, ndx, argv, 482 arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR), 483 MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) { 484 return (c); 485 } 486 break; 487 case 'd': 488 /* 489 * Translate --dynamic-linker <optarg> to 490 * -I <optarg> 491 */ 492 if ((c = str2chr(lml, ndx, argc, argv, arg, 'I', 493 MSG_ORIG(MSG_ARG_T_INTERP), 494 MSG_ARG_T_INTERP_SIZE, NULL)) != 0) { 495 return (c); 496 } 497 break; 498 case 'e': 499 /* Translate --entry <optarg> to -e <optarg> */ 500 if ((c = str2chr(lml, ndx, argc, argv, arg, 'e', 501 MSG_ORIG(MSG_ARG_T_ENTRY), 502 MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) { 503 return (c); 504 } 505 /* 506 * Translate --end-group to -z rescan-end 507 */ 508 if ((c = str2chr(lml, ndx, argc, argv, 509 arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP), 510 0, NULL)) != 0) { 511 optarg = (char *) 512 MSG_ORIG(MSG_ARG_RESCAN_END); 513 return (c); 514 } 515 break; 516 case 'f': 517 /* 518 * Translate --fatal-warnings to 519 * -z fatal-warnings. 520 */ 521 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 522 MSG_ORIG(MSG_ARG_T_FATWARN), 523 0, NULL)) != 0) { 524 optarg = (char *) 525 MSG_ORIG(MSG_ARG_FATWARN); 526 return (c); 527 } 528 /* Translate --filter <optarg> to -F <optarg> */ 529 if ((c = str2chr(lml, ndx, argc, argv, arg, 'F', 530 MSG_ORIG(MSG_ARG_T_STDFLTR), 531 MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) { 532 return (c); 533 } 534 break; 535 case 'h': 536 /* Translate --help to -zhelp */ 537 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 538 MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) != 539 0) { 540 optarg = (char *)MSG_ORIG(MSG_ARG_HELP); 541 return (c); 542 } 543 break; 544 case 'l': 545 /* 546 * Translate --library <optarg> to -l <optarg> 547 */ 548 if ((c = str2chr(lml, ndx, argc, argv, arg, 'l', 549 MSG_ORIG(MSG_ARG_T_LIBRARY), 550 MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) { 551 return (c); 552 553 /* 554 * Translate --library-path <optarg> to 555 * -L <optarg> 556 */ 557 } else if ((c = str2chr(lml, ndx, argc, argv, 558 arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH), 559 MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) { 560 return (c); 561 } 562 break; 563 case 'n': 564 /* 565 * Translate --no-fatal-warnings to 566 * -z nofatal-warnings. 567 */ 568 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 569 MSG_ORIG(MSG_ARG_T_NOFATWARN), 570 0, NULL)) != 0) { 571 optarg = (char *) 572 MSG_ORIG(MSG_ARG_NOFATWARN); 573 return (c); 574 } 575 576 /* Translate --no-undefined to -zdefs */ 577 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 578 MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) != 579 0) { 580 optarg = (char *)MSG_ORIG(MSG_ARG_DEFS); 581 return (c); 582 583 /* 584 * Translate --no-whole-archive to 585 * -z defaultextract 586 */ 587 } else if ((c = str2chr(lml, ndx, argc, argv, 588 arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC), 589 0, NULL)) != 0) { 590 optarg = 591 (char *)MSG_ORIG(MSG_ARG_DFLEXTRT); 592 return (c); 593 } 594 break; 595 case 'o': 596 /* Translate --output <optarg> to -o <optarg> */ 597 if ((c = str2chr(lml, ndx, argc, argv, arg, 'o', 598 MSG_ORIG(MSG_ARG_T_OUTPUT), 599 MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) { 600 return (c); 601 } 602 break; 603 case 'r': 604 /* Translate --relocatable to -r */ 605 if ((c = str2chr(lml, ndx, argc, argv, arg, 'r', 606 MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0, 607 NULL)) != 0) { 608 return (c); 609 } 610 break; 611 case 's': 612 /* Translate --strip-all to -s */ 613 if ((c = str2chr(lml, ndx, argc, argv, arg, 's', 614 MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) != 615 0) { 616 return (c); 617 } 618 /* 619 * Translate --start-group to -z rescan-start 620 */ 621 if ((c = str2chr(lml, ndx, argc, argv, 622 arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP), 623 0, NULL)) != 0) { 624 optarg = (char *) 625 MSG_ORIG(MSG_ARG_RESCAN_START); 626 return (c); 627 } 628 break; 629 case 'u': 630 /* 631 * Translate --undefined <optarg> to 632 * -u <optarg> 633 */ 634 if ((c = str2chr(lml, ndx, argc, argv, arg, 'u', 635 MSG_ORIG(MSG_ARG_T_UNDEF), 636 MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) { 637 return (c); 638 } 639 break; 640 case 'v': 641 /* Translate --version to -V */ 642 if ((c = str2chr(lml, ndx, argc, argv, arg, 'V', 643 MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) != 644 0) { 645 return (c); 646 } 647 break; 648 case 'w': 649 /* 650 * Translate --whole-archive to -z alltextract 651 */ 652 if ((c = str2chr(lml, ndx, argc, argv, 653 arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC), 654 0, NULL)) != 0) { 655 optarg = 656 (char *)MSG_ORIG(MSG_ARG_ALLEXTRT); 657 return (c); 658 } 659 /* 660 * Translate --wrap to -z wrap= 661 */ 662 if ((c = str2chr(lml, ndx, argc, argv, 663 arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP), 664 MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) != 665 0) { 666 return (c); 667 } 668 break; 669 } 670 break; 671 } 672 } 673 674 if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) { 675 /* 676 * It is possible that a "-Wl," argument has been used to 677 * specify an option. This isn't advertized ld(1) syntax, but 678 * compiler drivers and configuration tools, have been known to 679 * pass this compiler option to ld(1). Strip off the "-Wl," 680 * prefix and pass the option through. 681 */ 682 if ((c == 'W') && (strncmp(optarg, 683 MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) { 684 DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg)); 685 c = optarg[MSG_ARG_T_WL_SIZE]; 686 optarg += MSG_ARG_T_WL_SIZE + 1; 687 } 688 } 689 690 return (c); 691 } 692 693 /* 694 * A compare routine for Isd_node AVL trees. 695 */ 696 int 697 isdavl_compare(const void *n1, const void *n2) 698 { 699 uint_t hash1, hash2; 700 const char *st1, *st2; 701 int rc; 702 703 hash1 = ((Isd_node *)n1)->isd_hash; 704 hash2 = ((Isd_node *)n2)->isd_hash; 705 706 if (hash1 > hash2) 707 return (1); 708 if (hash1 < hash2) 709 return (-1); 710 711 st1 = ((Isd_node *)n1)->isd_name; 712 st2 = ((Isd_node *)n2)->isd_name; 713 714 rc = strcmp(st1, st2); 715 if (rc > 0) 716 return (1); 717 if (rc < 0) 718 return (-1); 719 return (0); 720 } 721 722 /* 723 * Messaging support - funnel everything through dgettext(). 724 */ 725 const char * 726 _libld_msg(Msg mid) 727 { 728 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 729 } 730 731 /* 732 * Determine whether a symbol name should be demangled. 733 */ 734 const char * 735 demangle(const char *name) 736 { 737 if (demangle_flag) 738 return (Elf_demangle_name(name)); 739 else 740 return (name); 741 } 742 743 /* 744 * Compare a series of platform or machine hardware names. 745 */ 746 int 747 cap_names_match(Alist *alp1, Alist *alp2) 748 { 749 Capstr *capstr1; 750 Aliste idx1; 751 int match = 0; 752 Word nitems; 753 754 if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2)) 755 return (1); 756 757 for (ALIST_TRAVERSE(alp1, idx1, capstr1)) { 758 Capstr *capstr2; 759 Aliste idx2; 760 761 for (ALIST_TRAVERSE(alp2, idx2, capstr2)) { 762 if (strcmp(capstr1->cs_str, capstr2->cs_str)) 763 continue; 764 765 match++; 766 break; 767 } 768 } 769 770 if (nitems == match) 771 return (0); 772 773 return (1); 774 } 775