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